如何使用Python或numpy实现沿路径移动连通点并输出新点集
实现方案(纯numpy实现,效率更高)
前置假设输入结构
- 所有路径存储为
list[np.ndarray],每个路径数组shape为(路径顶点数, 2),按路径连通顺序存储顶点x/y坐标 - 待移动点的属性存储为三个同长数组:
point_path_idx:shape为(点总数,), 每个元素对应点所属的路径索引point_t:shape为(点总数,), 每个元素是对应点在所属路径上的归一化位置参数,取值范围[0, 1],0对应路径起点,1对应路径终点move_step:shape为(点总数,), 每个元素是对应点单次移动的归一化步长,正数沿路径正向移动,负数反向移动
核心代码
import numpy as np def move_points_along_paths(paths: list[np.ndarray], point_path_idx: np.ndarray, point_t: np.ndarray, move_step: np.ndarray, loop: bool=False) -> tuple[np.ndarray, np.ndarray]: """ 沿路径移动点,返回新的点坐标和更新后的位置参数t :param loop: 点移动到路径端点后是否循环,False则停在端点,True则从另一端重新进入 """ num_points = len(point_path_idx) new_points = np.zeros((num_points, 2), dtype=np.float32) new_point_t = np.clip(point_t + move_step, 0.0, 1.0) if not loop else (point_t + move_step) % 1.0 # 预计算所有路径的归一化累计长度和各段向量 path_cum_lens = [] path_seg_vecs = [] for path in paths: seg_vec = np.diff(path, axis=0) seg_len = np.linalg.norm(seg_vec, axis=1) cum_len = np.concatenate([[0], np.cumsum(seg_len)]) norm_cum_len = cum_len / cum_len[-1] path_cum_lens.append(norm_cum_len) path_seg_vecs.append(seg_vec) # 逐点插值计算新坐标 for i in range(num_points): path_idx = point_path_idx[i] t = new_point_t[i] path = paths[path_idx] norm_cum_len = path_cum_lens[path_idx] seg_vec = path_seg_vecs[path_idx] # 匹配t对应的路径段 seg_idx = np.searchsorted(norm_cum_len, t, side='right') - 1 seg_idx = np.clip(seg_idx, 0, len(norm_cum_len)-2) # 计算段内插值比例 seg_t = (t - norm_cum_len[seg_idx]) / (norm_cum_len[seg_idx+1] - norm_cum_len[seg_idx]) # 得到新坐标 new_points[i] = path[seg_idx] + seg_t * seg_vec[seg_idx] return new_points, new_point_t
调用示例
# 测试:创建两条L型路径 path1 = np.array([[0,0], [10,0], [10,10]], dtype=np.float32) path2 = np.array([[0,10], [10,10], [10,0]], dtype=np.float32) paths = [path1, path2] # 测试点:2个点分别属于两条路径,初始位置为路径的0.2处,单次移动步长0.1 point_path_idx = np.array([0, 1], dtype=np.int32) point_t = np.array([0.2, 0.2], dtype=np.float32) move_step = np.array([0.1, 0.1], dtype=np.float32) new_coords, new_t = move_points_along_paths(paths, point_path_idx, point_t, move_step) print("移动后的点坐标:\n", new_coords)
如果你没有提前标注每个点所属的路径和初始位置t,可以额外加一步投影匹配:对每个点遍历所有路径的线段,计算点到线段的最短距离,找到距离最小的线段所属的路径,再计算投影点对应的归一化t值即可,该步骤也可纯numpy实现。
内容的提问来源于stack exchange,提问作者Tortenrandband
相关产品推荐
相关产品推荐

