生成空集的多边形数据上的 VTK 布尔运算 [英] VTK Boolean operations on poly data producing empty sets

查看:18
本文介绍了生成空集的多边形数据上的 VTK 布尔运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个陀螺仪的 STL &我想用球体裁剪它(

I have an STL of a gyroid & I want to crop it with a sphere (previous question)

Now I have the data represented in the correct manner but whenever I do a Boolean operation on my 2 objects I get an empty result.

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()

I appreciate that gyroids are complex surfaces & was wondering if that was the issue here? Do I need to further process the poly data before I get sensible answers or is this just a case where VTK's Boolean operators dont work?

Code to generate 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')

解决方案

I posted a possible solution here. A variation using the boolean filter gives reasonable results:

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)

这篇关于生成空集的多边形数据上的 VTK 布尔运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