[python bezier贝塞尔曲线] 数值解法、德卡斯特里奥解法解法以及bezier库的使用demo

修改自这个老哥的,非常的nice,此处仅作为学习记录

matplotlib==3.7.0 可行

Note: 数值解法是真的快

先上图

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import math
import time


class Bezier:
    def __init__(self, Points, InterpolationNum):
        # 输入控制点,Points是一个array,num是控制点间的插补个数
        self.pointsNum = Points.shape[0]  # 控制点的个数
        self.demension = Points.shape[1]  # 点的维度
        self.order = Points.shape[0] - 1  # 贝塞尔阶数=控制点个数-1
        self.num = InterpolationNum  # 相邻控制点的插补个数
        self.Points = Points

    def DigitalAlgo(self):
        # 数值解法
        PB = np.zeros((self.pointsNum, self.demension))  # 求和前各项
        pis = []  # 插补点
        for u in np.arange(0, 1 + 1 / self.num, 1 / self.num):
            for i in range(0, self.pointsNum):
                PB[i] = (math.factorial(self.order) / (
                        math.factorial(i) * math.factorial(self.order - i))) * (u ** i) * (
                                1 - u) ** (self.order - i) * self.Points[i]
            pi = sum(PB).tolist()  # 求和得到一个插补点
            pis.append(pi)
        return np.array(pis)

    def DeCasteljauAlgo(self):
        # 德卡斯特里奥解法
        pis = []  # 插补点
        for u in np.arange(0, 1 + 1 / self.num, 1 / self.num):
            Att = self.Points
            for i in np.arange(0, self.order):
                for j in np.arange(0, self.order - i):
                    Att[j] = (1.0 - u) * Att[j] + u * Att[j + 1]
            pis.append(Att[0].tolist())

        return np.array(pis)

    def __call__(self, method):
        # 获取Bezeir所有插补点
        if method == 0:
            return self.DigitalAlgo()
        if method == 1:
            return self.DeCasteljauAlgo()


points = np.array([
    [1, 3, 0],
    [1.5, 1, 0],
    [4, 2, 0],
    [4, 3, 4],
    [2, 3, 11],
    [5, 5, 9],
    [1, 3, 0],
    [1.5, 1, 0],
    [4, 2, 0],
    [4, 3, 4],
    [2, 3, 11],
    [5, 5, 9]
])
points[6:, ...] = 5 + points[6:, ...]

# points = np.array([
#     [0.0, 0.0, 0.],
#     [1.0, 0.0, 1.],
#     [1.0, 1.0, 1.],
#     [0.0, 1.0, 2.],
# ])


if points.shape[1] == 3:
    fig = plt.figure()
    ax = fig.add_axes(Axes3D(fig))

    # 标记控制点
    for i, point in enumerate(points, 1):
        ax.scatter(point[0], point[1], point[2], marker='o', color='r')
        ax.text(point[0], point[1], point[2], i, size=12)

    # 直线连接控制点
    ax.plot3D(points[:, 0], points[:, 1], points[:, 2], color='k')

    # 贝塞尔曲线连接控制点
    s = time.time()
    matpi = Bezier(points, 10000)(0)
    print(f'{time.time() - s:.5f}s')
    ax.plot3D(matpi[:, 0], matpi[:, 1], matpi[:, 2], color='r')
    plt.show()

    # 0 0.12295s
    # 1 0.35341s

if points.shape[1] == 2:
    # 标记控制点
    for i, point in enumerate(points, 1):
        plt.scatter(point[0], point[1], point[2], marker='o', color='r')
        plt.text(point[0], point[1], point[2], i, size=12)

    # 直线连接控制点
    plt.plot(points[:, 0], points[:, 1], color='k')

    # 贝塞尔曲线连接控制点
    matpi = Bezier(points, 1000)(1)
    plt.plot(matpi[:, 0], matpi[:, 1], color='r')
    plt.show()

 推荐一下bezier这个库画bezier贝塞尔曲线

也非常的好用,具体的看官方介绍吧....

不会安装的看这个详细的安装教程

(159条消息) [python 安装bezier的问题] win11 The BEZIER_INSTALL_PREFIX environment variable must be set._12..的博客-CSDN博客

import bezier
import numpy as np
import matplotlib.pyplot as plt

nodes1 = np.array([
    [0.0, 0.5, 1.0],
    [0.0, 1.0, 0.0],
])
nodes2 = np.array([
    [0.0, 0.25, 0.5, 0.75, 1.0],
    [0.0, 2.0, -2.0, 2.0, 0.0],
])

print(nodes2)
curve1 = bezier.Curve(nodes1, degree=2)
curve2 = bezier.Curve.from_nodes(nodes2)
intersections = curve1.intersect(curve2)

s_vals = np.array(intersections[0, :])
points = curve1.evaluate_multi(s_vals)


ax = curve1.plot(num_pts=256)
_ = curve2.plot(num_pts=256, ax=ax)
lines = ax.plot(
    points[0, :], points[1, :],
    marker="o", linestyle="None", color="black")

# ax.plot(nodes1[0, :], nodes1[1, :], label='l1')
# ax.plot(nodes2[0, :], nodes2[1, :], label='l2')
# ax.axis("scaled")
ax.set_xlim(-0.125, 1.125)
ax.set_ylim(-0.0625, 0.625)
plt.legend()
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放飞自我的Coder

你的鼓励很棒棒哦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值