过N点的贝塞尔曲线

做一条过N点的平滑曲线

引用自http://www.cnblogs.com/muxue/archive/2010/06/23/1763886.html

当然有一个小的速度上优化技巧,令d1=d2这样计算复杂度会减少,但是曲线的拐角会比较丑。

 public class BezierCurves
    {

        /// <summary>
        /// create control point 
        /// </summary>
        /// <param name="points"></param>
        /// <param name="smoothValue"></param>
        /// <returns></returns>
        private static Point[] CalculControlPoint(Point[] points, double smoothValue)
        {
            // Assume we need to calculate the control
            // points between (points[1].X,points[1].Y) and (points[2].X,points[2].Y).
            // Then points[0].X,points[0].Y - the previous vertex,
            //      points[3].X,points[3].Y - the next one.

            double xc1 = (points[0].X + points[1].X) / 2.0;
            double yc1 = (points[0].Y + points[1].Y) / 2.0;
            double xc2 = (points[1].X + points[2].X) / 2.0;
            double yc2 = (points[1].Y + points[2].Y) / 2.0;
            double xc3 = (points[2].X + points[3].X) / 2.0;
            double yc3 = (points[2].Y + points[3].Y) / 2.0;

            double len1 = Math.Sqrt((points[1].X - points[0].X) * (points[1].X - points[0].X) + (points[1].Y - points[0].Y) * (points[1].Y - points[0].Y));
            double len2 = Math.Sqrt((points[2].X - points[1].X) * (points[2].X - points[1].X) + (points[2].Y - points[1].Y) * (points[2].Y - points[1].Y));
            double len3 = Math.Sqrt((points[3].X - points[2].X) * (points[3].X - points[2].X) + (points[3].Y - points[2].Y) * (points[3].Y - points[2].Y));

            double k1 = len1 / (len1 + len2);
            double k2 = len2 / (len2 + len3);

            double xm1 = xc1 + (xc2 - xc1) * k1;
            double ym1 = yc1 + (yc2 - yc1) * k1;

            double xm2 = xc2 + (xc3 - xc2) * k2;
            double ym2 = yc2 + (yc3 - yc2) * k2;

            Point[] outPoints = new Point[4];
            // Resulting control points. Here smooth_value is mentioned
            // above coefficient K whose value should be in range [0...1].
            outPoints[0] = points[1];
            outPoints[1].X = (float)(xm1 + (xc2 - xm1) * smoothValue + points[1].X - xm1);
            outPoints[1].Y = (float)(ym1 + (yc2 - ym1) * smoothValue + points[1].Y - ym1);
            outPoints[2].X = (float)(xm2 + (xc2 - xm2) * smoothValue + points[2].X - xm2);
            outPoints[2].Y = (float)(ym2 + (yc2 - ym2) * smoothValue + points[2].Y - ym2);
            outPoints[3] = points[2];
            return outPoints;
        }

        // Number of intermediate points between two source ones,
        // Actually, this value should be calculated in some way,
        // Obviously, depending on the real length of the curve.
        // But I don't know any elegant and fast solution for this
        // problem.

        private static List<Point> Curve4(Point[] points, int numSteps = 20)
        {
            Trace.Assert(points.Length == 4);

            double x1 = points[0].X;
            double y1 = points[0].Y;    //Anchor1
            double x2 = points[1].X;
            double y2 = points[1].Y;    //Control1
            double x3 = points[2].X;
            double y3 = points[2].Y;    //Control2
            double x4 = points[3].X;
            double y4 = points[3].Y;    //Anchor2

            double dx1 = x2 - x1;
            double dy1 = y2 - y1;
            double dx2 = x3 - x2;
            double dy2 = y3 - y2;
            double dx3 = x4 - x3;
            double dy3 = y4 - y3;

            double subdiv_step = 1.0 / (numSteps + 1);
            double subdiv_step2 = subdiv_step * subdiv_step;
            double subdiv_step3 = subdiv_step * subdiv_step * subdiv_step;

            double pre1 = 3.0 * subdiv_step;
            double pre2 = 3.0 * subdiv_step2;
            double pre4 = 6.0 * subdiv_step2;
            double pre5 = 6.0 * subdiv_step3;

            double tmp1x = x1 - x2 * 2.0 + x3;
            double tmp1y = y1 - y2 * 2.0 + y3;

            double tmp2x = (x2 - x3) * 3.0 - x1 + x4;
            double tmp2y = (y2 - y3) * 3.0 - y1 + y4;

            double fx = x1;
            double fy = y1;

            double dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;
            double dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;

            double ddfx = tmp1x * pre4 + tmp2x * pre5;
            double ddfy = tmp1y * pre4 + tmp2y * pre5;

            double dddfx = tmp2x * pre5;
            double dddfy = tmp2y * pre5;

            int step = numSteps;

            List<Point> list = new List<Point>();
            // Suppose, we have some abstract object Polygon which
            // has method AddVertex(x, y), similar to LineTo in
            // many graphical APIs.
            // Note, that the loop has only operation add!
            while (step-- > 0)
            {
                fx += dfx;
                fy += dfy;
                dfx += ddfx;
                dfy += ddfy;
                ddfx += dddfx;
                ddfy += dddfy;
                list.Add(new Point(fx, fy));
            }
            list.Add(points[3]); // Last step must go exactly to x4, y4
            return list;
        }



        public static List<Point> GetPolyline(List<Point> list, double smoothValue, int numSteps, bool isLoop, bool isOpen)
        {
            List<Point> temp = list.ToList();
            if (isLoop)
            {
                temp.Insert(0, list.Last());
                temp.Add(temp[1]);
                temp.Add(temp[2]);
            }
            else
            {
                temp.Insert(0, temp.First());
                temp.Add(temp.Last());
                temp.Add(temp[0]);
                temp.Add(temp[0]);
            }
            List<Point> result = new List<Point>();
            result.Add(list[0]);    // first point
            for (int i = 0; i < (!isOpen ? list.Count : list.Count - 1); i++)
            {
                Point[] points = CalculControlPoint(temp.GetRange(i, 4).ToArray(), smoothValue);
                result.AddRange(Curve4(points, numSteps));
            }
            return result;
        }

    }

