Python 将曲线样条曲线拟合到三维点云 客观的
我有一个3D刻面模型(例如,关闭文件),例如,它看起来像管道(参见示例图片)。目标是使用python导出近似样条线(线和样条线的最佳组合),该样条线表示此管的三维骨架 目前技术水平 同一字段中的Stackoverflow posts:Python 将曲线样条曲线拟合到三维点云 客观的,python,geometry,spline,Python,Geometry,Spline,我有一个3D刻面模型(例如,关闭文件),例如,它看起来像管道(参见示例图片)。目标是使用python导出近似样条线(线和样条线的最佳组合),该样条线表示此管的三维骨架 目前技术水平 同一字段中的Stackoverflow posts: 概述: PowerCastle/NN外壳?我读过这些,但是我找不到python实现,也许我太笨了,不能自己实现它。据我所知,基础是delaunay/voronoi,我已经知道了。然而,我不知道还有什么进一步的步骤 我的方法(到目前为止) 从示例fac
- PowerCastle/NN外壳?我读过这些,但是我找不到python实现,也许我太笨了,不能自己实现它。据我所知,基础是delaunay/voronoi,我已经知道了。然而,我不知道还有什么进一步的步骤
由于中轴是Voronoi图的子图,因此Delaunay/Voronoi方法可用于此问题 (例如,见Attali、Boissonnat和Edelsbrunner的著作) 在下文中,我将演示从半径为10、半径为100的四分之一圆环曲面(中间路径/骨架从点(100,0,0)开始,到点(0,100,0)结束)采样点的示例方法 Voronoi图是3D Delaunay四面体化的对偶(从现在起,我将使用术语三角剖分)。 可以使用scipy的
scipy.spatial.Delaunay
包计算Delaunay三角剖分
下图是采样点(本例中为200个)及其完整的Delaunay三角剖分
(使用函数绘制三角剖分)。
与Delaunay四面体相对应的Voronoi顶点是四面体的外接球的中心。
下面是一个计算这些Delaunay中心的函数,它是我先前答案中2D函数的扩展
我们希望过滤掉原始曲面之外的四面体(例如上图中的长四面体)。
这可以通过在原始表面上测试四面体来实现。
但是,有一种更简单的方法非常适合输入三维布管曲面
过滤出具有较大外切半径的四面体。
这就是算法所做的。
这在我们的上下文中很容易做到,因为半径就是中心和任何四面体点之间的距离
下图显示了过滤掉半径大于20的四面体后的Delaunay三角剖分
我们现在可以使用这些构建块来构建通过半径条件的四面体的Voronoi子图。
下面的函数使用Delaunay三角剖分中的连通性信息来构造Voronoi子图,表示为边列表
def compute_voronoi_vertices_and_edges(points, r_thresh=np.inf):
"""
Compute (finite) Voronoi edges and vertices of a set of points.
:param points: input points.
:param r_thresh: radius value for filtering out vertices corresponding to
Delaunay tetrahedrons with large radii of circumscribing sphere (alpha-shape condition).
:return: array of xyz Voronoi vertex points and an edge list.
"""
dt = Delaunay(points)
xyz_centers = compute_delaunay_tetra_circumcenters(dt)
# filtering tetrahedrons that have radius > thresh
simp_pts_0 = dt.points[dt.simplices[:, 0]]
radii = np.linalg.norm(xyz_centers - simp_pts_0, axis=1)
is_in = radii < r_thresh
# build an edge list from (filtered) tetrahedrons neighbor relations
edge_lst = []
for i in range(len(dt.neighbors)):
if not is_in[i]:
continue # i is an outside tetra
for j in dt.neighbors[i]:
if j != -1 and is_in[j]:
edge_lst.append((i, j))
return xyz_centers, edge_lst
下图显示了原始200点的结果
这是1000个点的密集样本的结果
现在可以通过路径点传递近似样条插值或最小二乘拟合。
您可以使用链接中建议的scipy.interpolate.UnivariateSpline
或
scipy.interpolate.splrep
完成或任何其他标准样条线实现。曲面模型中的面是否结构化(例如,所有四边形或三角形四边形,其中一条边沿管方向)?我不这么认为,或者至少我不想认为这是理所当然的,因为它描述了另一个边界条件。现在我将在问题中添加我的另一次尝试谢谢@Iddo Hanniel为您所做的巨大努力!这似乎真的很有希望。唯一的问题是必须调整距离参数,但这似乎是一个很好的解决方案。不幸的是,我现在没有太多的空闲时间,我会尽快测试它!你好我不确定如何处理路径的对象。nx.shortest_path返回一个整数列表,该列表的长度大于原始输入数据的长度。这些整数是什么意思?如何得到最后两个图中显示的黑线的坐标?非常感谢。path_对象是xyz_中心数组中的索引列表。因此[xyz_centers[i,:]for i in path_s]应该为您提供黑线的(有序)3d坐标列表。
def compute_voronoi_vertices_and_edges(points, r_thresh=np.inf):
"""
Compute (finite) Voronoi edges and vertices of a set of points.
:param points: input points.
:param r_thresh: radius value for filtering out vertices corresponding to
Delaunay tetrahedrons with large radii of circumscribing sphere (alpha-shape condition).
:return: array of xyz Voronoi vertex points and an edge list.
"""
dt = Delaunay(points)
xyz_centers = compute_delaunay_tetra_circumcenters(dt)
# filtering tetrahedrons that have radius > thresh
simp_pts_0 = dt.points[dt.simplices[:, 0]]
radii = np.linalg.norm(xyz_centers - simp_pts_0, axis=1)
is_in = radii < r_thresh
# build an edge list from (filtered) tetrahedrons neighbor relations
edge_lst = []
for i in range(len(dt.neighbors)):
if not is_in[i]:
continue # i is an outside tetra
for j in dt.neighbors[i]:
if j != -1 and is_in[j]:
edge_lst.append((i, j))
return xyz_centers, edge_lst
# get closest vertex to start and end points
xyz_centers, edge_lst = compute_voronoi_vertices_and_edges(pts, r_thresh=20.)
kdt = cKDTree(xyz_centers)
dist0, idx0 = kdt.query(np.array([100., 0, 0]))
dist1, idx1 = kdt.query(np.array([0, 100., 0]))
# compute shortest weighted path
edge_lengths = [np.linalg.norm(xyz_centers[e[0], :] - xyz_centers[e[1], :]) for e in edge_lst]
g = nx.Graph((i, j, {'weight': dist}) for (i, j), dist in zip(edge_lst, edge_lengths))
path_s = nx.shortest_path(g,source=idx0,target=idx1, weight='weight')