如何绘制可经过任意含折返航点的曲线?(路线规划开发)
解决路线规划中支持X轴折返的平滑曲线绘制问题
问题根源
当前方案失效的核心原因是:CubicSpline要求输入的x值必须严格单调,但你对航点按x坐标排序的操作,直接破坏了用户点击的原始航点顺序——当出现x轴折返(比如先点击右侧点再点击左侧点)时,排序会让航点顺序颠倒,导致曲线无法按预期的折返路径生成。
解决方案思路
采用参数化插值:将航点的x、y坐标都表示为一个独立参数t的函数(t代表航点的顺序或累计路径长度),这样x(t)和y(t)都是关于t的单调函数,完全满足CubicSpline的要求,同时能严格保留航点的原始顺序,自然支持x轴折返场景。
改进后的代码
import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import CubicSpline plt.rcParams["figure.figsize"] = [7.00, 3.50] plt.rcParams["figure.autolayout"] = True pts: list[tuple[float, float]] = [] fig = plt.figure() graph = plt.subplot(xlim=(0, 10), ylim=(0, 10)) def mouse_event(event): # 忽略空白区域的无效点击 if event.xdata is None or event.ydata is None: return pts.append((event.xdata, event.ydata)) x = [pt[0] for pt in pts] y = [pt[1] for pt in pts] # 清空画布并重置坐标轴范围 graph.cla() graph.set_xlim([0, 10]) graph.set_ylim([0, 10]) # 绘制原始航点标记 graph.plot(x, y, ls='', marker='o', color='r') # 航点数量≥2时生成平滑曲线 if len(pts) >= 2: # 使用航点索引作为参数t(也可以替换为累计路径距离,优化曲线贴合度) t = np.arange(len(pts)) # 分别对x(t)和y(t)执行三次样条插值 cs_x = CubicSpline(t, np.array(x)) cs_y = CubicSpline(t, np.array(y)) # 生成密集的t值来绘制平滑曲线 t_new = np.linspace(0, len(pts)-1, 1000) x_new = cs_x(t_new) y_new = cs_y(t_new) graph.plot(x_new, y_new, color='b') plt.draw() cid = fig.canvas.mpl_connect('button_press_event', mouse_event) plt.show()
关键修改说明
- 移除航点排序逻辑:完全保留用户点击的原始航点顺序,确保路径按预期的折返方向生成
- 参数化插值:引入独立参数
t(示例中用航点索引),将x、y坐标转换为t的函数,绕开CubicSpline对x单调的要求 - 优化交互体验:增加空白区域点击过滤,避免无效航点添加
- 可选优化:若希望曲线平滑程度更贴合实际路径长度,可将
t替换为航点间的累计欧氏距离,代码如下:# 计算累计欧氏距离作为参数t t = np.zeros(len(pts)) for i in range(1, len(pts)): dx = pts[i][0] - pts[i-1][0] dy = pts[i][1] - pts[i-1][1] t[i] = t[i-1] + np.sqrt(dx**2 + dy**2)
内容的提问来源于stack exchange,提问作者Xbox One
相关产品推荐
相关产品推荐

