如何从带曲线的图形中获取均匀分布的点?
实现曲线上点的均匀分布
要让点沿曲线均匀分布,不能直接用numpy.interp对x/y坐标插值——因为它是基于坐标轴的线性插值,没法保证沿曲线的弧长均匀。正确思路是先计算曲线的累计弧长,再基于弧长做均匀采样,最后用numpy.interp映射回坐标。
步骤1:计算曲线的累计弧长
先把原始坐标转成numpy数组,再计算相邻点的距离并累加,得到从起点到每个点的弧长:
x = np.array(x_values) y = np.array(y_values) # 计算相邻点的欧氏距离 dx = np.diff(x) dy = np.diff(y) segment_lengths = np.sqrt(dx**2 + dy**2) # 生成累计弧长数组(起点弧长为0) cumulative_lengths = np.concatenate([[0], np.cumsum(segment_lengths)]) total_curve_length = cumulative_lengths[-1]
步骤2:生成均匀的弧长采样点
指定要生成的均匀点数量,用np.linspace生成从0到总弧长的等间距值:
# 示例:生成50个均匀点 target_point_count = 50 uniform_arc_lengths = np.linspace(0, total_curve_length, target_point_count)
步骤3:用numpy.interp插值得到均匀坐标
这一步才用到numpy.interp,参数对应关系和说明:
x:传入我们生成的uniform_arc_lengths(要插值的目标弧长)xp:传入cumulative_lengths(原始点的累计弧长,必须单调递增)fp:传入原始的x或y坐标数组(要插值的目标坐标)period:因为你的曲线是闭合的,设置为total_curve_length,让首尾插值连续,避免断点left/right:我们的采样范围刚好覆盖原始弧长区间,无需设置
代码实现:
# 对x、y坐标分别插值 uniform_x = np.interp(uniform_arc_lengths, cumulative_lengths, x, period=total_curve_length) uniform_y = np.interp(uniform_arc_lengths, cumulative_lengths, y, period=total_curve_length)
完整代码与效果对比
整合所有代码,对比原始点和均匀点的分布:
from matplotlib import pyplot as plt import numpy as np x_values = [1321.4, 598.6, 580.6, 563.8, 548.6, 535.4, 524.5, 516.2, 511, 509.2, 509.2, 511, 516.2, 524.5, 535.4, 548.6, 563.8, 580.6, 598.6, 1321.4, 1339.4, 1356.2, 1371.4, 1384.6, 1395.5, 1403.8, 1409, 1410.8, 1410.8, 1409, 1403.8, 1395.5, 1384.6, 1371.4, 1356.2, 1339.4, 1321.4] y_values = [805.4, 805.4, 803.5, 798.3, 790.1, 779.2, 766, 750.8, 734, 716, 364, 346, 329.2, 314, 300.8, 289.9, 281.7, 276.5, 274.6, 274.6, 276.5, 281.7, 289.9, 300.8, 314, 329.2, 346, 364, 716, 734, 750.8, 766, 779.2, 790.1, 798.3, 803.5, 805.4] # 转换为numpy数组 x = np.array(x_values) y = np.array(y_values) # 计算累计弧长 dx = np.diff(x) dy = np.diff(y) segment_lengths = np.sqrt(dx**2 + dy**2) cumulative_lengths = np.concatenate([[0], np.cumsum(segment_lengths)]) total_curve_length = cumulative_lengths[-1] # 生成均匀弧长采样点 target_point_count = 50 uniform_arc_lengths = np.linspace(0, total_curve_length, target_point_count) # 插值得到均匀坐标 uniform_x = np.interp(uniform_arc_lengths, cumulative_lengths, x, period=total_curve_length) uniform_y = np.interp(uniform_arc_lengths, cumulative_lengths, y, period=total_curve_length) # 绘图对比 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6)) # 原始点分布 ax1.plot(x, y, color='gray') ax1.scatter(x, y, color='blue', label='原始点') ax1.set_aspect('equal') ax1.set_title('原始点分布') ax1.legend() # 均匀点分布 ax2.plot(x, y, color='gray', alpha=0.5) ax2.scatter(uniform_x, uniform_y, color='red', label='均匀点') ax2.set_aspect('equal') ax2.set_title('均匀分布点') ax2.legend() plt.show()
numpy.interp参数补充说明
x:必须是一维数组,代表需要插值的自变量值(这里是均匀弧长)xp:必须是单调递增的一维数组,代表原始数据的自变量(这里是累计弧长)fp:和xp长度相同的一维数组,代表原始数据的因变量(这里是x/y坐标)period:设置后,插值会按周期重复,适合闭合曲线,避免首尾衔接处的断裂left/right:当x中存在超出xp范围的数值时,返回的默认值;我们的采样范围刚好匹配,所以不用设置
内容的提问来源于stack exchange,提问作者Dr. Pontchartrain
相关产品推荐
相关产品推荐

