我有一个陀螺仪的STL &我想用一个球体裁剪它(previous question)
现在我已经以正确的方式表示了数据,但是每当我对我的2个对象执行布尔操作时,我都会得到一个空的结果。
import vtk
colors = vtk.vtkNamedColors()
file_name = 'gyroid.stl'
# Load poly from STL
reader = vtk.vtkSTLReader()
reader.SetFileName(file_name)
reader.Update()
polyData = reader.GetOutput()
# Centre of poly
x = (polyData.GetBounds()[1] - polyData.GetBounds()[0]) / 2.0
y = (polyData.GetBounds()[3] - polyData.GetBounds()[2]) / 2.0
z = (polyData.GetBounds()[5] - polyData.GetBounds()[4]) / 2.0
# Set up cropping sphere
sphereSource = vtk.vtkSphereSource()
sphereSource.SetCenter(x, y, z)
sphereSource.SetPhiResolution(41)
sphereSource.SetThetaResolution(41)
sphereSource.SetRadius(63)
sphereSource.Update()
sphere = sphereSource.GetOutput()
# Boolean operations on poly with sphere
booleanOperation = vtk.vtkBooleanOperationPolyDataFilter()
booleanOperation.SetOperationToIntersection()
# booleanOperation.SetOperationToDifference()
# booleanOperation.SetOperationToUnion()
booleanOperation.SetInputData(0, polyData)
booleanOperation.SetInputData(1, sphere)
# # Output result to STL
# stlWriter = vtk.vtkSTLWriter()
# stlWriter.SetFileName("sphere_cropped.stl")
# stlWriter.SetInputConnection(booleanOperation.GetOutputPort())
# stlWriter.Write()
# Set up poly for display
polyDataMapper = vtk.vtkPolyDataMapper()
polyDataMapper.SetInputData(polyData)
polyDataMapper.ScalarVisibilityOff()
polyDataActor = vtk.vtkActor()
polyDataActor.SetMapper(polyDataMapper)
polyDataActor.GetProperty().SetDiffuseColor(colors.GetColor3d('Tomato'))
polyDataActor.GetProperty().SetSpecular(0.6)
polyDataActor.GetProperty().SetSpecularPower(20)
polyDataActor.SetPosition(polyData.GetBounds()[1] - polyData.GetBounds()[0], 0, 0)
# Set up sphere for display
sphereMapper = vtk.vtkPolyDataMapper()
sphereMapper.SetInputData(sphere)
sphereMapper.ScalarVisibilityOff()
sphereActor = vtk.vtkActor()
sphereActor.SetMapper(sphereMapper)
sphereActor.GetProperty().SetDiffuseColor(colors.GetColor3d('Mint'))
sphereActor.GetProperty().SetSpecular(0.6)
sphereActor.GetProperty().SetSpecularPower(20)
sphereActor.SetPosition(-(polyData.GetBounds()[1] - polyData.GetBounds()[0]), 0, 0)
# Set up Boolean result for display
booleanOperationMapper = vtk.vtkPolyDataMapper()
booleanOperationMapper.SetInputConnection(booleanOperation.GetOutputPort())
booleanOperationMapper.ScalarVisibilityOff()
booleanOperationActor = vtk.vtkActor()
booleanOperationActor.SetMapper(booleanOperationMapper)
booleanOperationActor.GetProperty().SetDiffuseColor(colors.GetColor3d('Banana'))
booleanOperationActor.GetProperty().SetSpecular(0.6)
booleanOperationActor.GetProperty().SetSpecularPower(20)
# Display all
renderer = vtk.vtkRenderer()
renderer.AddViewProp(polyDataActor)
renderer.AddViewProp(sphereActor)
renderer.AddViewProp(booleanOperationActor)
renderer.SetBackground(colors.GetColor3d('Silver'))
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindow.SetSize(640, 480)
renderWindow.SetWindowName('BooleanOperationPolyDataFilter')
renWinInteractor = vtk.vtkRenderWindowInteractor()
renWinInteractor.SetRenderWindow(renderWindow)
renderWindow.Render()
renWinInteractor.Start()
我理解陀螺仪是复杂的曲面&想知道这是不是这里的问题所在?在得到合理的答案之前,我是否需要进一步处理多边形数据,或者这只是VTK的布尔运算符不起作用的情况?
生成gyroid.stl
的代码
import numpy as np
from numpy import sin, cos, pi
from skimage import measure
import stl
from stl import mesh
def gyroid(x, y, z, t):
return cos(x)*sin(y) + cos(y)*sin(z) + cos(z)*sin(x) + t
lattice_param = 1.5
strut_param = 0
resolution = 127j
x, y, z = pi*np.mgrid[-1:1:resolution, -1:1:resolution, -1:1:resolution] * lattice_param
vol = gyroid(x, y, z, strut_param)
verts, faces, normals, values = measure.marching_cubes_lewiner(vol, 0, spacing=(0.1, 0.1, 0.1))
data = np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)
gyr_mesh = mesh.Mesh(data, remove_empty_areas=False)
for i, f in enumerate(faces):
for j in range(3):
gyr_mesh.vectors[i][j] = verts[f[j],:] * 10.0
gyr_mesh.save('gyroid.stl')
发布于 2020-12-05 04:03:57
我发布了一个可能的解决方案here。使用布尔过滤器的变体会给出合理的结果:
from vedo import *
import numpy as np
x, y, z = np.mgrid[:30,:30,:30] * 0.4
U = sin(x)*cos(y) + sin(y)*cos(z) + sin(z)*cos(x)
# Create a Volume, take the isosurface at 0 and smooth it
g = Volume(U).isosurface(0).smoothLaplacian()
# Intersect with a sphere
s = Sphere(pos=(15,15,15), r=14, quads=True).triangulate()
gxs = g.boolean('intersect',s).clean().computeNormals()
gxs.color('silver').lighting('metallic')
show([[g,s],gxs], N=2, bg='wheat', bg2='lightblue', axes=5)
https://stackoverflow.com/questions/65129906
复制相似问题