如何生成沿曲线点间距均衡的数组xx与yy(通用方法)
实现曲线上均匀分布采样的通用方法
你遇到的问题本质是按x轴均匀取点不等于按曲线弧长均匀取点——对于像1/x这类非线性强的函数,x轴上的均匀间隔会导致曲线陡峭区域的点极度稀疏,平缓区域点过度密集。要让曲线上相邻点的实际间距(弧长)保持相近,核心思路是基于曲线的弧长参数化来生成采样点。
通用实现步骤
核心逻辑是:先计算曲线从起点到每个x的累积弧长,再在弧长维度上均匀取点,最后反推对应的x值。这样得到的x采样点对应的曲线上点,弧长间距会均匀一致。
代码示例(以1/x为例)
import numpy as np from scipy.integrate import cumtrapz from scipy.interpolate import interp1d import matplotlib.pyplot as plt # 定义目标函数及其导数 def f(x): return 1.0 / x def df_dx(x): return -1.0 / (x**2) # 1. 生成足够密集的初始x点,用于计算累积弧长 x_dense = np.linspace(0.1, 10, 10000) # 2. 计算每个点的弧长元素:ds = sqrt(1 + (f'(x))²) dx ds = np.sqrt(1 + df_dx(x_dense)**2) # 3. 计算从起点开始的累积弧长 s_cumulative = np.concatenate([[0], cumtrapz(ds, x_dense)]) total_arc_length = s_cumulative[-1] # 4. 在弧长维度上均匀取点 num_samples = 1000 s_uniform = np.linspace(0, total_arc_length, num_samples) # 5. 反推对应的x值(利用插值,因为累积弧长和x是单调映射) x_uniform = interp1d(s_cumulative, x_dense, kind='linear')(s_uniform) # 6. 计算对应的y值 y_uniform = f(x_uniform) # 对比两种采样效果 plt.figure(figsize=(12, 6)) plt.subplot(1, 2, 1) plt.plot(np.linspace(0.1, 10, 1000), 1.0/np.linspace(0.1, 10, 1000), color='#1f77b4') plt.title('x轴均匀采样') plt.xlabel('x') plt.ylabel('y=1/x') plt.subplot(1, 2, 2) plt.plot(x_uniform, y_uniform, color='#ff7f0e') plt.title('弧长均匀采样') plt.xlabel('x') plt.ylabel('y=1/x') plt.tight_layout() plt.show()
扩展适配(无解析导数的情况)
如果目标函数的解析导数难以求出,可以用数值导数代替:
# 用数值梯度计算导数 y_dense = f(x_dense) df_dx_num = np.gradient(y_dense, x_dense) ds = np.sqrt(1 + df_dx_num**2)
后续步骤和之前完全一致,这个方法适用于绝大多数可数值计算的函数。
效果说明
用弧长均匀采样后,1/x曲线左侧陡峭区域的采样点会明显增多,右侧平缓区域点会相应减少,整条曲线上相邻点的实际间距(沿曲线的距离)基本一致,解决了分布不均的问题。
内容的提问来源于stack exchange,提问作者Erel Segal-Halevi
相关产品推荐
相关产品推荐

