我想使用 Python 获取 3D 表面上两点之间的最短(测地线)路径的路径坐标。该解决方案已经以某种方式显示在这篇文章中接受的答案中,但是,我无法重现 Fedor 的结果,因为我不理解 meshlib 期望提供点位置的格式。
测地线路径计算是使用computeGeodesicPath函数完成的,该函数需要MeshTriPoints作为输入。不幸的是,我不明白这种格式是如何工作的以及如何从笛卡尔点坐标转换为它。这是一个简单的圆柱形 3D 表面的示例,但我希望它也能够在更复杂的表面上工作。
import numpy as np
import meshlib.mrmeshnumpy as mnp
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)
# This part is not working because I don't understand how to provide the point coordinates
# p1 = mpy.MeshTriPoint(??)
# p2 = mpy.MeshTriPoint(??)
# mpy.computeGeodesicPath(mesh, p1, p2)
#%% optional plot with plotly
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]
)
])
fig.add_trace(go.Scatter3d(x=[xp1,xp2],y=[yp1,yp2],z=[zp1,zp2],mode='markers',marker={'size':8,'symbol':'circle'}))
fig.update_layout(scene=dict(aspectmode='data'))
fig.show(renderer='browser')
mpy.MeshTriPoint
是附加到网格对象的点。要从笛卡尔点获得mpy.MeshTriPoint
,将世界点投影到网格并找到相应的MeshTriPoint:
from meshlib import mrmeshpy as mm
mesh = mm.makeSphere( mm.SphereParams() ) # simple mesh for example
startPoint = mm.Vector3f(-1,-1,-1) # cartesian start coordinate
stopPoint = mm.Vector3f(1,1,1) # cartesian stop coordinate
# find corresponding MeshTriPoints
startMtp = mm.findProjection( startPoint, mesh).mtp
stopMtp = mm.findProjection( stopPoint, mesh).mtp
path = mm.computeGeodesicPath(mesh,startMtp,stopMtp,mm.GeodesicPathApprox.DijkstraBiDir)
# print path
for p in path:
pc = mesh.edgePoint(p)
print(pc.x,pc.y,pc.z)