我的目标是在这两个电路曲线形状之间找到一条平滑的最佳拟合线。 有没有比我的算法更好的算法可以找到两行之间的一组点(或曲线),如本例所示?
到目前为止我所拥有的算法占据了内部部分并且每个点都找到了最接近的部分,但是这不起作用,因为(看第一个角落)。
(红色是内部,绿色是外部,蓝色是我发现的优化点)
这是我的jsfiddle: http://jsfiddle.net/STLuG/
这是算法:
for (i = 0; i < coords[0].length; i++) {
var currentI = coords[0][i];
j = 0;
var currentJ = coords[0][j];
currentDist = dist(currentI,currentJ);
for (j=1; j < coords[1].length; j++) {
possibleJ = coords[1][j];
possibleDist = dist(currentI, possibleJ);
if (possibleDist < currentDist) {
currentJ = possibleJ;
currentDist = possibleDist;
} else {
}
}
b_context.fillRect(
(currentI.x+currentJ.x)/2+maxX,
(currentI.y+currentJ.y)/2+maxY,
1, 1);
}
由于
答案 0 :(得分:2)
我会尝试最小二乘算法。 您有多个点:分别为第一个和第二个曲线的y0和x0以及y1和x1。 您希望找到一条曲线y(t)和x(t),它是平滑的,位于两条给定曲线之间。 所以第一条曲线(x0(t),y0(t))与你的计算曲线(x(t),y(t))之间的距离是:
S0 = SumOverAllT(x0(t)-x(t))^ 2 +(y0(t) - y(t))^ 2
第二条曲线相同:
S1 = SumOverAllT(x1(t)-x(t))^ 2 +(y1(t) - y(t))^ 2
两笔金额的总和:
S = S0 + S1
您将拥有一组要确定的参数。 例如。如果你使用多项式:
X(t)= AX + BX * T + CX * T ^ 2 + DX * T ^ 3 ....
Y(T)= AY由* T + CY * T ^ 2 + DY * T ^ 3 ....
+然后你将计算
dS / dax,dS / dbx,dS / dcx,....
所有要计算的参数
并将这些衍生物设为零:
DS / DAX == 0 DS / DBX == 0 ....
这将为您提供一组线性方程,可以用高斯算法或任何解决线性方程组的方法进行攻击。
如果您使用多项式,可能会发生计算的曲线强烈振荡。 在这种情况下,我建议尽量减少二阶导数平方的积分:
I =积分((d ^ 2x / dt ^ 2)^ 2 +(d ^ 2y / dt ^ 2)^ 2,dt)
你会计算I与一些额外参数的差值,你没有用于上述方程组 - 添加一个参数rx并计算dI / drx == 0 - 因此你还有一个参数和一个参数方程。
任何有数学博士学位的人都请告诉我上面提到的任何愚蠢。
还在互联网上搜索:
更好的方法是使用样条 - 分段连续多项式,以便
是连续的。 查找或购买数字配方以找到完全符合这一要求的代码。
对于样条逼近,您将得到一组多项式:
x0(t)= a0x + b0x *(t - t0)+ c0x *(t-t0)^ 2 + d0x *(t - t0)^ 3 ....
x1(t)= a1x + b1x *(t-t0)+ c1x *(t-t0)^ 2 + d1x *(t-t0)^ 3 ....
每个多项式只用于覆盖两个给定点之间的匹配t = t0..t1。
然后,您将添加公式以确保两个相邻多项式的值,一阶和二阶导数相同。 并将第一个和最后一个多项式的2导数设置为零。
您可以计算两个样条线 - 您可以使用两条输入曲线中的每一条:
X0(t)的
Y0(t)的
X1(t)的
Y1(t)的
然后你可以得出两个样条曲线的中间部分:
x(t)=(x0(t)+(x1(t)-x0(t))/ 2
y(t)=(y0(t)+(y1(t)-y0(t))/ 2
确保任何给定曲线与您产生的曲线之间的距离永远不为零,这样它们就不会相互交叉
为了确定您的计算线不会交叉给定的一条线,您可以最小化(sum(sum(1 /(x0-x)^ 2))+ sum(sum (1 /(X1-X)^ 2)))