一尘不染

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

algorithm

给予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)函数。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace BezierFitting
{
    class CubicBezierFittingCalculator
    {
        private List<Point> data;

        public CubicBezierFittingCalculator(List<Point> 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),如何使静止的两个控制点靠近原点?


阅读 440

收藏
2020-07-28

共1个答案

一尘不染

如果要创建具有尖点的曲线,则问题非常棘手。我可以想到一种启发式方法来创建一组初始控制点。对于第一个控制点,当从距离到第一个锚点进行排序时,请尝试获取可用的点的前1/3。排序是必要的,否则,您可能会无所适从。取该点的1/3并进行线性最小二乘拟合,这具有线性时间复杂度。这为您提供了曲线起飞的方向。对最后1/3执行相同的操作,您将获得“着陆”方向。

使用那些线性解决方案来创建指向远离锚点的向量,然后尝试使这些向量变长和变短,以尽量减少误差。控制点将沿着来自锚点的向量。

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

2020-07-28