def CylinderVtuCut(inputVtu, radius, origin = (0.0, 0.0, 0.0), axis = (0.0, 0.0, 1.0)): """ Perform a 3D cylinder cut of a vtu """ assert(len(origin) == 3) assert(len(axis) == 3) # An implicit function with which to cut cylinder = vtk.vtkCylinder() cylinder.SetRadius(radius) cylinder.SetCenter((0.0, 0.0, 0.0)) # Generate the transform transform = vtk.vtkTransform() transform.Identity() if not calc.AlmostEquals(axis[0], 0.0) or not calc.AlmostEquals(axis[1], 1.0) or not calc.AlmostEquals(axis[2], 0.0): # Find the rotation axis # (0, 1, 0) x axis rotationAxis = [-axis[2], 0.0, -axis[0]] # Normalise rotationAxisMagnitude = calc.L2Norm(rotationAxis) rotationAxis = [val / rotationAxisMagnitude for val in rotationAxis] # Find the rotation angle angle = calc.Rad2Deg(math.acos(axis[1] / calc.L2Norm(axis))) # Rotation transform.RotateWXYZ(angle, rotationAxis[0], rotationAxis[1], rotationAxis[2]) # Translation transform.Translate(origin[0], origin[1], origin[2]) # Set the transform cylinder.SetTransform(transform) return ImplicitFunctionVtuCut(inputVtu, cylinder)
def createVtkCylinder(**kwargs): ''' Create a vtk cylinder Keyword arguments: :origin (tuple/list/np-array): Origin of the cylinder :axis (tuple/list/np-array): Cylinder axis :radius (float): Cylinder radius ''' origin = np.array(kwargs.get('origin', [0, 0, 0])) axis = np.array(kwargs.get('axis', [0, 0, 1])) radius = np.array(kwargs.get('radius', 1)) cylinder = vtk.vtkCylinder() cylinder.SetCenter(0, 0, 0) cylinder.SetRadius(radius) # The cylinder is (by default) aligned with the y-axis # Rotate the cylinder so that it is aligned with the tangent vector transform = vtk.vtkTransform() yDir = np.array([0, 1, 0]) # If the tangent is in the y-direction, do nothing if np.abs(1. - np.abs(np.dot(yDir, axis))) > 1e-8: # Create a vector in the normal direction to the plane spanned by yDir and the tangent rotVec = np.cross(yDir, axis) rotVec /= np.linalg.norm(rotVec) # Evaluate rotation angle rotAngle = np.arccos(np.dot(yDir, axis)) transform.RotateWXYZ(old_div(-180*rotAngle,np.pi), rotVec) transform.Translate(-origin) cylinder.SetTransform(transform) return cylinder
def __init__(self, parent = None): super(VTKFrame, self).__init__(parent) self.vtkWidget = QVTKRenderWindowInteractor(self) vl = QtGui.QVBoxLayout(self) vl.addWidget(self.vtkWidget) vl.setContentsMargins(0, 0, 0, 0) self.ren = vtk.vtkRenderer() self.vtkWidget.GetRenderWindow().AddRenderer(self.ren) self.iren = self.vtkWidget.GetRenderWindow().GetInteractor() # Create cylinder cylinder = vtk.vtkCylinder() cylinder.SetCenter(0, 0, 0) cylinder.SetRadius(1.0) # Create plane plane = vtk.vtkPlane() plane.SetOrigin(0, 0, 0) plane.SetNormal(0, -1, 0) # Cut the cylinder cuted_cylinder = vtk.vtkImplicitBoolean() cuted_cylinder.SetOperationTypeToIntersection() #cuted_cylinder.SetOperationTypeToUnion() cuted_cylinder.AddFunction(cylinder) cuted_cylinder.AddFunction(plane) # Sample sample = vtk.vtkSampleFunction() sample.SetImplicitFunction(cuted_cylinder) sample.SetModelBounds(-1.5 , 1.5 , -1.5 , 1.5 , -1.5 , 1.5) sample.SetSampleDimensions(60, 60, 60) sample.SetComputeNormals(0) # surface = vtk.vtkContourFilter() #surface.SetInput(sample.GetOutput()) surface.SetInputConnection(sample.GetOutputPort()) # Create a mapper mapper = vtk.vtkPolyDataMapper() #mapper.SetInput(surface.GetOutput()) mapper.SetInputConnection(surface.GetOutputPort()) # Create an actor actor = vtk.vtkActor() actor.SetMapper(mapper) self.ren.AddActor(actor) self.ren.ResetCamera() self._initialized = False
def __init__(self, geom, ident=None): self.src = vtkContourFilter() ODE_Object.__init__(self, geom, ident) (radius, height) = geom.getParams() cylinder = vtkCylinder() cylinder.SetRadius(radius) vertPlane = vtkPlane() vertPlane.SetOrigin(0, height / 2, 0) vertPlane.SetNormal(0, 1, 0) basePlane = vtkPlane() basePlane.SetOrigin(0, -height / 2, 0) basePlane.SetNormal(0, -1, 0) sphere_1 = vtkSphere() sphere_1.SetCenter(0, -height / 2, 0) sphere_1.SetRadius(radius) sphere_2 = vtkSphere() sphere_2.SetCenter(0, height / 2, 0) sphere_2.SetRadius(radius) # Combine primitives, Clip the cone with planes. cylinder_fct = vtkImplicitBoolean() cylinder_fct.SetOperationTypeToIntersection() cylinder_fct.AddFunction(cylinder) cylinder_fct.AddFunction(vertPlane) cylinder_fct.AddFunction(basePlane) # Take a bite out of the ice cream. capsule = vtkImplicitBoolean() capsule.SetOperationTypeToUnion() capsule.AddFunction(cylinder_fct) capsule.AddFunction(sphere_1) capsule.AddFunction(sphere_2) capsule_fct = vtkSampleFunction() capsule_fct.SetImplicitFunction(capsule) capsule_fct.ComputeNormalsOff() capsule_fct.SetModelBounds(-height - radius, height + radius, -height - radius, height + radius, -height - radius, height + radius) self.src.SetInputConnection(capsule_fct.GetOutputPort()) self.src.SetValue(0, 0.0)
def testStructured2D(self): planes = ['XY', 'XZ', 'YZ'] expectedNCells = [42, 34, 68] for plane, nCells in zip(planes,expectedNCells): rt = vtk.vtkRTAnalyticSource() if plane == 'XY': rt.SetWholeExtent(-5, 5, -5, 5, 0, 0) elif plane == 'XZ': rt.SetWholeExtent(-5, 5, 0, 0, -5, 5) else: rt.SetWholeExtent(0, 0, -5, 5, -5, 5) rt.Update() i = rt.GetOutput() st = vtk.vtkStructuredGrid() st.SetDimensions(i.GetDimensions()) nps = i.GetNumberOfPoints() ps = vtk.vtkPoints() ps.SetNumberOfPoints(nps) for idx in range(nps): ps.SetPoint(idx, i.GetPoint(idx)) st.SetPoints(ps) cyl = vtk.vtkCylinder() cyl.SetRadius(2) cyl.SetCenter(0,0,0) transform = vtk.vtkTransform() transform.RotateWXYZ(45,20,1,10) cyl.SetTransform(transform) c = vtk.vtkTableBasedClipDataSet() c.SetInputData(st) c.SetClipFunction(cyl) c.SetInsideOut(1) c.Update() self.assertEqual(c.GetOutput().GetNumberOfCells(), nCells)
def cylinderclip(dataset, point0, point1,normal,radius): """Define cylinder. The cylinder is infinite in extent. We therefore have to truncate the cylinder using vtkImplicitBoolean in combination with 2 clipping planes located at point0 and point1. The radius of the cylinder is set to be slightly larger than 'maxradius'.""" rotationaxis = cross([0, 1, 0], normal) rotationangle = (180 / math.pi) * angle([0, 1, 0], normal) transform = vtk.vtkTransform() transform.Translate(point0) transform.RotateWXYZ(rotationangle, rotationaxis) transform.Inverse() cylinder = vtk.vtkCylinder() cylinder.SetRadius(radius) cylinder.SetTransform(transform) plane0 = vtk.vtkPlane() plane0.SetOrigin(point0) plane0.SetNormal([-x for x in normal]) plane1 = vtk.vtkPlane() plane1.SetOrigin(point1) plane1.SetNormal(normal) clipfunction = vtk.vtkImplicitBoolean() clipfunction.SetOperationTypeToIntersection() clipfunction.AddFunction(cylinder) clipfunction.AddFunction(plane0) clipfunction.AddFunction(plane1) clipper = vtk.vtkClipPolyData() clipper.SetInputData(dataset) clipper.SetClipFunction(clipfunction) clipper.Update() return extractlargestregion(clipper.GetOutput())
def CylinderVtuCut(inputVtu, radius, origin=(0.0, 0.0, 0.0), axis=(0.0, 0.0, 1.0)): """ Perform a 3D cylinder cut of a vtu """ assert (len(origin) == 3) assert (len(axis) == 3) # An implicit function with which to cut cylinder = vtk.vtkCylinder() cylinder.SetRadius(radius) cylinder.SetCenter((0.0, 0.0, 0.0)) # Generate the transform transform = vtk.vtkTransform() transform.Identity() if not calc.AlmostEquals(axis[0], 0.0) or not calc.AlmostEquals( axis[1], 1.0) or not calc.AlmostEquals(axis[2], 0.0): # Find the rotation axis # (0, 1, 0) x axis rotationAxis = [-axis[2], 0.0, -axis[0]] # Normalise rotationAxisMagnitude = calc.L2Norm(rotationAxis) rotationAxis = [val / rotationAxisMagnitude for val in rotationAxis] # Find the rotation angle angle = calc.Rad2Deg(math.acos(axis[1] / calc.L2Norm(axis))) # Rotation transform.RotateWXYZ(angle, rotationAxis[0], rotationAxis[1], rotationAxis[2]) # Translation transform.Translate(origin[0], origin[1], origin[2]) # Set the transform cylinder.SetTransform(transform) return ImplicitFunctionVtuCut(inputVtu, cylinder)
iren.SetRenderWindow(renWin) # Create a synthetic source: sample a sphere across a volume sphere = vtk.vtkSphere() sphere.SetCenter( 0.0,0.0,0.0) sphere.SetRadius(0.25) sample = vtk.vtkSampleFunction() sample.SetImplicitFunction(sphere) sample.SetModelBounds(-0.5,0.5, -0.5,0.5, -0.5,0.5) sample.SetSampleDimensions(res,res,res) sample.ComputeNormalsOff() sample.Update() # Now create some new attributes to interpolate cyl = vtk.vtkCylinder() cyl.SetRadius(0.1) cyl.SetAxis(1,1,1) attr = vtk.vtkSampleImplicitFunctionFilter() attr.SetInputConnection(sample.GetOutputPort()) attr.SetImplicitFunction(cyl) attr.ComputeGradientsOn() attr.Update() # The cut plane plane = vtk.vtkPlane() plane.SetOrigin(-.2,-.2,-.2) plane.SetNormal(1,1,1) # Perform the cutting on named scalars
def getModelROIStencil(self): import time _t0 = time.time() t1 = self.__Transform.GetInverse() roi_type = self.getModelROIType() roi_orientation = self.getModelROIOrientation() # bounds, extent and center b = self.getModelROIBounds() # abort early if we haven't been fully set up yet if b is None: return None # determine transformed boundary _index = [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5]] b_t = [1e38, -1e38, 1e38, -1e38, 1e38, -1e38] is_identity = True # is transform identity? is_identity = self.__Transform.GetMatrix().Determinant() == 1.0 # is_identity = False for i in range(8): i2 = _index[i] pt = [b[i2[0]], b[i2[1]], b[i2[2]]] _temp = self.__Transform.TransformPoint(pt[0], pt[1], pt[2]) b_t[0] = min(_temp[0], b_t[0]) b_t[1] = max(_temp[0], b_t[1]) b_t[2] = min(_temp[1], b_t[2]) b_t[3] = max(_temp[1], b_t[3]) b_t[4] = min(_temp[2], b_t[4]) b_t[5] = max(_temp[2], b_t[5]) e_t = self._BoundsToExtent(b_t) # sanity check - check for inversion (caused by negative spacing) e_t = list(e_t) for i in range(3): if e_t[i * 2] > e_t[i * 2 + 1]: v = e_t[i * 2] e_t[i * 2] = e_t[i * 2 + 1] e_t[i * 2 + 1] = v # expand stencil extent by one pixel on all sides e_t = (e_t[0] - 1, e_t[1] + 1, e_t[2] - 1, e_t[3] + 1, e_t[4] - 1, e_t[5] + 1) # make sure we're dealing with ints e_t = map(int, e_t) if is_identity: # fast, but limited to canonical objects self._StencilGenerator = vtk.vtkROIStencilSource() else: # slow, but more generic self._StencilGenerator = vtk.vtkImplicitFunctionToImageStencil() self._StencilGenerator.SetOutputOrigin(self.getImageOrigin()) self._StencilGenerator.SetOutputSpacing(self.getImageSpacing()) # set extent of stencil - taking into account transformation self._StencilGenerator.SetOutputWholeExtent(e_t) if is_identity: # use DG's fast routines if roi_type == "box": self._StencilGenerator.SetShapeToBox() elif roi_type == "cylinder": if roi_orientation == "X": self._StencilGenerator.SetShapeToCylinderX() elif roi_orientation == "Y": self._StencilGenerator.SetShapeToCylinderY() elif roi_orientation == "Z": self._StencilGenerator.SetShapeToCylinderZ() elif roi_type == "ellipsoid": self._StencilGenerator.SetShapeToEllipsoid() self._StencilGenerator.SetBounds(b) else: # use JG's slow routines if roi_type == "box": obj = vtk.vtkBox() obj.SetTransform(t1) obj.SetBounds(b) elif roi_type == "cylinder": cyl = vtk.vtkCylinder() cyl.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = (b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) # The cylinder is infinite in extent, so needs to be cropped by using the intersection # of three implicit functions -- the cylinder, and two cropping # planes obj = vtk.vtkImplicitBoolean() obj.SetOperationTypeToIntersection() obj.AddFunction(cyl) clip1 = vtk.vtkPlane() clip1.SetNormal(0, 1, 0) obj.AddFunction(clip1) clip2 = vtk.vtkPlane() clip2.SetNormal(0, -1, 0) obj.AddFunction(clip2) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) if roi_orientation == "X": # cylinder is infinite in extent in the y-axis t2.Scale(1, diam_b / 2.0, diam_c / 2.0) t2.RotateZ(90) r = diam_a / 2.0 elif roi_orientation == "Y": # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, 1, diam_c / 2.0) r = diam_b / 2.0 elif roi_orientation == "Z": # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, diam_b / 2.0, 1) t2.RotateX(90) r = diam_c / 2.0 clip1.SetOrigin(0, r, 0) clip2.SetOrigin(0, -r, 0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) elif roi_type == "ellipsoid": obj = vtk.vtkSphere() obj.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = (b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) t2.Scale(diam_a / 2.0, diam_b / 2.0, diam_c / 2.0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) self._StencilGenerator.SetInput(obj) _t1 = time.time() self._StencilGenerator.Update() _t2 = time.time() return self._StencilGenerator.GetOutput()
def getModelROIStencil(self): import time _t0 = time.time() t1 = self.__Transform.GetInverse() roi_type = self.getModelROIType() roi_orientation = self.getModelROIOrientation() # bounds, extent and center b = self.getModelROIBounds() # abort early if we haven't been fully set up yet if b is None: return None # determine transformed boundary _index = [ [0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], ] b_t = [1e38, -1e38, 1e38, -1e38, 1e38, -1e38] is_identity = True # is transform identity? is_identity = self.__Transform.GetMatrix().Determinant() == 1.0 #is_identity = False for i in range(8): i2 = _index[i] pt = [b[i2[0]], b[i2[1]], b[i2[2]]] _temp = self.__Transform.TransformPoint(pt[0], pt[1], pt[2]) b_t[0] = min(_temp[0], b_t[0]) b_t[1] = max(_temp[0], b_t[1]) b_t[2] = min(_temp[1], b_t[2]) b_t[3] = max(_temp[1], b_t[3]) b_t[4] = min(_temp[2], b_t[4]) b_t[5] = max(_temp[2], b_t[5]) e_t = self._BoundsToExtent(b_t) # sanity check - check for inversion (caused by negative spacing) e_t = list(e_t) for i in range(3): if e_t[i * 2] > e_t[i * 2 + 1]: v = e_t[i * 2] e_t[i * 2] = e_t[i * 2 + 1] e_t[i * 2 + 1] = v # expand stencil extent by one pixel on all sides e_t = (e_t[0] - 1, e_t[1] + 1, e_t[2] - 1, e_t[3] + 1, e_t[4] - 1, e_t[5] + 1) # make sure we're dealing with ints e_t = map(int, e_t) if is_identity: # fast, but limited to canonical objects self._StencilGenerator = vtk.vtkROIStencilSource() else: # slow, but more generic self._StencilGenerator = vtk.vtkImplicitFunctionToImageStencil() self._StencilGenerator.SetOutputOrigin(self.getImageOrigin()) self._StencilGenerator.SetOutputSpacing(self.getImageSpacing()) # set extent of stencil - taking into account transformation self._StencilGenerator.SetOutputWholeExtent(e_t) if is_identity: # use DG's fast routines if roi_type == 'box': self._StencilGenerator.SetShapeToBox() elif roi_type == 'cylinder': if roi_orientation == 'X': self._StencilGenerator.SetShapeToCylinderX() elif roi_orientation == 'Y': self._StencilGenerator.SetShapeToCylinderY() elif roi_orientation == 'Z': self._StencilGenerator.SetShapeToCylinderZ() elif roi_type == 'ellipsoid': self._StencilGenerator.SetShapeToEllipsoid() self._StencilGenerator.SetBounds(b) else: # use JG's slow routines if roi_type == 'box': obj = vtk.vtkBox() obj.SetTransform(t1) obj.SetBounds(b) elif roi_type == 'cylinder': cyl = vtk.vtkCylinder() cyl.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * \ 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = ( b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) # The cylinder is infinite in extent, so needs to be cropped by using the intersection # of three implicit functions -- the cylinder, and two cropping # planes obj = vtk.vtkImplicitBoolean() obj.SetOperationTypeToIntersection() obj.AddFunction(cyl) clip1 = vtk.vtkPlane() clip1.SetNormal(0, 1, 0) obj.AddFunction(clip1) clip2 = vtk.vtkPlane() clip2.SetNormal(0, -1, 0) obj.AddFunction(clip2) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) if roi_orientation == 'X': # cylinder is infinite in extent in the y-axis t2.Scale(1, diam_b / 2.0, diam_c / 2.0) t2.RotateZ(90) r = diam_a / 2.0 elif roi_orientation == 'Y': # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, 1, diam_c / 2.0) r = diam_b / 2.0 elif roi_orientation == 'Z': # cylinder is infinite in extent in the y-axis t2.Scale(diam_a / 2.0, diam_b / 2.0, 1) t2.RotateX(90) r = diam_c / 2.0 clip1.SetOrigin(0, r, 0) clip2.SetOrigin(0, -r, 0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) elif roi_type == 'ellipsoid': obj = vtk.vtkSphere() obj.SetRadius(1.0) xc, yc, zc = (b[1] + b[0]) * \ 0.5, (b[3] + b[2]) * 0.5, (b[5] + b[4]) * 0.5 diam_a, diam_b, diam_c = ( b[1] - b[0]), (b[3] - b[2]), (b[5] - b[4]) t2 = vtk.vtkTransform() t2.Translate(xc, yc, zc) t2.Scale(diam_a / 2.0, diam_b / 2.0, diam_c / 2.0) # combine transforms t2.SetInput(self.__Transform) obj.SetTransform(t2.GetInverse()) self._StencilGenerator.SetInput(obj) _t1 = time.time() self._StencilGenerator.Update() _t2 = time.time() return self._StencilGenerator.GetOutput()
def main(): # vtkFlyingEdges3D was introduced in VTK >= 8.2 use_flying_edges = vtk_version_ok(8, 2, 0) colors = vtk.vtkNamedColors() sample_resolution = get_program_parameters() # Create a sampled sphere implicit_sphere = vtk.vtkSphere() radius = 1.0 implicit_sphere.SetRadius(radius) sampled_sphere = vtk.vtkSampleFunction() sampled_sphere.SetSampleDimensions(sample_resolution, sample_resolution, sample_resolution) x_min = -radius * 2.0 x_max = radius * 2.0 sampled_sphere.SetModelBounds(x_min, x_max, x_min, x_max, x_min, x_max) sampled_sphere.SetImplicitFunction(implicit_sphere) if use_flying_edges: try: iso_sphere = vtk.vtkFlyingEdges3D() except AttributeError: iso_sphere = vtk.vtkMarchingCubes() else: iso_sphere = vtk.vtkMarchingCubes() iso_sphere.SetValue(0, 1.0) iso_sphere.SetInputConnection(sampled_sphere.GetOutputPort()) # Create a sampled cylinder implicit_cylinder = vtk.vtkCylinder() implicit_cylinder.SetRadius(radius / 2.0) sampled_cylinder = vtk.vtkSampleFunction() sampled_cylinder.SetSampleDimensions(sample_resolution, sample_resolution, sample_resolution) sampled_cylinder.SetModelBounds(x_min, x_max, x_min, x_max, x_min, x_max) sampled_cylinder.SetImplicitFunction(implicit_cylinder) # Probe cylinder with the sphere isosurface probe_cylinder = vtk.vtkProbeFilter() probe_cylinder.SetInputConnection(0, iso_sphere.GetOutputPort()) probe_cylinder.SetInputConnection(1, sampled_cylinder.GetOutputPort()) probe_cylinder.Update() # Restore the original normals probe_cylinder.GetOutput().GetPointData().SetNormals( iso_sphere.GetOutput().GetPointData().GetNormals()) print('Scalar range: {:6.3f}, {:6.3f}'.format( probe_cylinder.GetOutput().GetScalarRange()[0], probe_cylinder.GetOutput().GetScalarRange()[1])) # Create a mapper and actor map_sphere = vtk.vtkPolyDataMapper() map_sphere.SetInputConnection(probe_cylinder.GetOutputPort()) map_sphere.SetScalarRange(probe_cylinder.GetOutput().GetScalarRange()) sphere = vtk.vtkActor() sphere.SetMapper(map_sphere) # Visualize renderer = vtk.vtkRenderer() render_window = vtk.vtkRenderWindow() render_window.AddRenderer(renderer) render_window.SetWindowName('IsosurfaceSampling') render_window_interactor = vtk.vtkRenderWindowInteractor() render_window_interactor.SetRenderWindow(render_window) renderer.AddActor(sphere) renderer.SetBackground(colors.GetColor3d('AliceBlue')) render_window.Render() render_window_interactor.Start()
def main(): colors = vtk.vtkNamedColors() # Demonstrate the use of clipping on polygonal data # # create pipeline # plane = vtk.vtkPlaneSource() plane.SetXResolution(25) plane.SetYResolution(25) plane.SetOrigin(-1, -1, 0) plane.SetPoint1(1, -1, 0) plane.SetPoint2(-1, 1, 0) transformSphere = vtk.vtkTransform() transformSphere.Identity() transformSphere.Translate(0.4, -0.4, 0) transformSphere.Inverse() sphere = vtk.vtkSphere() sphere.SetTransform(transformSphere) sphere.SetRadius(.5) transformCylinder = vtk.vtkTransform() transformCylinder.Identity() transformCylinder.Translate(-0.4, 0.4, 0) transformCylinder.RotateZ(30) transformCylinder.RotateY(60) transformCylinder.RotateX(90) transformCylinder.Inverse() cylinder = vtk.vtkCylinder() cylinder.SetTransform(transformCylinder) cylinder.SetRadius(.3) boolean = vtk.vtkImplicitBoolean() boolean.AddFunction(cylinder) boolean.AddFunction(sphere) clipper = vtk.vtkClipPolyData() clipper.SetInputConnection(plane.GetOutputPort()) clipper.SetClipFunction(boolean) clipper.GenerateClippedOutputOn() clipper.GenerateClipScalarsOn() clipper.SetValue(0) clipMapper = vtk.vtkPolyDataMapper() clipMapper.SetInputConnection(clipper.GetOutputPort()) clipMapper.ScalarVisibilityOff() clipActor = vtk.vtkActor() clipActor.SetMapper(clipMapper) clipActor.GetProperty().SetDiffuseColor(colors.GetColor3d("Black")) clipActor.GetProperty().SetRepresentationToWireframe() clipInsideMapper = vtk.vtkPolyDataMapper() clipInsideMapper.SetInputData(clipper.GetClippedOutput()) clipInsideMapper.ScalarVisibilityOff() clipInsideActor = vtk.vtkActor() clipInsideActor.SetMapper(clipInsideMapper) clipInsideActor.GetProperty().SetDiffuseColor( colors.GetColor3d("Dim_Gray")) # Create graphics stuff # ren1 = vtk.vtkRenderer() renWin = vtk.vtkRenderWindow() renWin.AddRenderer(ren1) iren = vtk.vtkRenderWindowInteractor() iren.SetRenderWindow(renWin) # Add the actors to the renderer, set the background and size # ren1.AddActor(clipActor) ren1.AddActor(clipInsideActor) ren1.SetBackground(colors.GetColor3d("Wheat")) ren1.ResetCamera() ren1.GetActiveCamera().Dolly(1.4) ren1.ResetCameraClippingRange() renWin.SetSize(640, 480) # render the image # renWin.Render() iren.Start()
def __init__(self, parent = None): super(VTKFrame, self).__init__(parent) self.vtkWidget = QVTKRenderWindowInteractor(self) vl = QtGui.QVBoxLayout(self) vl.addWidget(self.vtkWidget) vl.setContentsMargins(0, 0, 0, 0) self.ren = vtk.vtkRenderer() self.vtkWidget.GetRenderWindow().AddRenderer(self.ren) self.iren = self.vtkWidget.GetRenderWindow().GetInteractor() # Construct a Cylinder from (x1, y1, z1) to (x2, y2, z2), the inner and outer radius r1, r2 x1, y1, z1 = 10, 2, 3 x2, y2, z2 = 10, 20, 30 r1, r2 = 3, 8 dx, dy, dz = x2-x1, y2-y1, z2-z1 # create axis object axisSource = vtk.vtkLineSource() axisSource = vtk.vtkLineSource() axisSource.SetPoint1(x1, y1, z1) axisSource.SetPoint2(x2, y2, z2) axisMapper = vtk.vtkPolyDataMapper() axisMapper.SetInputConnection(axisSource.GetOutputPort()) axisActor = vtk.vtkActor() axisActor.GetProperty().SetColor(0, 0, 1) axisActor.SetMapper(axisMapper) self.ren.AddActor(axisActor) # Create planes plane1 = vtk.vtkPlane() plane1.SetOrigin(x1, y1, z1) plane1.SetNormal(-dx, -dy, -dz) plane2 = vtk.vtkPlane() plane2.SetOrigin(x2, y2, z2) plane2.SetNormal(dx, dy, dz) # Create cylinders out_cylinder = vtk.vtkCylinder() out_cylinder.SetCenter(0, 0, 0) out_cylinder.SetRadius(r2) in_cylinder = vtk.vtkCylinder() in_cylinder.SetCenter(0, 0, 0) in_cylinder.SetRadius(r1) # The rotation axis of cylinder is along the y-axis # What we need is the axis (x2-x1, y2-y1, z2-z1) angle = math.acos(dy/math.sqrt(dx**2 + dy**2 + dz**2)) * 180.0 / math.pi transform = vtk.vtkTransform() transform.RotateWXYZ(-angle, dz, 1, -dx) transform.Translate(-x1, -y1, -z1) out_cylinder.SetTransform(transform) in_cylinder.SetTransform(transform) # Cutted object cuted = vtk.vtkImplicitBoolean() cuted.SetOperationTypeToIntersection() cuted.AddFunction(out_cylinder) cuted.AddFunction(plane1) cuted.AddFunction(plane2) cuted2 = vtk.vtkImplicitBoolean() cuted2.SetOperationTypeToDifference() cuted2.AddFunction(cuted) cuted2.AddFunction(in_cylinder) # Sample sample = vtk.vtkSampleFunction() sample.SetImplicitFunction(cuted2) sample.SetModelBounds(-100 , 100 , -100 , 100 , -100 , 100) sample.SetSampleDimensions(300, 300, 300) sample.SetComputeNormals(0) # Filter surface = vtk.vtkContourFilter() surface.SetInputConnection(sample.GetOutputPort()) # Create a mapper mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(surface.GetOutputPort()) # Create an actor actor = vtk.vtkActor() actor.SetMapper(mapper) self.ren.AddActor(actor) self.ren.ResetCamera() self._initialized = False
def __init__(self, name, file_path="", density=0, volume=0, mass=0, J_zz=0, u_CAD=np.zeros(3), r_CAD=np.zeros(3), theta=np.zeros(3), dR=np.zeros(3), dtheta=np.zeros(3), color=np.ones(3, dtype="float32"), _dict={}, connected_to_ground=False, parent=None): """ Constructor of body class :param name: body name (string) :param filename: absolute path file of body properties :param density: density of the material of the body :param volume: volume of the body (as float) in m^3 :param mass: mass of the body (as float) in kg :param J_zz: mass moment of inertia of a body against z-axis (as float) in kg*m^2 :param u_CAD: a vector to mass center of a body in body CAD CS (as array) in m :param r_CAD: a vector to body CAD CS in GCS of a system (as array) in m :param theta: orientation angles (numpy array) in degrees :param dR: a vector of velocities (numpy array) in m/s :param dtheta: a vector of angular velocities (numpy array) in deg/s :param color: a color vector (RGB) :param properties_file: a path to mass and geometry properties data in .dat file (todo) :param geometry_data_file: a path to geometry .stl or .obj file (todo) """ super(RigidBody, self).__init__(name=name, file_path=file_path, parent=parent) # type of body self.body_type = "rigid body" # body id self.body_id = self._count() # body coordinates self.q_i_size = 3 # geometry and physical properties self.mass = mass self.J_zz = J_zz # size of mass matrix self.M_size = self.q_i_dim = 3 # material properties self.density = density self.volume = volume # visualization properties # size self.size = 1. # coordinate system properties self.u_CAD = u_CAD self.r_CAD = r_CAD # dynamic properties # transform with respect to selected CS # options: CAD, LCS self.transformCS = "CAD" self.R = self.u_CAD + self.r_CAD # (initial) coordinates and angles (in degrees) self.theta = theta # (initial) translational and rotational velocities self.dR = dR self.dtheta = dtheta # visualization properties self.color = color # connected to ground self._connected_to_ground = connected_to_ground # set directory to read body data from file self.file_path = file_path # os.chdir(MBD_folder_abs_path) # read body properties file if os.path.isfile(self.file_path): self._dict = read_body_data_file.read_body_data_file( self.file_path) self.add_attributes_from_dict(self._dict) # check if both files exist if not os.path.isfile(self.file_path): raise IOError, "Properties file not found!" if self._geometry_type == self.geometry_file_extension and self.geometry_filename is not None: if not os.path.isfile(self.geometry_filename): print "Geometry file %s not found!" % self.geometry_filename # additional translation due to rotation with respect to CAD CS # self.u_CAD[0:2] = Ai_ui_P_vector(self.u_CAD[0:2], 0)#self.theta[2] _R = self.u_CAD - Ai_ui_P_vector(self.u_CAD, self.theta[2]) #np.zeros(3)# # reevaluate R, based on body data from .dat file if all(self.u_CAD == np.zeros(3)) and all(self.r_CAD == np.zeros(3)): pass else: self.R = self.u_CAD + self.r_CAD # create geometry object # read geometry file and save vertices and normals if self._parent is not None: os.chdir(self._parent._parent.MBD_folder_abs_path) if self.geometry_filename is not None: if os.path.isfile(self.geometry_filename): # get extension self._geometry_type = os.path.splitext( self.geometry_filename)[1] if self._geometry_type == ".stl": self.geometry = Geometry(self.geometry_filename, parent=self) elif self._geometry_type == ".txt": self.geometry = Geometry2D(self.geometry_filename, parent=self) else: raise ValueError, "Object attribute _geometry_type not correct!" elif self._geometry_type == "line": self.geometry = Line(parent=self) elif self._geometry_type == "cylinder": self.geometry = vtk.vtkCylinderSource() self.geometry.SetRadius(self.R0) self.geometry.SetHeight(self.L) self.geometry.SetResolution(40) elif self._geometry_type == "box-cylinder": self.geometry_list = [None, None] # create a box box = vtk.vtkBox() box.SetBounds(-self.a, +self.a, -self.b, +self.b, -self.c, +self.c) # create a sphere cylinder = vtk.vtkCylinder() cylinder.SetRadius(self.R0) # cylinder.SetCenter(0,0,0) geometry_list = [box, cylinder] # combine the two implicit functions boolean = vtk.vtkImplicitBoolean() boolean.SetOperationTypeToDifference() # boolean.SetOperationTypeToUnion() # boolean.SetOperationTypeToIntersection() for geometry in geometry_list: boolean.AddFunction(geometry) # The sample function generates a distance function from the implicit # function. This is then contoured to get a polygonal surface. sample = vtk.vtkSampleFunction() sample.SetImplicitFunction(boolean) sample.SetModelBounds(-10E-3, +10E-3, -10E-3, +10E-3, -10E-3, +10E-3) sample.SetSampleDimensions(40, 40, 40) sample.ComputeNormalsOn() # contour self.surface = vtk.vtkContourFilter() self.surface.SetInputConnection(sample.GetOutputPort()) self.surface.SetValue(0, 0.0) else: if self.geometry is None: print "Body geometry file %s not found! Attribute self.geometry for body %s not created." % ( self.geometry_filename, self._name) # add additional attributes to geometry object _dict_geometry = extract_from_dictionary_by_string_in_key( _dict, "geometry.") if self.geometry is not None and _dict_geometry: self.geometry.add_attributes_from_dict(_dict_geometry) if (self.r_CAD == np.zeros(3)).all() and (self.u_CAD == np.zeros(3)).all(): self.r_CAD = self.R
from vtk.util.misc import vtkGetDataRoot VTK_DATA_ROOT = vtkGetDataRoot() # Demonstrate how to extract polygonal cells with an implicit function # get the interactor ui # create a sphere source and actor # sphere = vtk.vtkSphereSource() sphere.SetThetaResolution(8) sphere.SetPhiResolution(16) sphere.SetRadius(1.5) # Extraction stuff t = vtk.vtkTransform() t.RotateX(90) cylfunc = vtk.vtkCylinder() cylfunc.SetRadius(0.5) cylfunc.SetTransform(t) extract = vtk.vtkExtractPolyDataGeometry() extract.SetInputConnection(sphere.GetOutputPort()) extract.SetImplicitFunction(cylfunc) extract.ExtractBoundaryCellsOn() extract.PassPointsOn() sphereMapper = vtk.vtkPolyDataMapper() sphereMapper.SetInputConnection(extract.GetOutputPort()) sphereMapper.GlobalImmediateModeRenderingOn() sphereActor = vtk.vtkActor() sphereActor.SetMapper(sphereMapper) # Extraction stuff - now cull points extract2 = vtk.vtkExtractPolyDataGeometry()
# The orientation of the plane normal = [0.1,1,0.8] # Create a pipeline that cuts a volume to create a plane. This plane will be # cookie cut with a cylinder. # The cylinder is cut to produce a trim loop. This trim loop will cookie cut # the plane mentioned previously. # Along the way, various combinations of the cell data # and point data will be created which are processed by # the cookie cutter. # Create a synthetic source: sample a sphere across a volume cyl = vtk.vtkCylinder() cyl.SetCenter( 0.0,0.0,0.0) cyl.SetRadius(0.25) cyl.SetAxis(0,1,0) sample = vtk.vtkSampleFunction() sample.SetImplicitFunction(cyl) sample.SetModelBounds(-0.75,0.75, -1,1, -0.5,0.5) sample.SetSampleDimensions(res,res,res) sample.ComputeNormalsOff() sample.SetOutputScalarTypeToFloat() sample.Update() # The cut plane plane = vtk.vtkPlane() plane.SetOrigin(0,0,0)
def execute_module(self): if self._giaHumerus and self._giaGlenoid and \ len(self._glenoidEdge) >= 6 and self._inputPolyData: # _glenoidEdgeImplicitFunction # construct eight planes with the insertion axis as mid-line # the planes should go somewhat further proximally than the # proximal insertion axis point # first calculate the distal-proximal glenoid insertion axis gia = tuple(map(operator.sub, self._giaGlenoid, self._giaHumerus)) # and in one swift move, we normalize it and get the magnitude giaN = list(gia) giaM = vtk.vtkMath.Normalize(giaN) # extend gia with a few millimetres giaM += 5 gia = tuple([giaM * i for i in giaN]) stuff = [] yN = [0,0,0] zN = [0,0,0] angleIncr = 2.0 * vtk.vtkMath.Pi() / 8.0 for i in range(4): angle = float(i) * angleIncr vtk.vtkMath.Perpendiculars(gia, yN, zN, angle) # each ridge is 1 cm (10 mm) - we'll change this later y = [10.0 * j for j in yN] origin = map(operator.add, self._giaHumerus, y) point1 = map(operator.add, origin, [-2.0 * k for k in y]) point2 = map(operator.add, origin, gia) # now create the plane source ps = vtk.vtkPlaneSource() ps.SetOrigin(origin) ps.SetPoint1(point1) ps.SetPoint2(point2) ps.Update() plane = vtk.vtkPlane() plane.SetOrigin(ps.GetOrigin()) plane.SetNormal(ps.GetNormal()) pdn = vtk.vtkPolyDataNormals() pdn.SetInput(self._inputPolyData) cut = vtk.vtkCutter() cut.SetInput(pdn.GetOutput()) cut.SetCutFunction(plane) cut.GenerateCutScalarsOn() cut.SetValue(0,0) cut.Update() contour = cut.GetOutput() # now find line segment closest to self._giaGlenoid pl = vtk.vtkPointLocator() pl.SetDataSet(contour) pl.BuildLocator() startPtId = pl.FindClosestPoint(self._giaGlenoid) cellIds = vtk.vtkIdList() contour.GetPointCells(startPtId, cellIds) twoLineIds = cellIds.GetId(0), cellIds.GetId(1) ptIds = vtk.vtkIdList() cellIds = vtk.vtkIdList() # we'll use these to store tuples: # (ptId, (pt0, pt1, pt2), (n0, n1, n2)) lines = [[],[]] lineIdx = 0 for startLineId in twoLineIds: # we have a startLineId, a startPtId and polyData curStartPtId = startPtId curLineId = startLineId onGlenoid = True offCount = 0 while onGlenoid: contour.GetCellPoints(curLineId, ptIds) if ptIds.GetNumberOfIds() != 2: print 'aaaaaaaaaaaaack!' ptId0 = ptIds.GetId(0) ptId1 = ptIds.GetId(1) nextPointId = [ptId0, ptId1]\ [bool(ptId0 == curStartPtId)] contour.GetPointCells(nextPointId, cellIds) if cellIds.GetNumberOfIds() != 2: print 'aaaaaaaaaaaaaaaack2!' cId0 = cellIds.GetId(0) cId1 = cellIds.GetId(1) nextLineId = [cId0, cId1]\ [bool(cId0 == curLineId)] # get the normal for the current point n = contour.GetPointData().GetNormals().GetTuple3( curStartPtId) # get the current point pt0 = contour.GetPoints().GetPoint(curStartPtId) # store the real ptid, point coords and normal lines[lineIdx].append((curStartPtId, tuple(pt0), tuple(n))) if vtk.vtkMath.Dot(giaN, n) > -0.9: # this means that this point could be falling off # the glenoid, let's make a note of the incident offCount += 1 # if the last N points have been "off" the glenoid, # it could mean we've really fallen off! if offCount >= 40: del lines[lineIdx][-40:] onGlenoid = False # get ready for next iteration curStartPtId = nextPointId curLineId = nextLineId # closes: while onGlenoid lineIdx += 1 # closes: for startLineId in twoLineIds # we now have two line lists... we have to combine them and # make sure it still constitutes one long line lines[0].reverse() edgeLine = lines[0] + lines[1] # do line extrusion resulting in a list of 5-element tuples, # each tuple representing the 5 3-d vertices of a "house" houses = self._lineExtrudeHouse(edgeLine, plane) # we will dump ALL the new points in here newPoints = vtk.vtkPoints() newPoints.SetDataType(contour.GetPoints().GetDataType()) # but we're going to create 5 lines idLists = [vtk.vtkIdList() for i in range(5)] for house in houses: for vertexIdx in range(5): ptId = newPoints.InsertNextPoint(house[vertexIdx]) idLists[vertexIdx].InsertNextId(ptId) # create a cell with the 5 lines newCellArray = vtk.vtkCellArray() for idList in idLists: newCellArray.InsertNextCell(idList) newPolyData = vtk.vtkPolyData() newPolyData.SetLines(newCellArray) newPolyData.SetPoints(newPoints) rsf = vtk.vtkRuledSurfaceFilter() rsf.CloseSurfaceOn() #rsf.SetRuledModeToPointWalk() rsf.SetRuledModeToResample() rsf.SetResolution(128, 4) rsf.SetInput(newPolyData) rsf.Update() stuff.append(rsf.GetOutput()) # also add two housies to cap all the ends capHousePoints = vtk.vtkPoints() capHouses = [] if len(houses) > 1: # we only cap if there are at least two houses capHouses.append(houses[0]) capHouses.append(houses[-1]) capHouseIdLists = [vtk.vtkIdList() for dummy in capHouses] for capHouseIdx in range(len(capHouseIdLists)): house = capHouses[capHouseIdx] for vertexIdx in range(5): ptId = capHousePoints.InsertNextPoint(house[vertexIdx]) capHouseIdLists[capHouseIdx].InsertNextId(ptId) if capHouseIdLists: newPolyArray = vtk.vtkCellArray() for capHouseIdList in capHouseIdLists: newPolyArray.InsertNextCell(capHouseIdList) capPolyData = vtk.vtkPolyData() capPolyData.SetPoints(capHousePoints) capPolyData.SetPolys(newPolyArray) # FIXME: put back stuff.append(capPolyData) # closes: for i in range(4) ap = vtk.vtkAppendPolyData() # copy everything to output (for testing) for thing in stuff: ap.AddInput(thing) #ap.AddInput(stuff[0]) # seems to be important for vtkAppendPolyData ap.Update() # now cut it with the FBZ planes fbzSupPlane = self._fbzCutPlane(self._fbzSup, giaN, self._giaGlenoid) fbzSupClip = vtk.vtkClipPolyData() fbzSupClip.SetClipFunction(fbzSupPlane) fbzSupClip.SetValue(0) fbzSupClip.SetInput(ap.GetOutput()) fbzInfPlane = self._fbzCutPlane(self._fbzInf, giaN, self._giaGlenoid) fbzInfClip = vtk.vtkClipPolyData() fbzInfClip.SetClipFunction(fbzInfPlane) fbzInfClip.SetValue(0) fbzInfClip.SetInput(fbzSupClip.GetOutput()) cylinder = vtk.vtkCylinder() cylinder.SetCenter([0,0,0]) # we make the cut-cylinder slightly larger... it's only there # to cut away the surface edges, so precision is not relevant cylinder.SetRadius(self.drillGuideInnerDiameter / 2.0) # cylinder is oriented along y-axis (0,1,0) - # we need to calculate the angle between the y-axis and the gia # 1. calc dot product (|a||b|cos(\phi)) cylDotGia = - giaN[1] # 2. because both factors are normals, angle == acos phiRads = math.acos(cylDotGia) # 3. cp is the vector around which gia can be turned to # coincide with the y-axis cp = [0,0,0] vtk.vtkMath.Cross((-giaN[0], -giaN[1], -giaN[2]), (0.0, 1.0, 0.0), cp) # this transform will be applied to all points BEFORE they are # tested on the cylinder implicit function trfm = vtk.vtkTransform() # it's premultiply by default, so the last operation will get # applied FIRST: # THEN rotate it around the cp axis so it's relative to the # y-axis instead of the gia-axis trfm.RotateWXYZ(phiRads * vtk.vtkMath.RadiansToDegrees(), cp[0], cp[1], cp[2]) # first translate the point back to the origin trfm.Translate(-self._giaGlenoid[0], -self._giaGlenoid[1], -self._giaGlenoid[2]) cylinder.SetTransform(trfm) cylinderClip = vtk.vtkClipPolyData() cylinderClip.SetClipFunction(cylinder) cylinderClip.SetValue(0) cylinderClip.SetInput(fbzInfClip.GetOutput()) cylinderClip.GenerateClipScalarsOn() ap2 = vtk.vtkAppendPolyData() ap2.AddInput(cylinderClip.GetOutput()) # this will cap the just cut polydata ap2.AddInput(self._capCutPolyData(fbzSupClip)) ap2.AddInput(self._capCutPolyData(fbzInfClip)) # thees one she dosint werk so gooood #ap2.AddInput(self._capCutPolyData(cylinderClip)) # now add outer guide cylinder, NOT capped cs1 = vtk.vtkCylinderSource() cs1.SetResolution(32) cs1.SetRadius(self.drillGuideOuterDiameter / 2.0) cs1.CappingOff() cs1.SetHeight(self.drillGuideHeight) # 15 mm height cs1.SetCenter(0,0,0) cs1.Update() # inner cylinder cs2 = vtk.vtkCylinderSource() cs2.SetResolution(32) cs2.SetRadius(self.drillGuideInnerDiameter / 2.0) cs2.CappingOff() cs2.SetHeight(self.drillGuideHeight) # 15 mm height cs2.SetCenter(0,0,0) cs2.Update() # top cap tc = vtk.vtkDiskSource() tc.SetInnerRadius(self.drillGuideInnerDiameter / 2.0) tc.SetOuterRadius(self.drillGuideOuterDiameter / 2.0) tc.SetCircumferentialResolution(64) tcTrfm = vtk.vtkTransform() # THEN flip it so that its centre-line is the y-axis tcTrfm.RotateX(90) # FIRST translate the disc tcTrfm.Translate(0,0,- self.drillGuideHeight / 2.0) tcTPDF = vtk.vtkTransformPolyDataFilter() tcTPDF.SetTransform(tcTrfm) tcTPDF.SetInput(tc.GetOutput()) # bottom cap bc = vtk.vtkDiskSource() bc.SetInnerRadius(self.drillGuideInnerDiameter / 2.0) bc.SetOuterRadius(self.drillGuideOuterDiameter / 2.0) bc.SetCircumferentialResolution(64) bcTrfm = vtk.vtkTransform() # THEN flip it so that its centre-line is the y-axis bcTrfm.RotateX(90) # FIRST translate the disc bcTrfm.Translate(0,0, self.drillGuideHeight / 2.0) bcTPDF = vtk.vtkTransformPolyDataFilter() bcTPDF.SetTransform(bcTrfm) bcTPDF.SetInput(bc.GetOutput()) tubeAP = vtk.vtkAppendPolyData() tubeAP.AddInput(cs1.GetOutput()) tubeAP.AddInput(cs2.GetOutput()) tubeAP.AddInput(tcTPDF.GetOutput()) tubeAP.AddInput(bcTPDF.GetOutput()) # we have to transform this f****r as well csTrfm = vtk.vtkTransform() # go half the height + 2mm upwards from surface drillGuideCentre = - 1.0 * self.drillGuideHeight / 2.0 - 2 cs1Centre = map(operator.add, self._giaGlenoid, [drillGuideCentre * i for i in giaN]) # once again, this is performed LAST csTrfm.Translate(cs1Centre) # and this FIRST (we have to rotate the OTHER way than for # the implicit cylinder cutting, because the cylinder is # transformed from y-axis to gia, not the other way round) csTrfm.RotateWXYZ(-phiRads * vtk.vtkMath.RadiansToDegrees(), cp[0], cp[1], cp[2]) # actually perform the transform csTPDF = vtk.vtkTransformPolyDataFilter() csTPDF.SetTransform(csTrfm) csTPDF.SetInput(tubeAP.GetOutput()) csTPDF.Update() ap2.AddInput(csTPDF.GetOutput()) ap2.Update() self._outputPolyData.DeepCopy(ap2.GetOutput())