IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> C# 贝塞尔曲线开发相关总结 -> 正文阅读

[数据结构与算法]C# 贝塞尔曲线开发相关总结

贝塞尔曲线开发相关总结

提示:个人学习总结,如有错误,敬请指正。



一、1-3阶贝塞尔曲线

1.一阶贝塞尔曲线

一阶贝塞尔曲线公式:B(t) = P1 + (P2 ? P1)t = P1(1?t)+ P2t, t∈[0,1]

一阶贝塞尔曲线是一条直线,在三阶贝塞尔中表现为调整点为起终止点

    public Vector3 lineBezier(float t,Vector3 p0, Vector3 p1)
    {
        Vector3 a = p0;
        Vector3 b = p1;
        return a + (b - a) * t;
    }

2.二阶贝塞尔曲线

二阶贝塞尔曲线公式:B(t) = P1(1 - t)2 + 2P2t(1 - t) + P3t2,t∈[0,1]

二阶贝塞尔曲线有一个调整点,但画出的贝塞尔曲线没有经过该调整点

    /// <summary>
    /// 获得二阶
    /// </summary>
    /// <param name="p0">起点</param>
    /// <param name="p1">调整点</param>
    /// <param name="p2">终点</param>
    /// <param name="t"></param>
    /// <returns></returns>
public Vector3 quardaticBezier(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        Vector3 a = p0;
        Vector3 b = p1;
        Vector3 c = p2;
        
        Vector3 aa = a + (b - a) * t;
        Vector3 bb = b + (c - b) * t;
        return aa + (bb - aa) * t;
    }

3.三阶贝塞尔曲线

三阶贝塞尔曲线公式:B(t) = P1(1 - t)3 + 3P2t(1 - t)2 + 3P3t2(1 - t) + P4t3,t∈[0,1]

    /// <summary>
    /// 获得三阶
    /// </summary>
    /// <param name="p0">起点</param>
    /// <param name="p1">调整点</param>
    /// <param name="p2">调整点</param>
    /// <param name="p3">终点</param>
    /// <param name="t"></param>
    /// <returns></returns>
    public Vector3 cubicBezier(float t,Vector3 p0, Vector3 p1, Vector3 p2,Vector3 p3)
    {
        Vector3 a = p0;
        Vector3 b = p1;
        Vector3 c = p2;
        Vector3 d = p3;
        
        Vector3 aa = a + (b - a) * t;
        Vector3 bb = b + (c - b) * t;
        Vector3 cc = c + (d - c) * t;

        Vector3 aaa = aa + (bb - aa) * t;
        Vector3 bbb = bb + (cc - bb) * t;
        return aaa + (bbb - aaa) * t;
    }

二、过定点的二阶贝塞尔曲线以及其升阶

1.过定点的二阶贝塞尔曲线

在二阶贝塞尔曲线中我们知道其有一个调整点但曲线本身不经过,但在开发中会要求使用一个经过曲线的点来控制曲线的变化。为了解决这个问题,我们可以设置一个新的调整点,使得产生的新曲线经过要求的点。

	  /// <summary>
    /// 定点的二阶
    /// </summary>
    /// <param name="p0">起点</param>
    /// <param name="p1">调整点</param>
    /// <param name="p2">终点</param>
    /// <param name="t"></param>
    /// <returns></returns>
    public Vector3 quardaticOverPointBezier(float t,Vector3 p0, Vector3 p1, Vector3 p2)
    {
        Vector3 a = p0;
        Vector3 b = p1;
        Vector3 c = p2;
        //具体推导可以看后面的链接
        b = p1 - Mathf.Sqrt((p0 - p1).magnitude * (p2 - p1).magnitude) * ((p0 - p1) / (p0 - p1).magnitude + (p2 - p1) / (p2 - p1).magnitude) / 2;
        Vector3 aa = a + (b - a) * t;
        Vector3 bb = b + (c - b) * t;
        return aa + (bb - aa) * t;
    }

2.二阶贝塞尔曲线的升阶

由于n次贝塞尔曲线可以转换为一个形状完全相同的n+1次贝塞尔曲线
因此可以根据过定点的二阶贝塞尔转化成过顶点三阶贝塞尔

