Java曲线拟合库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/878200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java curve fitting library
提问by Russell Leggett
I'm hoping to find a simple library that can take a series of 2 dimensional points and give me back a larger series of points that model the curve. Basically, I want to get the effect of curve fitting like this sample from JFreeChart:
我希望找到一个简单的库,它可以采用一系列二维点,并给我更多的模拟曲线的点。基本上,我想从 JFreeChart 获得像这个示例一样的曲线拟合效果:
The problem with JFreeChart is that the code does not provide this type of api. I even looked at the source and the algorithm is tightly coupled to the actual drawing.
JFreeChart 的问题是代码没有提供这种类型的 api。我什至查看了源代码,并且算法与实际绘图紧密耦合。
回答by jbasko
I've never done it, but a quick Google search revealed that Bezier curves are implemented in http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html
我从来没有做过,但快速的谷歌搜索显示贝塞尔曲线是在http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/QuadCurve2D.Double.html中实现的
Then, you can getPathIterator() from this curve and with that, according to what documentation says, you get the "coordinates of shape boundaries", which, i suppose, is what you are looking for.
然后,您可以从这条曲线中获取路径迭代器(),然后根据文档说明,您将获得“形状边界的坐标”,我想这就是您要寻找的。
回答by David Tonhofer
Apache Commons Mathhas a nice series of algorithms, in particular "SplineInterpolator", see the API docs
Apache Commons Math有一系列不错的算法,特别是“SplineInterpolator”,请参阅API 文档
An example in which we call the interpolation functions for alpha(x), beta(x) from Groovy:
我们在 Groovy 中调用 alpha(x)、beta(x) 的插值函数的示例:
package example.com
import org.apache.commons.math3.analysis.interpolation.SplineInterpolator
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction
import statec.Extrapolate.Value;
class Interpolate {
enum Value {
ALPHA, BETA
}
def static xValues = [
-284086,
-94784,
31446,
354837,
667782,
982191
]
def static alphaValues = [
71641,
78245,
80871,
94045,
105780,
119616
]
def static betaValues = [
95552,
103413,
108667,
128456,
144686,
171953
]
static def getValueByName(Value value, int i) {
def res
switch (value) {
case Value.ALPHA:
res = alphaValues[i]
break
case Value.BETA:
res = betaValues[i]
break
default:
assert false
}
return res
}
static PolynomialSplineFunction interpolate(Value value) {
def yValues = []
int i = 0
xValues.each {
def y = getValueByName(value, i++)
yValues << (y as Double)
}
SplineInterpolator spi = new SplineInterpolator()
return spi.interpolate(xValues as double[], yValues as double[])
}
static void main(def argv) {
//
// Create a map mapping a Value instance to its interpolating function
//
def interpolations = [:]
Value.values().each {
interpolations[it] = interpolate(it)
}
//
// Create an array of new x values to compute display.
// Make sure the last "original" value is in there!
// Note that the newxValues MUST stay within the range of the original xValues!
//
def newxValues = []
for (long x = xValues[0] ; x < xValues[-1] ; x+=25000) {
newxValues << x
}
newxValues << xValues[-1]
//
// Write interpolated values for ALPHA and BETA, adding the original values in columns 4 and 5
//
System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n"
int origIndex = 0
newxValues.each { long x ->
def alpha_ipol = interpolations[Value.ALPHA].value(x)
def beta_ipol = interpolations[Value.BETA].value(x)
String out = "${x} , ${alpha_ipol} , ${beta_ipol}"
if (x >= xValues[origIndex]) {
out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}"
origIndex++
}
System.out << out << "\n"
}
}
}
And now for an off-topic example for EXTRAPOLATIONS, because it's fun. Here we use the same data as above, but extrapolate using an 2nd-degree polynomial. And the appropriate classes, of course. Again, in Groovy:
现在为 EXTRAPOLATIONS 提供一个偏离主题的示例,因为它很有趣。这里我们使用与上面相同的数据,但使用二阶多项式进行外推。当然还有合适的课程。同样,在 Groovy 中:
package example.com
import org.apache.commons.math3.analysis.polynomials.PolynomialFunction
import org.apache.commons.math3.fitting.PolynomialFitter
import org.apache.commons.math3.fitting.WeightedObservedPoint
import org.apache.commons.math3.optim.SimpleVectorValueChecker
import org.apache.commons.math3.optim.nonlinear.vector.jacobian.GaussNewtonOptimizer
class Extrapolate {
enum Value {
ALPHA, BETA
}
def static xValues = [
-284086,
-94784,
31446,
354837,
667782,
982191
]
def static alphaValues = [
71641,
78245,
80871,
94045,
105780,
119616
]
def static betaValues = [
95552,
103413,
108667,
128456,
144686,
171953
]
static def getValueByName(Value value, int i) {
def res
switch (value) {
case Value.ALPHA:
res = alphaValues[i]
break
case Value.BETA:
res = betaValues[i]
break
default:
assert false
}
return res
}
static PolynomialFunction extrapolate(Value value) {
//
// how to check that we converged
//
def checker
A: {
double relativeThreshold = 0.01
double absoluteThreshold = 10
int maxIter = 1000
checker = new SimpleVectorValueChecker(relativeThreshold, absoluteThreshold, maxIter)
}
//
// how to fit
//
def fitter
B: {
def useLUdecomposition = true
def optimizer = new GaussNewtonOptimizer(useLUdecomposition, checker)
fitter = new PolynomialFitter(optimizer)
int i = 0
xValues.each {
def weight = 1.0
def y = getValueByName(value, i++)
fitter.addObservedPoint(new WeightedObservedPoint(weight, it, y))
}
}
//
// fit using a 2-degree polynomial; guess at a linear function at first
// "a0 + (a1 * x) + (a2 * x2)"; a linear guess mean a2 == 0
//
def params
C: {
def mStart = getValueByName(value,0)
def mEnd = getValueByName(value,-1)
def xStart = xValues[0]
def xEnd = xValues[-1]
def a2 = 0
def a1 = (mEnd - mStart) / (xEnd - xStart) // slope
def a0 = mStart - (xStart * a1) // 0-intersection
def guess = [a0 , a1 , a2]
params = fitter.fit(guess as double[])
}
//
// make polynomial
//
return new PolynomialFunction(params)
}
static void main(def argv) {
//
// Create a map mapping a Value instance to its interpolating function
//
def extrapolations = [:]
Value.values().each {
extrapolations[it] = extrapolate(it)
}
//
// New x, this times reaching out past the range of the original xValues
//
def newxValues = []
for (long x = xValues[0] - 400000L ; x < xValues[-1] + 400000L ; x += 10000) {
newxValues << x
}
//
// Write the extrapolated series ALPHA and BETA, adding the original values in columns 4 and 5
//
System.out << "X , ALPHA, BETA, X_orig, ALPHA_orig, BETA_orig" << "\n"
int origIndex = 0
newxValues.each { long x ->
def alpha_xpol = extrapolations[Value.ALPHA].value(x)
def beta_xpol = extrapolations[Value.BETA].value(x)
String out = "${x} , ${alpha_xpol} , ${beta_xpol}"
if (origIndex < xValues.size() && x >= xValues[origIndex]) {
out += ", ${xValues[origIndex]}, ${alphaValues[origIndex]}, ${betaValues[origIndex]}"
origIndex++
}
System.out << out << "\n"
}
}
}