如何获得最接近给定点的三次贝塞尔曲线?

给出n分:

p0,p1,p2,…,pn;

如何得到点c1,c2以便定义的三次贝塞尔曲线

p0,c1,c2,pn

最接近给定点?

我试过最小二乘法。 我在http://www.mathworks.com/matlabcentral/fileexchange/15542-cubic-bezier-least-square-fitting上阅读pdf文档后写了这篇文章。 但我找不到一个好的t(i)function。

using System; using System.Collections.Generic; using System.Linq; using System.Windows; namespace BezierFitting { class CubicBezierFittingCalculator { private List data; public CubicBezierFittingCalculator(List data) { this.data = data; } private double t(int i) { return (double)(i - 1) / (data.Count - 1); // double s = 0.0, d = 0.0; // // for (int j = 1; j < data.Count; j++) // { // if (j < i) // { // s += (data[j] - data[j - 1]).Length; // } // d += (data[j] - data[j - 1]).Length; // } // return s / d; } public void Calc(ref Point p1, ref Point p2) { double n = data.Count; Vector p0 = (Vector)data.First(); Vector p3 = (Vector)data.Last(); double a1 = 0.0, a2 = 0.0, a12 = 0.0; Vector c1 = new Vector(0.0, 0.0), c2 = new Vector(0.0, 0.0); for (int i = 1; i <= n; i++) { double ti = t(i), qi = 1 - ti; double ti2 = ti * ti, qi2 = qi * qi; double ti3 = ti * ti2, qi3 = qi * qi2; double ti4 = ti * ti3, qi4 = qi * qi3; a1 += ti2 * qi4; a2 += ti4 * qi2; a12 += ti3 * qi3; Vector pi = (Vector)data[i - 1]; Vector m = pi - qi3 * p0 - ti3 * p3; c1 += ti * qi2 * m; c2 += ti2 * qi * m; } a1 *= 9.0; a2 *= 9.0; a12 *= 9.0; c1 *= 3.0; c2 *= 3.0; double d = a1 * a2 - a12 * a12; p1 = (Point)((a2 * c1 - a12 * c2) / d); p2 = (Point)((a1 * c2 - a12 * c1) / d); } } } 

获得最接近给定点的三次贝塞尔曲线的最佳方法是什么?

例如,这里有30分:

 22, 245 26, 240 39, 242 51, 231 127, 189 136, 185 140, 174 147, 171 163, 162 169, 155 179, 107 181, 147 189, 168 193, 187 196, 75 199, 76 200, 185 201, 68 204, 73 205, 68 208, 123 213, 118 216, 210 216, 211 218, 68 226, 65 227, 110 228, 102 229, 87 252, 247 

这些点分布在由四个点控制的三次贝塞尔曲线周围:

P0(0,256),P1(512,0),P2(0,0),P3(256,256)。

假设曲线是从(0,256)到(256,256),如何让两个控制点靠近原点?

如果要使用尖点创建曲线,则问题非常严重。 我可以想一个启发式来创建一组初始控制点。 对于第一个控制点,尝试从距离第一个锚点的距离排序时,获取可用点的前1/3。 排序是必要的,否则,你可能会跳过。 取1/3的点并进行线性最小二乘拟合,这具有线性时间复杂度。 这为您提供了曲线需要起飞的方向。 用最后的1/3做同样的事情,你就有了“着陆”的方向。

使用这些线性解决方案创建指向远离锚点的向量,然后尝试使这些向量更长和更短,尝试最小化错误。 控制点将沿着来自锚点的那些向量。

这里有一些其他的想法(我只能发布两个链接!): 物理论坛问题 贝塞尔曲线拟合论文

您可能需要查看此页面: http : //www.antigrain.com/research/bezier_interpolation/index.html

这是一个非常好的实现,尽管作者写道:“这种方法纯粹是启发式和经验性的。从严格的数学建模的角度来看,它可能会产生错误的结果。但在实践中,结果是足够好的,它需要绝对最小计算。“

它是用C ++编写的,但很容易移植到任何语言……通过控制点计算function传递每个“边缘”,然后通过bezier计算,然后你就可以了。 要在多边形上执行贝塞尔平滑,请使用最后一个和第一个点传递最后一个边。

贝齐尔顺利

(三次)贝塞尔曲线是一种定义一般forms的三次参数样条的方法P = A * t ^ 3 + B * t ^ 2 + C * t + D其中P,A,B,C和D是(二维(即矢量)权重。 使用伯恩斯坦多项式,您可以计算给定四个控制点P0,P1,P2和P3的权重A,B,C和D,如实际上所有矢量绘图程序所知。

由于你只有四个控制点,但想要适应任意数量的任意点,我怀疑没有独特的解决方案。 例如,给定输入(0,0),(1,0),(1,1)和(0,1),对于每个“最优”解(无论它是什么),您可以通过镜像来构造等效解。沿主对角线的样条曲线。

对于这种问题存在一种通用方法,即构造所有点到一般贝塞尔曲线(即由变量 A,B,C和D定义的曲线)的距离的平方和的等式,计算得出第一个devirative并将其设置为零并解决A,B,C和D的最终系统。这通常会导致一个线性方程组(抱歉,我需要一些时间来做数学,这已经很长时间了。因为我这样做了……)。 但是,正如我所说,我认为对于您的问题,这不会产生独特的解决方案。

如果你在输入点上定义一个顺序,即你想使用单个贝塞尔曲线拟合一个多边形线 ,我认为一个独特的解决方案有太多的自由度(但是,我再没有时间)或者也许是certificate……的技巧

从你的问题判断,我假设你只是希望优化曲线拟合在三次贝塞尔曲线的2’内部’控制点上。 这不是一个容易解决的问题,因为参数化地描述了贝塞尔曲线。 最明显的解决方案是使用最小二乘正交距离回归,但这很困难,因为您需要在Bezier曲线上为您希望拟合的每个点生成足点参数。 如果这个问题需要一个特定的分析解决方案并且你有一些数学教育,我建议阅读Peigl和Tiller的“The NURBS Book”并熟悉近似理论和优化技术。 如果没有,我会采用更具启发性的方法,因为这种类型的问题不太可能通过这里的简单答案来解决。

Khan函数使用两个版本的t [i],其中t [i]表示近似曲线上最接近点到输入点p [i]的猜测。 第一个简单地使用均匀的t [i] = i /(N-1),第二个使用和弦长度。 虽然我找不到Khan的函数,但我认为这只是计算线性距离p [i]到p [i + 1],将t [0]设置为0,t [1]到距离p [0]到p [1],t [2]到t [1] +距离p [1]到p [2],依此类推。 除以最后一个值,将所有内容放在0-1范围内。