• 贝塞尔曲线的一些资料收集


    贝塞尔曲线
    一本免费的在线书籍,供你在非常需要了解如何处理贝塞尔相关的事情。
    https://pomax.github.io/bezierinfo/zh-CN/index.html

    An algorithm to find bounding box of closed bezier curves? - Stack Overflow
    https://stackoverflow.com/questions/2587751/an-algorithm-to-find-bounding-box-of-closed-bezier-curves

    前端动画之贝塞尔曲线推导及应用-CSDN博客
    https://blog.csdn.net/frontend_frank/article/details/123437040

    贝塞尔曲线在线绘制🚀
    https://www.bezier-curve.com/

    Calculating / Computing the Bounding Box of Cubic Bezier https://floris.briolas.nl/floris/2009/10/bounding-box-of-cubic-bezier/

    获取三阶贝塞尔曲线的最小包围盒

    c# https://floris.briolas.nl/floris/2009/10/bounding-box-of-cubic-bezier/

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;
    
    namespace BoundingBoxTestProject
    {
    public static class BezierOp
    {
        public delegate TResult Func<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    
        //cubic polinomal
        //x = At^3 + Bt^2 + Ct + D
        //where A,B,C,D:
        //A = p3 -3 * p2 + 3 * p1 - p0
        //B = 3 * p2 - 6 * p1 +3 * p0
        //C = 3 * p1 - 3 * p0
        //D = p0            
        public static Func<double, double, double, double, double, double> bezierSpline = (p0, p1, p2, p3, t) =>
                                                                            (p3 - 3 * p2 + 3 * p1 - p0) * Math.Pow(t, 3)
                                                                            + (3 * p2 - 6 * p1 + 3 * p0) * Math.Pow(t, 2)
                                                                            + (3 * p1 - 3 * p0) * t
                                                                            + (p0);
    
        //X = At^3 + Bt^2 + Ct + D
        //where A,B,C,D:
        //A = (p3 -3 * p2 + 3 * p1 - p0)
        //B = (3 * p2 - 6 * p1 +3 * p0)
        //C = (3 * p1 - 3 * p0)
        //D = (p0)
    
        //We would like to know the values of t where X = 0
        //X  = (p3-3*p2+3*p1-p0)t^3 + (3*p2-6*p1+3*p0)t^2 + (3*p1-3*p0)t + (p0)
        //Derivetive :
        //X' = 3(p3-3*p2+3*p1-p0)t^(3-1) + 2(6*p2-12*p1+6*p0)t^(2-1) + 1(3*p1-3*p0)t^(1-1)              [f(x)=aX^n => f'(x)=a*n*X^(n-1)  remember?]
        //simplified:
        //X' = (3*p3-9*p2+9*p1-3*p0)t^2 + (6*p2-12*p1+6*p0)t + (3*p1-3*p0)
        //**!!reusing a,b,and c!!!***
        //taken as aX^2 + bX + c  a,b and c are:          
        public static Func<double, double, double, double, double> A = (p0, p1, p2, p3) => 3 * p3 - 9 * p2 + 9 * p1 - 3 * p0;
        //ommitting power 2 for now            
        public static Func<double, double, double, double> B = (p0, p1, p2) => 6 * p2 - 12 * p1 + 6 * p0;
        public static Func<double, double, double> C = (p0, p1) => 3 * p1 - 3 * p0;
    
        //b^2 - 4ac = Determinant
        public static Func<double, double, double, double> Determinant = (a, b, c) => Math.Pow(b, 2) - 4d * a * c;
    
        public static Func<double, double, double, double[]> Solve = (a, b, c) =>
                                                           {
                                                               Func<double, double, double, bool, double> _Solve =
                                                                   (a_, b_, c_, s) =>
                                                                   (-b_ +
                                                                    (Math.Sqrt((b_ * b_) - (4d * a_ * c_)) *
                                                                     ((s) ? 1d : -1d))) / (2d * a_);
    
                                                               double d = Determinant(a, b, c);
                                                               if (d < 0)
                                                                   return new double[] { };
    
                                                               if (a == 0)
                                                                   //aX^2 + bX + c well then then this is a simple line
                                                                   //x= -c / b
                                                                   return new double[] { -c / b };
    
                                                               if (d == 0)
                                                               {
                                                                   return new double[] { _Solve(a, b, c, true) };
                                                               }
                                                               else
                                                                   return new double[]
                                                                      {
                                                                          _Solve(a, b, c, true),
                                                                          _Solve(a, b, c, false)
                                                                      };
                                                           };
    
        public static RectangleF GetRect(PointF p1, PointF c1, PointF c2, PointF p2)
        {
            double aX = A(p1.X, c1.X, c2.X, p2.X);
            double bX = B(p1.X, c1.X, c2.X);
            double cX = C(p1.X, c1.X);
    
            double aY = A(p1.Y, c1.Y, c2.Y, p2.Y);
            double bY = B(p1.Y, c1.Y, c2.Y);
            double cY = C(p1.Y, c1.Y);
    
            var resX = Solve(aX, bX, cX).Where(t => (t >= 0) && (t <= 1)); //solve for t ==0 & filter
            var resY = Solve(aY, bY, cY).Where(t => (t >= 0) && (t <= 1)); //solve for t ==0 & filter
    
            //Draw min and max;
    
            List<PointF> _BBox = new List<PointF>();
            _BBox.Add(p1); //Add Begin and end point not the control points!
            _BBox.Add(p2);
    
            foreach (var e in resX.Union(resY))
            {
                double x = bezierSpline(p1.X, c1.X, c2.X, p2.X, e);
                double y = bezierSpline(p1.Y, c1.Y, c2.Y, p2.Y, e);
    
                PointF p = new PointF((float)x, (float)y);
                _BBox.Add(p);
            }
    
            float minX = float.MaxValue;
            float minY = float.MaxValue;
            float maxX = float.MinValue;
            float maxY = float.MinValue;
    
            foreach (var e in _BBox) //find the bounding box.
            {
                minX = Math.Min(e.X, minX);
                minY = Math.Min(e.Y, minY);
                maxX = Math.Max(e.X, maxX);
                maxY = Math.Max(e.Y, maxY);
            }
    
            return new RectangleF(minX, minY, maxX - minX, maxY - minY);
        }
    
    }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124

    c++ 由上述c#代码改写而来,未做优化

    #include 
    #include 
    #include 
    #include 
    
    // 表示一个边界框的结构体
    struct BoundingBox {
        double x;      // 左上角 x 坐标
        double y;      // 左上角 y 坐标
        double width;  // 宽度
        double height; // 高度
        BoundingBox(double _x, double _y, double _width, double _height) : 
        x(_x), y(_y), width(_width), height(_height) {}
    };
    
    // 表示一个二维点的结构体
    struct Point {
        double x; // x 坐标
        double y; // y 坐标
        Point(double _x, double _y) : x(_x), y(_y) {}
    };
    
    // 计算三次贝塞尔曲线的值
    double bezierSpline(double p0, double p1, double p2, double p3, double t) {
        double mt = 1 - t;
        return mt * mt * mt * p0 + 3 * mt * mt * t * p1 + 3 * mt * t * t * p2 + t * t * t * p3;
    }
    
    // 计算贝塞尔曲线的导数系数
    void calculateCoefficients(double p0, double p1, double p2, double p3, double &a, double &b, double &c) {
        a = 3 * (p3 - 3 * p2 + 3 * p1 - p0);
        b = 6 * (p2 - 2 * p1 + p0);
        c = 3 * (p1 - p0);
    }
    
    // 解二次方程 ax^2 + bx + c = 0,并返回在区间 [0, 1] 内的实数解
    std::vector<double> solveQuadratic(double a, double b, double c) {
        std::vector<double> solutions;
        
        // 计算判别式
        double discriminant = b * b - 4 * a * c;
        
        if (discriminant >= 0) {
            double sqrtDiscriminant = std::sqrt(discriminant);
            double t1 = (-b + sqrtDiscriminant) / (2 * a);
            double t2 = (-b - sqrtDiscriminant) / (2 * a);
            
            if (t1 >= 0 && t1 <= 1) {
                solutions.push_back(t1);
            }
            
            if (t2 >= 0 && t2 <= 1) {
                solutions.push_back(t2);
            }
        }
        
        return solutions;
    }
    
    // 计算贝塞尔曲线的边界框
    BoundingBox getBoundsOfCurve(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3) {
        double aX, bX, cX, aY, bY, cY;
        
        // 计算 x 和 y 方向的导数系数
        calculateCoefficients(x0, x1, x2, x3, aX, bX, cX);
        calculateCoefficients(y0, y1, y2, y3, aY, bY, cY);
        
        // 找到导数为零的参数值
        std::vector<double> xSolutions = solveQuadratic(aX, bX, cX);
        std::vector<double> ySolutions = solveQuadratic(aY, bY, cY);
        
        // 存储边界框的点
        std::vector<Point> bboxPoints;
        bboxPoints.push_back(Point(x0, y0));
        bboxPoints.push_back(Point(x3, y3));
        
        // 在导数为零的参数值下计算曲线上的点
        for (double t : xSolutions) {
            double x = bezierSpline(x0, x1, x2, x3, t);
            double y = bezierSpline(y0, y1, y2, y3, t);
            bboxPoints.push_back(Point(x, y));
        }
        
        for (double t : ySolutions) {
            double x = bezierSpline(x0, x1, x2, x3, t);
            double y = bezierSpline(y0, y1, y2, y3, t);
            bboxPoints.push_back(Point(x, y));
        }
        
        // 计算边界框的坐标
        double minX = bboxPoints[0].x;
        double minY = bboxPoints[0].y;
        double maxX = bboxPoints[0].x;
        double maxY = bboxPoints[0].y;
        
        for (const Point &point : bboxPoints) {
            minX = std::min(minX, point.x);
            minY = std::min(minY, point.y);
            maxX = std::max(maxX, point.x);
            maxY = std::max(maxY, point.y);
        }
        
        // 创建边界框并返回
        return BoundingBox(minX, minY, maxX - minX, maxY - minY);
    }
    
    int main()
    {
        // 定义四个控制点的坐标
        // double x0 = 300.0, y0 = 400.0, x1 = 400.0, y1 = 300.0, x2 = 700.0, y2 = 500.0, x3 = 500.0, y3 = 500.0;
        double x0 = 300.0, y0 = 400.0, x1 = 400.0, y1 = 600.0, x2 = 700.0, y2 = 500.0, x3 = 500.0, y3 = 500.0;
        
        // 计算贝塞尔曲线的边界框
        BoundingBox bounds = getBoundsOfCurve(x0, y0, x1, y1, x2, y2, x3, y3);
        
        std::cout << "Bounding Box: (" << bounds.x << ", " << bounds.y << ") - Width: " << bounds.width << ", Height: " << bounds.height;
    
        return 0;
    }
    
    
    // Bounding Box: (300, 400) - Width: 267.277, Height: 125
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
  • 相关阅读:
    Javascript基于protobufjs接入protobuf
    c++菱形继承
    C#唯一进程的处理Winform/WPF
    「网络流浅谈」最小割的模型
    三、C++面向对象-类和对象那些你不知道的细节原理
    CesiumJS 源码杂谈 - 从光到 Uniform
    小白零基础学数学建模系列-Day2-数学建模工具介绍与案例实践
    29、域名ICP备案查询API接口,免费好用
    大聪明教你学Java | 在支付模块中如何防止掉单和重复支付
    生产者消费模式
  • 原文地址:https://blog.csdn.net/yulinxx/article/details/132733317