Path.CURVE3 和 Path.CURVE4 有什么问题?贝塞尔曲线在某一点混乱

What is wrong with Path.CURVE3 and Path.CURVE4? Bézier curve messes up in a certain point

我想用 Python 在 JupyterLab 上绘制贝塞尔曲线,我正在使用 MatplotLib 来制作兰博基尼的复制品。绘图必须是忠实的复制品,所以我使用 NumPy 带来 Lamborghini image as a background, as long as I can draw over it and manipulate its properties such as opacity. But no matter what I do, these very first points of the bumber just go crazy. I tried using Path.CURVE3 and Path.CURVE4, Path.STOP and also Path.LINETO in order to make the Bézier curve stop properly on a given point (curve going crazy)。我也尝试制作更小的曲线,但我看不到我想要的东西。我必须完全按照汽车的曲线行驶。我用GIMP提取了我需要的点。

这是我的代码,实际上,这种情况比我在这里暴露的还要普遍,即使没有使用 NumPy 图像处理也会发生这种情况。使用 CURVE 对象的规则是什么?有什么限制?是什么让我的曲线变得疯狂?

import math
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.pyplot as plt
import numpy as np

Path = mpath.Path

fig, ax = plt.subplots()

bumper = mpatches.PathPatch(
    Path(
        [(22, 163), (12, 134), (13, 132), (30.6, 117.65), (43, 118)],
        [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.CURVE4],
    ),
    fc="none",
    transform=ax.transData,
    color="green",
    lw=1,
)

ax.add_patch(bumper)

ax.set_title("Lamborghini Sián FKP 37", fontfamily="Tahoma", fontsize=22)
ax.set_aspect(1)

plt.xticks(np.linspace(0, 1180, 21), fontsize=10)
plt.yticks(np.linspace(0, 330, 9), fontsize=10)
plt.grid(color="gray", ls=":", lw=0.2)

lambo = plt.imread("Lamborghini Sian FKP 37 Right Side.png")

plt.imshow(lambo, alpha=0.35, extent=[0, 1180, 0, 330])

plt.rcParams["figure.figsize"] = (15, 6)

plt.show()

于是,经过一段时间的研究,我在MatplotLib文档中找到了this,弄明白了Path的二次曲线Path.CURVE3和三次曲线Path.CURVE4属性的含义。 CURVE3 表示您只能绘制具有 2 个给定点的曲线,CURVE4 具有 3 个点。我们要记住:起点就像把铅笔放在纸上,第一个点; 控制点才是真正的曲线,你可以想象一根绳子在两点之间完全笔直,被拉动,形成曲线; 终点 是您停止绘图并将铅笔从纸上拿开的最后一个点。

  • Path.MOVETO是当你把铅笔放在纸上(开始一个新的轨迹)

  • Path.CURVE3 必须与精确的 2 点一起使用:
    • 1 个控制点。 (Path.CURVE3)
    • 1 终点。 (Path.CURVE3)

  • Path.CURVE4 必须与精确的 3 点一起使用:
    • 2 个控制点。 (Path.CURVE4)
    • 1 终点。 (Path.CURVE4)

我的努力是将很多点放在 verts 列表中,如下所示:[(x,y),(x,y),(x,y),(x,y),(x,y)] 并拥有一个 codes 列表,如下所示:[Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, Path.CURVE4]。请注意,在此示例中,我们有 5 个点。当我们要绘制贝塞尔曲线时,我们必须分析它必须是 CURVE3 还是 CURVE4。如果你有4点,就用CURVE4,如果有3点就用CURVE3。我们必须做一些变通方法来划分要定义的路径。如果你有超过点数的限制,你必须重新启动关于曲线大小的路径。像这样:

bezier1 = mpatches.PathPatch( # Everything in the same patch
    Path([(5, 30), (15, 55), (25, 15), (35, 40), # 4 first points
          (20, 10), (30, 0), (35, 10)],        # 3 new points, so start a new curve and use
         [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4, # Begin the curve
          Path.MOVETO, Path.CURVE3, Path.CURVE3]),            # Restart the process with a new one
    fc="none", transform=ax.transData, color="red", lw=2)

重要提示:另外,如果你绘制的是一条长曲线,当线条的一部分完成时,你必须通过立即开始线条的延续最后一点,这会给你一个连续的。这就是我发现的,我希望这可以帮助别人。