//二阶转三阶:
    A= p0;
    B= p0/3+2*p1/3;
    C= 2*p1/3+p2/3;
    D= p2;
//后续照搬上面的三阶贝塞尔

三、三阶贝塞尔的分段

如果在三阶贝塞尔曲线上添加一个点,那么由此生成的两段曲线依然是贝塞尔曲线吗?
答案是是的,链接中已给出了求添加点调整点的公式,但新的问题是如何求该点在贝塞尔曲线中的t值?

1.迭代求t

找到一段范围然后再新的分成新的范围去找满足条件的t值
迭代能保证一定的精度,但是耗时,在频繁求t值可能会出现崩溃

    /// <summary>
    ///根据贝塞尔曲线上的点求t 
    /// </summary>
    /// <param name="p0"></param>
    /// <param name="p1"></param>
    /// <param name="p2"></param>
    /// <param name="p3"></param>
    /// <param name="p">该点</param>
    /// <param name="startT"></param>
    /// <param name="endT"></param>
    /// <returns></returns>
    private float GetTFormCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3,Vector3 p,float startT = 0,float endT = 1)
    {
        var t = startT;
        var minDistance = Mathf.Infinity;
        var minDistanceT = 0f;
        var step = (endT - startT) / 100;
        for (int i = 0; i < 100; i++)
        {
            var point = cubicBezier(t,p0, p1, p2,p3);
            var dst = Vector3.Distance(point, p);
            if (dst < minDistance)
            {
                minDistance = dst;
                minDistanceT = t;
            }
            if (dst < 0.0001)
            {
                return t;
            }
            t += step;
        }
        return GetTFormCurve(p0, p1, p2,p3, p, minDistanceT - step, minDistanceT + step);
    }

2.解方程求t

我尝试找过三阶贝塞尔的解方程,但是难以实现。之前讲过可以用二阶升三阶,二阶贝塞尔解方程是一件容易的事情,那么可以从二阶贝塞尔曲线出发
二阶贝塞尔解方程是一元二次方程,得出在[0,1]之间的解,若两个则求坐标与点最近的那个。

//z0,z1,z2为p1,p2,p3的x值,tp为目标x
//curvedata中存储一元二次方程解的情况
//tt单解,tt1,tt2为解
private curvedata Solution(float z0, float z1, float z2, float tp)
    {
        var a = z0 - z1 * 2 + z2;
        var b = 2 * (z1 - z0);
        var c = z0 - tp;
        var tt = 0f;
        curvedata result = new curvedata();
        if (a == 0 && b != 0)
        {
            tt = -c / b;
        }
        else
        {
            var sq = Math.Sqrt(b * b - 4 * a * c);
            var tt1 = (sq - b) / (2 * a);
            var tt2 = (-sq - b) / (2 * a);
            if ((tt1 <= 1 && tt1 >= 0) && (tt2 <= 1 && tt2 >= 0))
            {               
                result.tt1 = (float)tt1;
                result.tt1 = (float)tt2;
                return result;
            }
            else if (tt1 <= 1 && tt1 >= 0)
            {
                tt = (float)tt1;
                result.t = tt;
            }
             else
            {
                tt = (float)tt2;
                result.t = tt;
            }
        }
        return result;
    }

经过上面进行判断即可求出t值

//A、B、C、D为上文的二阶转三阶
//I,J 即为所求
        var F = A * (1 - t) + B * t;
        var G = B * (1 - t) + C * t;
        var H = C * (1 - t) + D * t;

        var I = F * (1 - t) + G * t;
        var J = G * (1 - t) + H * t;

亲测得出的结果和迭代所求有可忽略的误差。
至此已经求出点的两个调整点,可实现在一段由二阶升三阶的贝塞尔曲线添加一个点,形成两段可调节的三阶贝塞尔曲线。


四、贝塞尔曲线的平行线

TODO


附:参考链接

提示:链接里有较为详细的推导

1.过定点的二阶贝塞尔
2.贝塞尔曲线基础
3.贝塞尔曲线分段

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:56:50  更:2022-04-07 22:58:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 10:01:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码