前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[1106]python bezier(贝塞尔)曲线

[1106]python bezier(贝塞尔)曲线

作者头像
周小董
发布2022-04-13 15:08:27
1.1K0
发布2022-04-13 15:08:27
举报
文章被收录于专栏:python前行者

文章目录

首先简单了解一下什么是贝塞尔曲线(余弦函数曲线我就不多说了哈!),贝塞尔曲线又称贝兹曲线,是法国工程师皮埃尔.贝塞尔于1962年发表。贝塞尔曲线广泛应用于二维绘图软件,早期用于汽车车体设计。

三阶贝塞尔曲线

三阶贝塞尔曲线由如下方程描述:

image.png
image.png

其中t的范围是0到1的闭区间。P0和P3是三阶贝塞尔曲线的起点和终点,P1和P2是曲线的控制点。

然后我们讲一下计算机绘制曲线的原理。从数学定义上,一条连续函数曲线有无数个点,从算法的特点将,算法具有有穷性。所以我们不可能把所有的点全部刻画在屏幕上。另一方面,计算机的屏幕像素是离散的,无法表示连续的曲线。于是引入一个概念,那就是微分思想。将曲线分为一个个小段,将曲线“化曲为直”。

最后说明一下计算机屏幕的坐标系。数学里的笛卡尔坐标系通常以水平向右为x轴正方向,垂直于x轴向上为y轴正方向。而计算机屏幕表示像素点时,其坐标原点位于屏幕左上角,x轴水平向右,而y轴垂直于x轴向下。

下面展示贝赛尔曲线函数代码:

代码语言:javascript
复制
def tri_bezier(p1,p2,p3,p4,t):
    parm_1 = (1-t)**3
    parm_2 = 3*(1-t)**2 * t
    parm_3 = 3 * t**2 * (1-t)
    parm_4 = t**3
 
    px = p1[0] * parm_1 + p2[0] * parm_2 + p3[0] * parm_3 + p4[0] * parm_4
    py = p1[1] * parm_1 + p2[1] * parm_2 + p3[1] * parm_3 + p4[1] * parm_4
    
    return (px,py)

效果展示:

image.png
image.png

python bezier曲线

代码语言:javascript
复制
pip install bezier

手写bezier公式,生成bezier代码, 如果给的点数过多,则会生成一半bezier曲线,剩下的一半就需要进行拼接

代码语言:javascript
复制
import numpy as np
import matplotlib.pyplot as plt
import bezier
b_xs = []
b_ys = []


# xs表示原始数据
# n表示阶数
# k表示索引
def one_bezier_curve(a, b, t):
    return (1 - t) * a + t * b


def n_bezier_curve(xs, n, k, t):
    if n == 1:
        return one_bezier_curve(xs[k], xs[k + 1], t)
    else:
        return (1 - t) * n_bezier_curve(xs, n - 1, k, t) + t * n_bezier_curve(xs, n - 1, k + 1, t)


def bezier_curve(xs, ys, num, b_xs, b_ys):
    n = 5  # 采用5次bezier曲线拟合
    t_step = 1.0 / (num - 1)
    # t_step = 1.0 / num
    print(t_step)
    t = np.arange(0.0, 1 + t_step, t_step)
    print(len(t))
    for each in t:
        b_xs.append(n_bezier_curve(xs, n, 0, each))
        b_ys.append(n_bezier_curve(ys, n, 0, each))


def func():
    xs = [1.0, 2.1, 3.0, 4.0, 5.0, 6.0]
    ys = [0, 1.1, 2.1, 1.0, 0.2, 0]
    num = 20

    bezier_curve(xs, ys, num, b_xs, b_ys)  # 将计算结果加入到列表中
    print(b_xs, b_ys)
    plt.figure()
    plt.plot(b_xs, b_ys, 'r')  # bezier曲线
    # plt.plot(xs, ys)  # 原曲线
    # plt.show()

