如何将笛卡尔坐标转为MeshTriPoint以用meshlib计算3D曲面测地线?
3D曲面上两点间测地线路径计算(基于meshlib)
问题描述
需要用Python获取3D曲面上两点间的最短测地线路径坐标,但无法复现有方案,核心问题是不理解meshlib中computeGeodesicPath函数要求的MeshTriPoint格式,不知道如何将笛卡尔坐标转换为该类型。示例代码基于圆柱曲面,希望方案能适配复杂曲面。
解决方案
1. 理解MeshTriPoint格式
MeshTriPoint是meshlib用于定位三角形网格面上任意点的数据类型,包含两个核心信息:
- 该点所在的三角形网格索引(face index)
- 点在该三角形内的重心坐标(barycentric coordinates):用三个权重值表示,权重和为1,对应三角形三个顶点的加权位置。
无需手动计算这些参数,meshlib提供工具函数可直接从笛卡尔坐标转换得到MeshTriPoint。
2. 关键代码修改与完整实现
补充导入meshlib.mrmeshpy模块,使用findNearestPointOnMesh完成坐标格式转换,再调用computeGeodesicPath计算路径,最后提取路径坐标并可视化。
完整代码如下:
import numpy as np import meshlib.mrmeshnumpy as mnp import meshlib.mrmeshpy as mpy # 补充导入mrmeshpy模块 def cyl2cart(rho,phi,z): return rho*np.cos(phi),rho*np.sin(phi),z # cylinder coordinates N = 101 radius = 5 rho = radius*np.ones(N) phi = np.linspace(0,2*np.pi,37) # 10 degree steps z = np.linspace(-10,10,N) # surface grid coordinates x = np.outer(rho,np.cos(phi)) y = np.outer(rho,np.sin(phi)) z = np.outer(z,np.ones(len(phi))) # create mesh mesh = mnp.meshFromUVPoints(x, y, z) # define two points on the surface # point1 rhop = radius phip = -10/180.*np.pi zp = -3 xp1,yp1,zp1 = cyl2cart(rhop, phip, zp) # point2 rhop = radius phip = 60/180.*np.pi zp = 8 xp2,yp2,zp2 = cyl2cart(rhop, phip, zp) # --- 核心修改部分 --- # 将笛卡尔坐标转为meshlib兼容的Vector3d格式 p1_cart = mpy.Vector3d(xp1, yp1, zp1) p2_cart = mpy.Vector3d(xp2, yp2, zp2) # 找到网格上最近的点,返回MeshTriPoint类型 p1 = mpy.findNearestPointOnMesh(mesh, p1_cart).point p2 = mpy.findNearestPointOnMesh(mesh, p2_cart).point # 计算测地线路径 geodesic_path = mpy.computeGeodesicPath(mesh, p1, p2) # 提取路径的笛卡尔坐标 path_points = [] for tri_point in geodesic_path.points: # 将MeshTriPoint转换为笛卡尔坐标 world_point = mpy.toWorldSpace(tri_point, mesh) path_points.append([world_point.x, world_point.y, world_point.z]) path_points = np.array(path_points) # --- 核心修改结束 --- #%% 绘图展示(包含测地线路径) import plotly.graph_objects as go # extract numpy arrays verts = mnp.getNumpyVerts(mesh) faces = mnp.getNumpyFaces(mesh.topology) # prepare data for plotly vertsT = np.transpose(verts) facesT = np.transpose(faces) # draw fig = go.Figure(data=[ go.Mesh3d( x = vertsT[0], y = vertsT[1], z = vertsT[2], i = facesT[0], j = facesT[1], k = facesT[2], opacity=0.5 # 调整透明度方便查看路径 ) ]) # 添加原始两点标记 fig.add_trace(go.Scatter3d(x=[xp1,xp2],y=[yp1,yp2],z=[zp1,zp2],mode='markers',marker={'size':8,'symbol':'circle'})) # 添加测地线路径 fig.add_trace(go.Scatter3d(x=path_points[:,0], y=path_points[:,1], z=path_points[:,2], mode='lines', line={'color':'red','width':3})) fig.update_layout(scene=dict(aspectmode='data')) fig.show(renderer='browser')
3. 核心函数说明
mpy.Vector3d:将笛卡尔坐标转换为meshlib兼容的向量格式findNearestPointOnMesh:输入网格和目标点,返回包含MeshTriPoint的结果对象,确保点严格落在网格面上computeGeodesicPath:输入两个MeshTriPoint,返回包含测地线路径点列表的结果对象toWorldSpace:将MeshTriPoint转换回笛卡尔坐标,方便后续可视化或计算
4. 复杂曲面适配
该方案无需修改核心逻辑即可适配任意三角形网格曲面,只需确保输入的mesh是合法的三角形网格对象,且目标点在曲面附近(findNearestPointOnMesh会自动吸附到最近的网格面)。
内容的提问来源于stack exchange,提问作者QuantumKicked
相关产品推荐
相关产品推荐

