VTK中世界坐标转换为视图坐标的正确实现方法求助
VTK世界坐标转标准化视图坐标解决方案
问题原因
你的现有代码最后将目标坐标系设置为Display,得到的结果是屏幕像素坐标,和你需要的j、k取值在[-1,1]的标准化视图坐标完全不符,所以结果异常。vtkCoordinate确实没有提供GetComputedViewValue()方法直接返回标准化视图坐标,你可以通过以下两种方案实现转换。
解决方法
方案1:直接通过相机变换矩阵计算(最可靠)
直接从渲染器的相机中获取视图、投影变换矩阵,手动计算得到标准化设备坐标,就是你需要的[j,k,t]:
import numpy as np # 待转换的世界坐标点 world_point = np.array([x, y, z, 1.0]) # 获取视图变换矩阵(世界坐标转相机坐标) view_mat = np.array(renderer.GetActiveCamera().GetViewTransformMatrix()) # 获取投影变换矩阵(相机坐标转裁剪坐标) proj_mat = np.array(renderer.GetActiveCamera().GetProjectionTransformMatrix(renderer.GetTiledAspectRatio(), 0, 1)) # 计算总变换矩阵 total_mat = proj_mat @ view_mat # 变换到裁剪坐标 clip_point = total_mat @ world_point # 透视除法得到标准化设备坐标 ndc_point = clip_point / clip_point[3] # 最终结果:j、k范围[-1,1],t为深度值 view_coord = ndc_point[:3]
方案2:通过vtkCoordinate间接转换
先获取视口坐标(x、y范围[0,1]),再归一化到[-1,1]区间:
coordinate = vtk.vtkCoordinate() coordinate.SetCoordinateSystemToWorld() coordinate.SetValue(x, y, z) # 获取视口坐标,返回值[x,y,z],x、y范围[0,1],z为深度值范围[0,1] viewport_coord = coordinate.GetComputedViewportValue(renderer) # 转换为要求的坐标范围 j = viewport_coord[0] * 2 - 1 k = viewport_coord[1] * 2 - 1 # 若需要深度t也适配[-1,1]范围,可改为t = viewport_coord[2] * 2 - 1 t = viewport_coord[2] view_coord = [j, k, t]
注意事项
- 两种方案都需要确保renderer已经执行过至少一次
Render()操作,否则相机变换矩阵未完成计算,会得到错误结果 - 透视投影场景下方案1返回的t是裁剪空间深度,和方案2的视口深度值线性相关,可根据你的使用需求调整深度范围
内容的提问来源于stack exchange,提问作者Junda Zhang
相关产品推荐
相关产品推荐

