如何在不翻译的情况下在 vtk 中缩放 PolyData?
How to scale a PolyData in vtk without translating it?
我在 python 中使用 VTK 导入 .stl 文件。那么我想做的就是在不改变方向矩阵的情况下缩小网格并使其变小。
我尝试 vtkTransform
使用缩放元组,但问题是缩放的多数据正在旋转。
代码如下:
def scaleSTL(filenameSTL, opacity=0.75, scale=(1,1,1), mesh_color="gold"):
colors = vtk.vtkNamedColors()
reader = vtk.vtkSTLReader()
reader.SetFileName(filenameSTL)
reader.Update()
transform = vtk.vtkTransform()
transform.Scale(scale)
transformFilter = vtk.vtkTransformPolyDataFilter()
transformFilter.SetInputConnection(reader.GetOutputPort())
transformFilter.SetTransform(transform)
transformFilter.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(transformFilter.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d(mesh_color))
actor.GetProperty().SetOpacity(opacity)
return actor
def render_scene(my_actor_list):
renderer = vtk.vtkRenderer()
for arg in my_actor_list:
renderer.AddActor(arg)
namedColors = vtk.vtkNamedColors()
renderer.SetBackground(namedColors.GetColor3d("SlateGray"))
window = vtk.vtkRenderWindow()
window.SetWindowName("Oriented Cylinder")
window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(window)
# Visualize
window.Render()
interactor.Start()
if __name__ == "__Main__":
filename = "400_tri.stl"
scale01 = (1, 1, 1)
scale02 = (0.5, 0.5, 0.5)
my_list = []
my_list.append(scaleSTL(filename, 0.75, scale01, "Gold"))
my_list.append(scaleSTL(filename, 0.75, scale02, "DarkGreen"))
render_scene(my_list)
我使用了我的网格文件 kidney.stl
(黄色文件),但我得到的是缩放和旋转的网格。我将不透明度设置为 0.75 以查看两个网格。在下图中,您可以看到绿色的完全移动了,但我想缩放绿色的完全在原来的黄色网格内。
可以在这里找到简单的答案(没有解释):Scaling 3D models, finding the origin
这是因为缩放变换被简单地定义为将坐标乘以给定因子(参见 https://www.tutorialspoint.com/computer_graphics/3d_transformation.htm)。这本质上意味着它是相对于某个参考点完成的。您的 transform.Scale() 调用将使用原点 (0,0,0) 作为参考点,并且由于您的对象显然不以原点为中心,因此您会得到平移(不是您声称的旋转)。
要获得局部居中缩放,您需要在要围绕其缩放的对象上选择一个参考点 R(在您的情况下,由于您希望缩放后的对象位于原始对象内部,因此您需要某种中心 - 因为对象是 "almost convex",质心 - 所有点的平均值 - 可能就足够了)。通过 -R 平移对象以使其与坐标系对齐,缩放然后通过 +R 平移回来。
尝试一个小练习来形象化:简单的二维示例 - 给自己画一个由坐标为 (2,2)、(2,3)、(3,3)、(3,2) 和"scale it by 2" - 你得到 (4,4), (4,6),(6,6), (6,4) - 也绘制它。现在尝试替代方案 - 首先通过正方形的中心 (2.5,2.5) 平移,你得到 (-0.5,-0.5), (-0.5,0.5), (0.5,0.5), (0.5,-0.5) (画出来) , 按二缩放,你得到 (-1,-1), (-1, 1), (1,1), (1,-1) (draw) 最后平移 2.5: (1.5, 1.5), (1.5,3.5), (3.5,3.5), (3.5, 1.5) 和绘制 - 看出区别了吗?
我在 python 中使用 VTK 导入 .stl 文件。那么我想做的就是在不改变方向矩阵的情况下缩小网格并使其变小。
我尝试 vtkTransform
使用缩放元组,但问题是缩放的多数据正在旋转。
代码如下:
def scaleSTL(filenameSTL, opacity=0.75, scale=(1,1,1), mesh_color="gold"):
colors = vtk.vtkNamedColors()
reader = vtk.vtkSTLReader()
reader.SetFileName(filenameSTL)
reader.Update()
transform = vtk.vtkTransform()
transform.Scale(scale)
transformFilter = vtk.vtkTransformPolyDataFilter()
transformFilter.SetInputConnection(reader.GetOutputPort())
transformFilter.SetTransform(transform)
transformFilter.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(transformFilter.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d(mesh_color))
actor.GetProperty().SetOpacity(opacity)
return actor
def render_scene(my_actor_list):
renderer = vtk.vtkRenderer()
for arg in my_actor_list:
renderer.AddActor(arg)
namedColors = vtk.vtkNamedColors()
renderer.SetBackground(namedColors.GetColor3d("SlateGray"))
window = vtk.vtkRenderWindow()
window.SetWindowName("Oriented Cylinder")
window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(window)
# Visualize
window.Render()
interactor.Start()
if __name__ == "__Main__":
filename = "400_tri.stl"
scale01 = (1, 1, 1)
scale02 = (0.5, 0.5, 0.5)
my_list = []
my_list.append(scaleSTL(filename, 0.75, scale01, "Gold"))
my_list.append(scaleSTL(filename, 0.75, scale02, "DarkGreen"))
render_scene(my_list)
我使用了我的网格文件 kidney.stl
(黄色文件),但我得到的是缩放和旋转的网格。我将不透明度设置为 0.75 以查看两个网格。在下图中,您可以看到绿色的完全移动了,但我想缩放绿色的完全在原来的黄色网格内。
可以在这里找到简单的答案(没有解释):Scaling 3D models, finding the origin
这是因为缩放变换被简单地定义为将坐标乘以给定因子(参见 https://www.tutorialspoint.com/computer_graphics/3d_transformation.htm)。这本质上意味着它是相对于某个参考点完成的。您的 transform.Scale() 调用将使用原点 (0,0,0) 作为参考点,并且由于您的对象显然不以原点为中心,因此您会得到平移(不是您声称的旋转)。
要获得局部居中缩放,您需要在要围绕其缩放的对象上选择一个参考点 R(在您的情况下,由于您希望缩放后的对象位于原始对象内部,因此您需要某种中心 - 因为对象是 "almost convex",质心 - 所有点的平均值 - 可能就足够了)。通过 -R 平移对象以使其与坐标系对齐,缩放然后通过 +R 平移回来。
尝试一个小练习来形象化:简单的二维示例 - 给自己画一个由坐标为 (2,2)、(2,3)、(3,3)、(3,2) 和"scale it by 2" - 你得到 (4,4), (4,6),(6,6), (6,4) - 也绘制它。现在尝试替代方案 - 首先通过正方形的中心 (2.5,2.5) 平移,你得到 (-0.5,-0.5), (-0.5,0.5), (0.5,0.5), (0.5,-0.5) (画出来) , 按二缩放,你得到 (-1,-1), (-1, 1), (1,1), (1,-1) (draw) 最后平移 2.5: (1.5, 1.5), (1.5,3.5), (3.5,3.5), (3.5, 1.5) 和绘制 - 看出区别了吗?