smoothValue =0 就是单纯的直线,

loop是首尾相接,主要影响的是起点和终点是否平滑。

open代表是否开闭。

没怎么优化,基本就是抄了一遍引用链接里的代码。

### 回答1: Matlab空间贝塞尔曲线是指在三维空间中,由一组构成的贝塞尔曲线贝塞尔曲线是一种多项式插值曲线,在计算机图形学及计算机辅助设计中广泛应用。 在Matlab中,空间贝塞尔曲线可以通过使用Bezier函数实现。首先我们要给定一组控制,这组控制可以是分布在三维空间中的任意位置。通过调用Bezier函数,将控制传入函数中,就可以得到由这组控制构成的空间贝塞尔曲线。 同时,在Matlab中,还可以调用spcrv函数实现空间贝塞尔曲线的绘制。该函数可以对给定的控制进行插值,生成平滑且符合要求的曲线。除此之外,还可以通过修改spcrv函数中的参数,即控制曲线的度数、曲线的平滑度等,实现更加灵活的曲线绘制。 总之,Matlab空间贝塞尔曲线可以快速生成三维空间中的平滑曲线,广泛应用于计算机图形学、计算机辅助设计、工程建模等领域。 ### 回答2: Matlab中的空间贝塞尔曲线基于贝塞尔曲线的一种应用,用于生成一条平滑的曲线,由若干控制组成。空间贝塞尔曲线是在三维空间中生成的曲线,由一系列控制确定,曲线穿过第一个和最后一个控制,并且通过中间控制,形成一条平稳的曲线。 在Matlab中,我们可以使用bezier函数来生成空间贝塞尔曲线。该函数需要一个包含所有控制的矩阵作为输入参数,并返回一个包含曲线上所有点的矩阵。对于三维空间中的曲线,输入矩阵应该是一个n*3维的矩阵,其中n是控制的数量。例如,如果我们有四个控制,并且每个的坐标分别为(0,0,0)、(1,2,3)、(3,2,1)和(4,0,0),那么输入矩阵应该如下所示: ctrlPts = [0 0 0; 1 2 3; 3 2 1; 4 0 0]; 我们可以使用bezier函数来生成曲线上的所有点,并将结果存储在一个矩阵中: curvePts = bezier(ctrlPts); curvePts矩阵包含曲线上的所有点,可以通过plot3函数将它们绘制出来。 空间贝塞尔曲线可以应用于许多不同的领域,例如计算机图形学、机器人运动规划和航空航天等。在这些领域中,空间贝塞尔曲线可以用来生成平稳的路径或轨迹,以及在运动或控制系统中应用的其他功能。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值