func()

拼接bezier曲线

代码语言:javascript
复制
def point_bezier(avoid_point):
    global p
    xs = avoid_point[0, 0]  # 0
    ys = avoid_point[1, 0]  # 0
    xe = avoid_point[0, -1]  # 34.5844
    ye = avoid_point[1, -1]  # 0
    Latoff = 2.3
    startp = np.array([xs, ys])
    endp = np.array([xe, ye])
    endp1 = np.array([xe+2, ye])
    # print(startp, endp)
    P0 = startp
    P1 = np.array([startp[0] + (endp[0] - startp[0]) / 8, startp[1]])
    P2 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 2, startp[1]])
    P3 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 2, startp[1] + Latoff])
    P4 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 3, startp[1] + Latoff])
    P5 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 4, startp[1] + Latoff])
    P6 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 5, startp[1] + Latoff])
    P7 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 6, startp[1] + Latoff])
    P8 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 6, startp[1] + Latoff])
    P9 = np.array([startp[0] + (endp[0] - startp[0]) / 8 * 7, startp[1]])
    P10 = endp
    P11 = endp1
    i = 1
    half_length = 0.5 * (xe + xs)
    for u in np.arange(startp[0], startp[0] + (endp[0] - startp[0]) / 2, 0.2):
        # for u =startp[0]:0.2: startp[1] + (endp[1] - startp[1]) / 2
        c = (1 - (u - startp[0]) / half_length) ** 5 * P0 + 5 * (1 - (u - startp[0]) / half_length) ** 4 * (
                u - startp[0]) / half_length * P1 + 10 * (1 - (u - startp[0]) / half_length) ** 3 * (
                    (u - startp[0]) / half_length) ** 2 * P2 + 10 * (1 - (u - startp[0]) / half_length) ** 2 * (
                    (u - startp[0]) / half_length) ** 3 * P3 + 5 * (1 - (u - startp[0]) / half_length) * (
                    (u - startp[0]) / half_length) ** 4 * P4 + ((u - startp[0]) / half_length) ** 5 * P5
        i = i + 1
        p = np.append(p, [c], axis=0)

    for u in np.arange(startp[0] + half_length, endp[0], 0.2):
        d = (1 - (u - startp[0] - half_length) / half_length) ** 5 * P6 + 5 * (
                    1 - (u - startp[0] - half_length) / half_length) ** 4 * (
                    u - startp[0] - half_length) / half_length * P7 + 10 * (
                        1 - (u - startp[0] - half_length) / half_length) ** 3 * (
                    (u - startp[0] - half_length) / half_length) ** 2 * P8 + 10 * (
                        1 - (u - startp[0] - half_length) / half_length) ** 2 * (
                    (u - startp[0] - half_length) / half_length) ** 3 * P9 + 5 * (
                        1 - (u - startp[0] - half_length) / half_length) * (
                    (u - startp[0] - half_length) / half_length) ** 4 * P10 + (
                        (u - startp[0] - half_length) / half_length) ** 5 * P11
        i = i + 1
        p = np.append(p, [d], axis=0)
    return p
    # print(p)
    # plt.plot(p[:, 0], p[:, 1], 'r')
    # plt.show()

使用python 内置bezier包,完成bezier曲线(使用前需安装bezier包)

代码语言:javascript
复制
a = np.array([[1.0, 2.1, 3.0, 4.0, 5.0, 6.0], [0, 1.1, 2.1, 1.0, 0.2, 0]])
curve = bezier.Curve(a, degree=5)
# print(curve)
s_vals = np.linspace(0.0, 1.0, 30)
data = curve.evaluate_multi(s_vals)
x33 = data[0]
y33 = data[1]
plt.plot(x33, y33, 'y', linewidth=2.0, linestyle="-", label="y2")
plt.show()
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022/03/13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 三阶贝塞尔曲线
  • python bezier曲线
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档