def GetDirections(self): """ Return image directions of current view in world coordinates. Changes if image is rotated. """ renderer = self.viewer.GetRenderer() # Get screen frame coordinate = vtk.vtkCoordinate() coordinate.SetCoordinateSystemToNormalizedDisplay() coordinate.SetValue(0.0, 0.0) # Lower left lowerLeft = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(1.0, 0.0) # Lower right lowerRight = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(0.0, 1.0) # Upper left upperLeft = coordinate.GetComputedWorldValue(renderer) first1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(lowerRight, lowerLeft, first1) tmp = vtk.vtkMath.Distance2BetweenPoints(lowerRight, lowerLeft) vtk.vtkMath.MultiplyScalar(first1, 1.0 / math.sqrt(tmp)) second1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(upperLeft, lowerLeft, second1) tmp = vtk.vtkMath.Distance2BetweenPoints(upperLeft, lowerLeft) vtk.vtkMath.MultiplyScalar(second1, 1.0 / math.sqrt(tmp)) normal1 = vtk.vtkVector3d() vtk.vtkMath.Cross(first1, second1, normal1) return first1, second1, normal1
def onLineButton(self): if self.endPoints_positions is None: print("You haven't entered any fiducials yet!") return lineNodes = slicer.mrmlScene.GetNodesByClass("vtkMRMLMarkupsLineNode") if lineNodes is not None: for lineNode in lineNodes: slicer.mrmlScene.RemoveNode(lineNode) endPointsMarkupsNode = self._parameterNode.GetNodeReference( "EndPoints") numNodePoints = endPointsMarkupsNode.GetNumberOfControlPoints() for i in range(0, numNodePoints, 2): fiducialLabel = endPointsMarkupsNode.GetNthFiducialLabel(i) ras1 = vtk.vtkVector3d(0, 0, 0) endPointsMarkupsNode.GetNthControlPointPosition(i, ras1) ras2 = vtk.vtkVector3d(0, 0, 0) endPointsMarkupsNode.GetNthControlPointPosition(i + 1, ras2) pointPositions = np.asarray([ras1, ras2]) lineNode = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsLineNode") slicer.util.updateMarkupsControlPointsFromArray( lineNode, pointPositions) lineDisplayNode = lineNode.GetDisplayNode() lineDisplayNode.SetPropertiesLabelVisibility(False) lineDisplayNode.SetPointSize(0.5) lineDisplayNode.SetSelectable(False) slicer.app.processEvents()
def __init__(self, transform = None): self.planeWidget = vtk.vtkPlaneWidget() self.axes = vtk.vtkAxesActor() pOrigin = vtk.vtkVector3d(np.r_[0, 0, 0]) pPoint1 = vtk.vtkVector3d(np.r_[1, 0, 0]) pPoint2 = vtk.vtkVector3d(np.r_[0, 1, 0]) if transform is not None: self.axes.SetUserTransform(transform) pOrigin = transform.TransformPoint(pOrigin) pPoint1 = transform.TransformPoint(pPoint1) pPoint2 = transform.TransformPoint(pPoint2) self.planeWidget.SetOrigin(pOrigin) self.planeWidget.SetPoint1(pPoint1) self.planeWidget.SetPoint2(pPoint2) self.planeWidget.Modified() self.lastNormal = self.planeWidget.GetNormal() self.lastAxis1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(self.planeWidget.GetPoint1(), self.planeWidget.GetOrigin(), self.lastAxis1) print(self.lastNormal) print(self.lastAxis1) self.axes.SetOrigin(self.planeWidget.GetOrigin()) self.axes.Modified() self.planeWidget.AddObserver(vtk.vtkCommand.EndInteractionEvent, self.SynchronizeAxes, 1.0)
def UpdatePlane(self): origin = vtk.vtkVector3d(np.r_[0, 0, 0]) point1 = vtk.vtkVector3d(np.r_[1, 0, 0]) point2 = vtk.vtkVector3d(np.r_[0, 1, 0]) self.planeWidget.SetOrigin(self.axes.GetUserTransform().TransformPoint(origin)) self.planeWidget.SetPoint1(self.axes.GetUserTransform().TransformPoint(point1)) self.planeWidget.SetPoint2(self.axes.GetUserTransform().TransformPoint(point2)) self.planeWidget.Modified()
def test_arrayFromMarkupsControlPoints(self): # Test if retrieving markups control coordinates as a numpy array works import numpy as np self.delayDisplay('Test arrayFromMarkupsControlPoints') markupsNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLMarkupsFiducialNode') markupsNode.AddControlPoint(vtk.vtkVector3d(10, 20, 30)) markupsNode.AddControlPoint(vtk.vtkVector3d(21, 21, 31)) markupsNode.AddControlPoint(vtk.vtkVector3d(32, 33, 44)) markupsNode.AddControlPoint(vtk.vtkVector3d(45, 45, 55)) markupsNode.AddControlPoint(vtk.vtkVector3d(51, 41, 59)) translation = [10.0, 30.0, 20.0] transformNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLTransformNode') transformMatrix = vtk.vtkMatrix4x4() transformMatrix.SetElement(0, 3, translation[0]) transformMatrix.SetElement(1, 3, translation[1]) transformMatrix.SetElement(2, 3, translation[2]) transformNode.SetMatrixTransformToParent(transformMatrix) markupsNode.SetAndObserveTransformNodeID(transformNode.GetID()) narray = slicer.util.arrayFromMarkupsControlPoints(markupsNode) self.assertEqual(narray.shape, (5, 3)) self.assertEqual(narray[0, 0], 10) self.assertEqual(narray[1, 2], 31) self.assertEqual(narray[4, 2], 59) self.delayDisplay('Test arrayFromMarkupsControlPoints with world=True') narray = slicer.util.arrayFromMarkupsControlPoints(markupsNode, world=True) self.assertEqual(narray.shape, (5, 3)) self.assertEqual(narray[0, 0], 10 + translation[0]) self.assertEqual(narray[1, 2], 31 + translation[2]) self.assertEqual(narray[4, 2], 59 + translation[2]) self.delayDisplay('Test updateMarkupsControlPointsFromArray') narray = np.array([[2, 3, 4], [6, 7, 8]]) slicer.util.updateMarkupsControlPointsFromArray(markupsNode, narray) self.assertEqual(markupsNode.GetNumberOfControlPoints(), 2) position = [0] * 3 markupsNode.GetNthControlPointPosition(1, position) np.testing.assert_array_equal(position, narray[1, :]) self.delayDisplay( 'Test updateMarkupsControlPointsFromArray with world=True') narray = np.array([[2, 3, 4], [6, 7, 8]]) slicer.util.updateMarkupsControlPointsFromArray(markupsNode, narray, world=True) self.assertEqual(markupsNode.GetNumberOfControlPoints(), 2) markupsNode.GetNthControlPointPositionWorld(1, position) np.testing.assert_array_equal(position, narray[1, :])
def CreateArrow(pdLength, startPoint, endPoint): polyData = vtk.vtkPolyData() # Create an arrow. arrowSource = vtk.vtkArrowSource() arrowSource.SetShaftRadius(pdLength * .01) arrowSource.SetShaftResolution(20) arrowSource.SetTipLength(pdLength * .1) arrowSource.SetTipRadius(pdLength * .05) arrowSource.SetTipResolution(20) # Compute a basis normalizedX = vtk.vtkVector3d() normalizedY = vtk.vtkVector3d() normalizedZ = vtk.vtkVector3d() # The X axis is a vector from start to end vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX) length = vtk.vtkMath.Norm(normalizedX) vtk.vtkMath.Normalize(normalizedX) # The Z axis is an arbitrary vector cross X rng = vtk.vtkMinimalStandardRandomSequence() rng.SetSeed(8775070) # For testing. arbitrary = vtk.vtkVector3d() for i in range(3): rng.Next() arbitrary[i] = rng.GetRangeValue(-10, 10) vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ) vtk.vtkMath.Normalize(normalizedZ) # The Y axis is Z cross X vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY) matrix = vtk.vtkMatrix4x4() # Create the direction cosine matrix matrix.Identity() for i in range(3): matrix.SetElement(i, 0, normalizedX[i]) matrix.SetElement(i, 1, normalizedY[i]) matrix.SetElement(i, 2, normalizedZ[i]) # Apply the transforms transform = vtk.vtkTransform() transform.Translate(startPoint) transform.Concatenate(matrix) transform.Scale(length, length, length) # Transform the polydata transformPD = vtk.vtkTransformPolyDataFilter() transformPD.SetTransform(transform) transformPD.SetInputConnection(arrowSource.GetOutputPort()) transformPD.Update() polyData = transformPD.GetOutput() return polyData
def createRationalEllipse(self): import vtk # declare vals erp = vtk.vtkPatchInterpolation() cpt = vtk.vtkDoubleArray() pts = vtk.vtkPoints() pd = vtk.vtkPolyData() ln = vtk.vtkCellArray() pd.SetPoints(pts) pd.SetLines(ln) prange = [0, 1] ns = 21 center = vtk.vtkVector3d() center.SetX(0.0) center.SetY(0.0) center.SetZ(0.0) majorAxis = vtk.vtkVector3d() majorAxis.SetX(1.0) majorAxis.SetY(0.0) majorAxis.SetZ(0.0) minorAxis = vtk.vtkVector3d() minorAxis.SetX(0.0) minorAxis.SetY(1.414) minorAxis.SetZ(1.414) for quadrant in range(1, 5): # generate control points of ellipse for one quadrant erp.GenerateEllipseCtrlPt(cpt, center, majorAxis, minorAxis, quadrant) npts = cpt.GetNumberOfTuples() degree = [npts - 1, 0, 0] self.assertGreater( degree[0], 0, 'Need at least 2 control points, got {n}'.format(n=npts)) # compute points coordinates params = [0., 0., 0.] delta = (prange[1] - prange[0]) / (ns - 1.) for r in [prange[0] + delta * x for x in range(ns)]: params[0] = r erp.InterpolateOnPatch(pts.GetData(), 1, cpt, degree, params) [ ln.InsertNextCell(2, [(quadrant - 1) * ns + i, (quadrant - 1) * ns + i + 1]) for i in range(ns - 1) ] wri = vtk.vtkPolyDataWriter() wri.SetInputDataObject(pd) wri.SetFileName('bezier-{shape}.vtk'.format(shape='ellipse3d')) wri.Write() return pd
def Tick(self, obj, ev): position = vtk.vtkVector3d() if (type(obj) == vtk.vtkAnimationCue): ac = obj t = (ac.GetAnimationTime() - ac.GetStartTime()) / (ac.GetEndTime() - ac.GetStartTime()) delta = vtk.vtkVector3d() vtk.vtkMath.Subtract(self.EndPosition, self.StartPosition, delta) vtk.vtkMath.MultiplyScalar(delta, t) position = vtk.vtkVector3d() vtk.vtkMath.Add(self.StartPosition, delta, position) self.Actor.SetPosition(position)
def test_VolumeRenderingSpecialEffects1(self): """ Ideally you should have several levels of tests. At the lowest level tests should exercise the functionality of the logic with different inputs (both valid and invalid). At higher levels your tests should emulate the way the user would interact with your code and confirm that it still works the way you intended. One of the most important features of the tests is that it should alert other developers when their changes will have an impact on the behavior of your module. For example, if a developer removes a feature that you depend on, your test should break so they know that the feature is needed. """ self.delayDisplay("Starting the test") # Get/create input data import SampleData volumeNode = SampleData.downloadFromURL( nodeNames='MRHead', fileNames='MR-Head.nrrd', uris='https://github.com/Slicer/SlicerTestingData/releases/download/MD5/39b01631b7b38232a220007230624c8e', checksums='MD5:39b01631b7b38232a220007230624c8e')[0] self.delayDisplay('Finished with download and loading') markupsNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode") markupsNode.CreateDefaultDisplayNodes() parameterNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLScriptedModuleNode") parameterNode.SetModuleName("VolumeRenderingSpecialEffects") parameterNode.SetAttribute("ModuleName", "VolumeRenderingSpecialEffects") parameterNode.SetNodeReferenceID("InputVolume", volumeNode.GetID()) parameterNode.SetNodeReferenceID("InputMarkups", markupsNode.GetID()) parameterNode.SetParameter("Radius", "60.0") parameterNode.SetParameter("Mode", "None") # Test the module logic self.delayDisplay('No special effect') logic = VolumeRenderingSpecialEffectsLogic() logic.setParameterNode(parameterNode) self.delayDisplay('Sphere crop') markupsNode.AddControlPointWorld(vtk.vtkVector3d(-3,67,45)) parameterNode.SetParameter("Mode", "SphereCrop") self.delayDisplay('Wedge crop') markupsNode.RemoveAllControlPoints() markupsNode.AddControlPointWorld(vtk.vtkVector3d(1,30,-20)) markupsNode.AddControlPointWorld(vtk.vtkVector3d(30,97,20)) parameterNode.SetParameter("Mode", "WedgeCrop") self.delayDisplay('Test passed')
def test_array(self): # Test if convenience function of getting numpy array from various nodes works self.delayDisplay('Test array with scalar image') import SampleData volumeNode = SampleData.downloadSample("MRHead") voxelPos = [120, 135, 89] voxelValueVtk = volumeNode.GetImageData().GetScalarComponentAsDouble( voxelPos[0], voxelPos[1], voxelPos[2], 0) narray = slicer.util.arrayFromVolume(volumeNode) voxelValueNumpy = narray[voxelPos[2], voxelPos[1], voxelPos[0]] self.assertEqual(voxelValueVtk, voxelValueNumpy) # self.delayDisplay('Test array with tensor image') # tensorVolumeNode = SampleData.downloadSample('DTIBrain') # narray = slicer.util.array(tensorVolumeNode.GetName()) # self.assertEqual(narray.shape, (85, 144, 144, 3, 3)) self.delayDisplay('Test array with model points') sphere = vtk.vtkSphereSource() modelNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLModelNode') modelNode.SetPolyDataConnection(sphere.GetOutputPort()) narray = slicer.util.array(modelNode.GetName()) self.assertEqual(narray.shape, (50, 3)) self.delayDisplay('Test array with markups fiducials') markupsNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLMarkupsFiducialNode') markupsNode.AddControlPoint(vtk.vtkVector3d(10, 20, 30)) markupsNode.AddControlPoint(vtk.vtkVector3d(21, 21, 31)) markupsNode.AddControlPoint(vtk.vtkVector3d(32, 33, 44)) markupsNode.AddControlPoint(vtk.vtkVector3d(45, 45, 55)) markupsNode.AddControlPoint(vtk.vtkVector3d(51, 41, 59)) narray = slicer.util.array(markupsNode.GetName()) self.assertEqual(narray.shape, (5, 3)) self.delayDisplay('Test array with transforms') transformNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLTransformNode') transformMatrix = vtk.vtkMatrix4x4() transformMatrix.SetElement(0, 0, 2.0) transformMatrix.SetElement(0, 3, 11.0) transformMatrix.SetElement(1, 3, 22.0) transformMatrix.SetElement(2, 3, 44.0) transformNode.SetMatrixTransformToParent(transformMatrix) narray = slicer.util.array(transformNode.GetName()) self.assertEqual(narray.shape, (4, 4)) self.delayDisplay('Testing slicer.util.test_array passed')
def createRationalEllipse(self): import vtk # declare vals erp = vtk.vtkPatchInterpolation() cpt = vtk.vtkDoubleArray() pts = vtk.vtkPoints() pd = vtk.vtkPolyData() ln = vtk.vtkCellArray() pd.SetPoints(pts) pd.SetLines(ln) prange = [0, 1] ns = 21 center = vtk.vtkVector3d() center.SetX(0.0) center.SetY(0.0) center.SetZ(0.0) majorAxis = vtk.vtkVector3d() majorAxis.SetX(1.0) majorAxis.SetY(0.0) majorAxis.SetZ(0.0) minorAxis = vtk.vtkVector3d() minorAxis.SetX(0.0) minorAxis.SetY(1.414) minorAxis.SetZ(1.414) for quadrant in range(1, 5): # generate control points of ellipse for one quadrant erp.GenerateEllipseCtrlPt(cpt, center, majorAxis, minorAxis, quadrant) npts = cpt.GetNumberOfTuples() degree = [npts - 1,0,0] self.assertGreater(degree[0], 0, 'Need at least 2 control points, got {n}'.format(n=npts)) # compute points coordinates params = [0., 0., 0.] delta = (prange[1] - prange[0]) / (ns - 1.) for r in [prange[0] + delta * x for x in range(ns)]: params[0] = r erp.InterpolateOnPatch(pts.GetData(), 1, cpt, degree, params) [ln.InsertNextCell(2, [(quadrant-1)*ns + i, (quadrant-1)*ns + i+1]) for i in range(ns - 1)] wri = vtk.vtkPolyDataWriter() wri.SetInputDataObject(pd) wri.SetFileName('bezier-{shape}.vtk'.format(shape='ellipse3d')) wri.Write() return pd
def create_structure(self): import vtk # REQUIRES VTK < 9.0!!! # molecule mol = vtk.vtkMolecule() # hardcoded structure CO2 a1 = mol.AppendAtom(6, 0.0, 0.0, 0.0) a2 = mol.AppendAtom(8, 0.0, 0.0, -1.0) a3 = mol.AppendAtom(8, 0.0, 0.0, 1.0) mol.AppendBond(a2, a1, 1) mol.AppendBond(a3, a1, 1) # hardcoded cell, cubic 10x10x10 vector = vtk.vtkMatrix3x3() vector.DeepCopy([10, 0, 0, 0, 10, 0, 0, 0, 10]) mol.SetLattice(vector) # Change lattice origin so molecule is in the centre mol.SetLatticeOrigin(vtk.vtkVector3d(-5.0, -5.0, -5.0)) # Create a mapper and actor mapper = vtk.vtkMoleculeMapper() mapper.SetInputData(mol) actor = vtk.vtkActor() actor.SetMapper(mapper) self.fbo.addActors([actor]) self.fbo.update()
def addFiducialPoints(title, fiducialPoints): fiducialNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsFiducialNode', title) point = vtk.vtkVector3d() for fiducialPoint in fiducialPoints: point.Set(fiducialPoint[0], fiducialPoint[1], fiducialPoint[2]) fiducialNode.AddControlPointWorld(point) return fiducialNode
def testConstructors(self): """Test overloaded constructors""" # resolve by number of arguments v = vtk.vtkVector3d(3, 4, 5) self.assertEqual((v[0], v[1], v[2]), (3, 4, 5)) v = vtk.vtkVector3d(6) self.assertEqual((v[0], v[1], v[2]), (6, 6, 6)) # resolve by argument type v = vtk.vtkVariant(3.0) self.assertEqual(v.GetType(), vtk.VTK_DOUBLE) v = vtk.vtkVariant(1) self.assertEqual(v.GetType(), vtk.VTK_INT) v = vtk.vtkVariant("hello") self.assertEqual(v.GetType(), vtk.VTK_STRING) v = vtk.vtkVariant(vtk.vtkObject()) self.assertEqual(v.GetType(), vtk.VTK_OBJECT)
def GetScreenTransform(self): """ Get transform from origin to window slice plane """ renderer = self.viewer.GetRenderer() # Get screen frame coordinate = vtk.vtkCoordinate() coordinate.SetCoordinateSystemToNormalizedDisplay() coordinate.SetValue(0.0, 0.0) # Lower left lowerLeft = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(1.0, 0.0) # Lower right lowerRight = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(0.0, 1.0) # Upper left upperLeft = coordinate.GetComputedWorldValue(renderer) first1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(lowerRight, lowerLeft, first1) tmp = vtk.vtkMath.Distance2BetweenPoints(lowerRight, lowerLeft) vtk.vtkMath.MultiplyScalar(first1, 1.0 / math.sqrt(tmp)) second1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(upperLeft, lowerLeft, second1) tmp = vtk.vtkMath.Distance2BetweenPoints(upperLeft, lowerLeft) vtk.vtkMath.MultiplyScalar(second1, 1.0 / math.sqrt(tmp)) normal1 = vtk.vtkVector3d() vtk.vtkMath.Cross(first1, second1, normal1) # Get distance from plane to screen cursor = self.viewer.GetResliceCursorWidget( ).GetResliceCursorRepresentation().GetResliceCursor() normal = cursor.GetPlane(self.iDim).GetNormal() origin = cursor.GetPlane(self.iDim).GetOrigin() PQ = vtk.vtkVector3d() vtk.vtkMath.Subtract(origin, lowerLeft, PQ) dist = vtk.vtkMath.Dot(normal, PQ) trans = vtk.vtkTransform() trans.Translate(dist * normal[0], dist * normal[1], dist * normal[2]) origin1 = trans.TransformPoint(lowerLeft) normal0 = (0.0, 0.0, 1.0) first0 = (1.0, 0.0, 0.0) origin0 = (0.0, 0.0, 0.0) transMat = AxesToTransform(normal0, first0, origin0, normal1, first1, origin1) return transMat
def placeAutoPlane(self): planeNode = slicer.vtkMRMLMarkupsPlaneNode() slicer.mrmlScene.AddNode(planeNode) planeNode.CreateDefaultDisplayNodes() self.splitPlanes.append(planeNode) bounds = [0,0,0,0,0,0] self.activeNode.GetRASBounds(bounds) # TODO: Clean this up to be clearer about what is being calculated, maybe add a function center = [((bounds[1] - bounds[0]) / 2) + bounds[0], ((bounds[3] - bounds[2]) / 2) + bounds[2], ((bounds[5] - bounds[4]) / 2) + bounds[4]] p2 = [((bounds[1] - bounds[0]) / 2) + bounds[0]+(bounds[1] - bounds[0])*1.5/2, ((bounds[3] - bounds[2]) / 2) + bounds[2], ((bounds[5] - bounds[4]) / 2) + bounds[4]] p3 = [((bounds[1] - bounds[0]) / 2) + bounds[0], ((bounds[3] - bounds[2]) / 2) + bounds[2]+(bounds[3] - bounds[2])*1.5/2, ((bounds[5] - bounds[4]) / 2) + bounds[4]] planeNode.AddControlPoint(vtk.vtkVector3d(center)) planeNode.AddControlPoint(vtk.vtkVector3d(p2)) planeNode.AddControlPoint(vtk.vtkVector3d(p3)) self.ui.PreviewSplitButton.enabled = True
def setFiducialNodeAs(self, type, fromNode, name, radius): toNode = self.parameterNode.GetNodeReference(type + "Fiducial") for i in range(fromNode.GetNumberOfControlPoints()): toNode.AddControlPoint( vtk.vtkVector3d(fromNode.GetNthControlPointPosition(i)), name) toNode.SetNthControlPointDescription( toNode.GetNumberOfControlPoints() - 1, radius) slicer.mrmlScene.RemoveNode(fromNode)
def createTipFiducial(self): fiducialNode = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLMarkupsFiducialNode') fiducialNode.GetDisplayNode().SetTextScale(0) fiducialNode.GetDisplayNode().SetVisibility3D(1) fiducialNode.AddControlPointWorld(vtk.vtkVector3d([0, 0, 0])) fiducialNode.SetLocked(True) return fiducialNode
def createPerpendicular(vector3d): """ Create vector in 3D that is perpendicular to input """ values = np.fabs(np.r_[vector3d[0],vector3d[1],vector3d[2]]) inx = values.argsort() tmp = vtk.vtkVector3d() # Swap the two largest component and add a sign tmp[inx[-1]] = -vector3d[inx[-2]] tmp[inx[-2]] = vector3d[inx[-1]] tmp[inx[-3]] = vector3d[inx[-3]] # Cross-product with the input result = vtk.vtkVector3d() vtk.vtkMath.Cross(vector3d, tmp, result) # Return unit vector norm = result.Normalize() return result
def UpdatePlane(self): """ Update last position/orientation of plane widget to match axes """ origin = vtk.vtkVector3d(np.r_[-0.5, -0.5, 0]) point1 = vtk.vtkVector3d(np.r_[0.5, -0.5, 0]) point2 = vtk.vtkVector3d(np.r_[-0.5, 0.5, 0]) self.planeWidget.SetOrigin( self.axes.GetUserTransform().TransformPoint(origin)) self.planeWidget.SetPoint1( self.axes.GetUserTransform().TransformPoint(point1)) self.planeWidget.SetPoint2( self.axes.GetUserTransform().TransformPoint(point2)) self.planeWidget.Modified() # We have used the last position of the plane widget to store last point. # This must be updated when updated indrectly (chain of transforms) self.lastNormal = self.planeWidget.GetNormal() vtk.vtkMath.Subtract(self.planeWidget.GetPoint1(), self.planeWidget.GetOrigin(), self.lastAxis1) self.axes.SetOrigin(self.planeWidget.GetCenter())
def GetOrientation(self): # Normal can be obtained using self.GetResliceCursor().GetPlane(iDim).GetNormal() renderer = self.viewer.GetRenderer() # Get screen frame coordinate = vtk.vtkCoordinate() coordinate.SetCoordinateSystemToNormalizedDisplay() coordinate.SetValue(0.0, 0.0) # Lower left lowerLeft = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(1.0, 0.0) # Lower right lowerRight = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(0.0, 1.0) # Upper left upperLeft = coordinate.GetComputedWorldValue(renderer) first1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(lowerRight, lowerLeft, first1) tmp = vtk.vtkMath.Distance2BetweenPoints(lowerRight, lowerLeft) vtk.vtkMath.MultiplyScalar(first1, 1.0 / math.sqrt(tmp)) second1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(upperLeft, lowerLeft, second1) tmp = vtk.vtkMath.Distance2BetweenPoints(upperLeft, lowerLeft) vtk.vtkMath.MultiplyScalar(second1, 1.0 / math.sqrt(tmp)) normal1 = vtk.vtkVector3d() vtk.vtkMath.Cross(first1, second1, normal1) return first1, second1, normal1
def __init__(self, transform=None): self.planeWidget = createPlaneWidget(native=False) self.axes = createAxesActor(native=False, length=0.5) pOrigin = vtk.vtkVector3d(np.r_[-0.5, -0.5, 0]) pPoint1 = vtk.vtkVector3d(np.r_[0.5, -0.5, 0]) pPoint2 = vtk.vtkVector3d(np.r_[-0.5, 0.5, 0]) if transform is not None: self.axes.SetUserTransform(transform) pOrigin = transform.TransformPoint(pOrigin) pPoint1 = transform.TransformPoint(pPoint1) pPoint2 = transform.TransformPoint(pPoint2) self.planeWidget.SetOrigin(pOrigin) self.planeWidget.SetPoint1(pPoint1) self.planeWidget.SetPoint2(pPoint2) self.planeWidget.Modified() self.lastNormal = self.planeWidget.GetNormal() self.lastAxis1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(self.planeWidget.GetPoint1(), self.planeWidget.GetOrigin(), self.lastAxis1) self.axes.SetOrigin(self.planeWidget.GetCenter()) self.axes.Modified() self.planeWidget.AddObserver(vtk.vtkCommand.EndInteractionEvent, self.SynchronizePlaneCallback, 1.0) self.extrinsicHandle = 0 self.updateHandle = 0 self.extrinsic = False
def setAorticAnnulusFiducialNode(self, aorticAnnulusNode): self.aorticAnnulusFiducialNode = aorticAnnulusNode centerLineNode = self.getCenterlineNode() if self.aorticAnnulusFiducialNode and self.aorticAnnulusFiducialNode.GetNumberOfFiducials() and \ centerLineNode.GetNumberOfMarkups() == 0: probeToRasTransformNode = self.getProbeToRasTransform() if probeToRasTransformNode: centerLineNode.SetAndObserveTransformNodeID(probeToRasTransformNode.GetID() if probeToRasTransformNode else None) aorticAnnulusCentroid = self.getAnnulusCentroidPosition(self.aorticAnnulusFiducialNode) centerLineNode.AddControlPoint(vtk.vtkVector3d(aorticAnnulusCentroid)) else: logging.info("Aortic annulus has no points or center line already has more than 0 markups.")
def GetScreenImage(self, useOffScreenBuffer=False, showContours=False): image = None if useOffScreenBuffer: image = self.readOffScrenBuffer(showContours=showContours) image.SetOrigin(0, 0, 0) else: image = self.readOnScreenBuffer(showContours=showContours) renderer = self.viewer.GetRenderer() coordinate = vtk.vtkCoordinate() coordinate.SetCoordinateSystemToNormalizedDisplay() dims = image.GetDimensions() coordinate.SetValue(1.0, 0.0) # Lower right lowerRight = coordinate.GetComputedWorldValue(renderer) coordinate.SetValue(0.0, 0.0) # Lower left lowerLeft = coordinate.GetComputedWorldValue(renderer) dx = vtk.vtkMath.Distance2BetweenPoints(lowerRight, lowerLeft) dx = math.sqrt(dx) / dims[0] coordinate.SetValue(0.0, 1.0) # Upper left dy = vtk.vtkMath.Distance2BetweenPoints( coordinate.GetComputedWorldValue(renderer), lowerLeft) dy = math.sqrt(dy) / dims[1] image.SetSpacing(dx, dy, 0.0) image.Modified() # Adjust origin cursor = self.viewer.GetResliceCursor() normal = cursor.GetPlane(self.iDim).GetNormal() origin = cursor.GetPlane(self.iDim).GetOrigin() PQ = vtk.vtkVector3d() vtk.vtkMath.Subtract(origin, lowerLeft, PQ) # Signed distance to plane dist = vtk.vtkMath.Dot(normal, PQ) # If VTK 9.0 add origin and orientation trans = vtk.vtkTransform() trans.Translate(dist * normal[0], dist * normal[1], dist * normal[2]) image.SetOrigin(trans.TransformPoint(lowerLeft)) image.Modified() # TODO: Compute orientation for VTK 9.0 # image.SetOrientation(mat) self.viewer.Render() return image
def SynchronizeAxes(self, obj, ev): # Old coordinate system normal0 = self.lastNormal first0 = self.lastAxis1 origin0 = self.axes.GetOrigin() # Way to store origin # New coordinate system normal1 = obj.GetNormal() first1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(obj.GetPoint1(), obj.GetOrigin(), first1) # Normalize (not needed - but we do this anyway) #first1.Normalize() #origin1 = obj.GetCenter() # Original origin1 = obj.GetOrigin() # Transform trans = AxesToTransform(normal0, first0, origin0, normal1, first1, origin1) if self.axes.GetUserTransform() is not None: self.axes.GetUserTransform().Concatenate(trans) else: transform = vtk.vtkTransform() transform.PostMultiply() transform.SetMatrix(trans) self.axes.SetUserTransform(transform) self.axes.GetUserTransform().Update() # Center moved to origin of axes self.axes.SetOrigin(obj.GetOrigin()) self.axes.Modified() # Update last axes self.lastAxis1 = first1 self.lastNormal = normal1 print(self.__repr__) print('done sync')
def onPointPositionDefined(self, caller, event): targetFiducialNode = slicer.mrmlScene.GetNodeByID( self.targetFiducialNodeID) lastControlPoint = targetFiducialNode.GetNumberOfControlPoints() - 1 name = targetFiducialNode.GetNthControlPointLabel(lastControlPoint) if name.startswith(targetFiducialNode.GetName()): sourceFiducialNode = slicer.mrmlScene.GetNodeByID( self.sourceFiducialNodeID) sourceFiducialNode.AddControlPoint( vtk.vtkVector3d( targetFiducialNode.GetNthControlPointPosition( lastControlPoint))) targetFiducialNode.SetNthControlPointLabel( lastControlPoint, slicer.mrmlScene.GenerateUniqueName('fixed point')) targetFiducialNode.SetNthControlPointDescription( lastControlPoint, self.parameterNode.GetParameter("Radius")) sourceFiducialNode.SetNthControlPointLabel( lastControlPoint, targetFiducialNode.GetNthControlPointLabel(lastControlPoint)) sourceFiducialNode.SetNthControlPointDescription( lastControlPoint, self.parameterNode.GetParameter("Radius")) self.parameterNode.SetParameter("Update", "true")
def SynchronizePlaneCallback(self, obj, ev): # If not updated using 'b', things get out of order # Consider update these parameters when the axes actor has been updated normal0 = self.lastNormal first0 = self.lastAxis1 origin0 = self.axes.GetOrigin() # Way to store origin # New coordinate system normal1 = obj.GetNormal() first1 = vtk.vtkVector3d() vtk.vtkMath.Subtract(obj.GetPoint1(), obj.GetOrigin(), first1) first1.Normalize() origin1 = obj.GetCenter() # Transform trans = AxesToTransform(normal0, first0, origin0, normal1, first1, origin1) if self.axes.GetUserTransform() is not None: self.axes.GetUserTransform().Concatenate(trans) else: transform = vtk.vtkTransform() transform.PostMultiply() transform.SetMatrix(trans) self.axes.SetUserTransform(transform) self.axes.GetUserTransform().Update() # Center moved to origin of axes self.axes.SetOrigin(obj.GetCenter()) self.axes.Modified() # Update last axes self.lastAxis1 = first1 self.lastNormal = normal1
def run(self, inputDirectory, outputDirectory, resampleNumber, closedCurveOption): extension = ".fcsv" for file in os.listdir(inputDirectory): if file.endswith(extension): # read landmark file inputFilePath = os.path.join(inputDirectory, file) markupsNode = slicer.util.loadMarkupsFiducialList( inputFilePath) #resample if closedCurveOption: curve = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsClosedCurveNode", "resampled_temp") resampledCurve = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsClosedCurveNode", "resampledClosedCurve") else: curve = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsCurveNode", "resampled_temp") resampledCurve = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsCurveNode", "resampledCurve") vector = vtk.vtkVector3d() pt = [0, 0, 0] landmarkNumber = markupsNode.GetNumberOfFiducials() for landmark in range(0, landmarkNumber): markupsNode.GetMarkupPoint(landmark, 0, pt) vector[0] = pt[0] vector[1] = pt[1] vector[2] = pt[2] curve.AddControlPoint(vector) currentPoints = curve.GetCurvePointsWorld() newPoints = vtk.vtkPoints() if closedCurveOption: sampleDist = curve.GetCurveLengthWorld() / (resampleNumber) else: sampleDist = curve.GetCurveLengthWorld() / ( resampleNumber - 1) curve.ResamplePoints(currentPoints, newPoints, sampleDist, closedCurveOption) #set resampleNumber control points if (newPoints.GetNumberOfPoints() == resampleNumber) or ( closedCurveOption and (newPoints.GetNumberOfPoints() == resampleNumber + 1)): for controlPoint in range(0, resampleNumber): newPoints.GetPoint(controlPoint, pt) vector[0] = pt[0] vector[1] = pt[1] vector[2] = pt[2] resampledCurve.AddControlPoint(vector) newPointNumber = resampledCurve.GetNumberOfControlPoints() # save newFileName = os.path.splitext(file)[ 0] + "_resample_" + str(newPointNumber) + extension outputFilePath = os.path.join(outputDirectory, newFileName) slicer.util.saveNode(resampledCurve, outputFilePath) slicer.mrmlScene.RemoveNode( markupsNode) #remove node from scene slicer.mrmlScene.RemoveNode(curve) slicer.mrmlScene.RemoveNode(resampledCurve) else: print( "Error: resampling did not return expected number of points" ) print("Resampled Points: ", newPoints.GetNumberOfPoints()) logging.info('Processing completed') return True
def testWedgeCut(self): self.delayDisplay("Starting...") self.setUp() fileURL = 'http://slicer.kitware.com/midas3/download/item/426450/MRRobot-Shoulder-MR.nrrd' filePath = os.path.join(slicer.util.tempDirectory(), 'MRRobot-Shoulder-MR.nrrd') slicer.util.downloadFile(fileURL, filePath) success, shoulder = slicer.util.loadVolume(filePath, returnNode=True) self.delayDisplay("Shoulder downloaded...") slicer.util.mainWindow().moduleSelector().selectModule('VolumeRendering') volumeRenderingWidgetRep = slicer.modules.volumerendering.widgetRepresentation() volumeRenderingWidgetRep.setMRMLVolumeNode(shoulder) volumeRenderingNode = slicer.mrmlScene.GetFirstNodeByName('VolumeRendering') volumeRenderingNode.SetVisibility(1) self.delayDisplay('Volume rendering on') methodComboBox = slicer.util.findChildren(name='RenderingMethodComboBox')[0] methodComboBox.currentIndex = methodComboBox.findText('VTK GPU Ray Casting') self.delayDisplay('GPU Ray Casting on') endpoints = [ [-162.94, 2.32192, -30.1792], [-144.842, 96.867, -36.8726] ] markupNode = slicer.mrmlScene.AddNode(slicer.vtkMRMLMarkupsLineNode()) for endpoint in endpoints: markupNode.AddControlPoint(vtk.vtkVector3d(endpoint)) self.delayDisplay('Line added') #------------------------------------------------------ # Utility functions to get the position of the first # fiducial point in the scene and the shader property # node #------------------------------------------------------ def GetLineEndpoints(): fn = slicer.util.getNode('vtkMRMLMarkupsLineNode1') endpoints = [] for n in range(2): endpoints.append([0,]*3) fn.GetNthControlPointPosition(n,endpoints[n]) return endpoints def GetShaderPropertyNode(): return slicer.util.getNode('vtkMRMLShaderPropertyNode1') #------------------------------------------------------ # Get the shader property node which contains every custom # shader modifications for every mapper associated with # the first volume rendering display node #------------------------------------------------------ displayNode = slicer.util.getNodesByClass('vtkMRMLGPURayCastVolumeRenderingDisplayNode')[0] shaderPropNode = displayNode.GetOrCreateShaderPropertyNode(slicer.mrmlScene) shaderProp = shaderPropNode.GetShaderProperty() # turn off shading so carved region looks reasonable volumePropertyNode = displayNode.GetVolumePropertyNode() volumeProperty = volumePropertyNode.GetVolumeProperty() volumeProperty.ShadeOff() #------------------------------------------------------ # Declare and initialize custom uniform variables # used in our shader replacement #------------------------------------------------------ shaderUniforms = shaderPropNode.GetFragmentUniforms() shaderUniforms.RemoveAllUniforms() endpoints = GetLineEndpoints() shaderUniforms.SetUniform3f("endpoint0",endpoints[0]) shaderUniforms.SetUniform3f("endpoint1",endpoints[1]) shaderUniforms.SetUniformf("coneCutoff",0.8) #------------------------------------------------------ # Replace the cropping implementation part of the # raycasting shader to skip everything in the sphere # defined by endpoints and radius #------------------------------------------------------ croppingImplShaderCode = """ vec4 texCoordRAS = in_volumeMatrix[0] * in_textureDatasetMatrix[0] * vec4(g_dataPos, 1.); vec3 samplePoint = texCoordRAS.xyz; vec3 toSample = normalize(samplePoint - endpoint0); vec3 toEnd = normalize(endpoint1 - endpoint0); float onLine = dot(toEnd, toSample); g_skip = (onLine > coneCutoff); """ shaderProp.ClearAllFragmentShaderReplacements() shaderProp.AddFragmentShaderReplacement("//VTK::Cropping::Impl", True, croppingImplShaderCode, False) #------------------------------------------------------ # Add a callback when the fiducial moves to adjust # the endpoints of the carving sphere accordingly #------------------------------------------------------ def onControlPointMoved(): endpoints = GetLineEndpoints() propNode = GetShaderPropertyNode() propNode.GetFragmentUniforms().SetUniform3f("endpoint0",endpoints[0]) propNode.GetFragmentUniforms().SetUniform3f("endpoint1",endpoints[1]) fn = slicer.util.getNode('vtkMRMLMarkupsLineNode1') fn.AddObserver(fn.PointModifiedEvent, lambda caller,event: onControlPointMoved()) self.delayDisplay("Should be a carved out shoulder now")
def run(self, nodeType, numberOfNodes=10, numberOfControlPoints=10, rOffset=0, usefewerModifyCalls=False, locked=False, labelsHidden=False): """ Run the actual algorithm """ print( f'Running test to add {numberOfNodes} nodes markups with {numberOfControlPoints} control points' ) print('Index\tTime to add fid\tDelta between adds') print("%(index)04s\t" % {'index': "i"}, "t\tdt'") r = rOffset a = 0 s = 0 t1 = 0 t2 = 0 t3 = 0 t4 = 0 timeToAddThisFid = 0 timeToAddLastFid = 0 testStartTime = time.process_time() import random if usefewerModifyCalls: print("Pause render") slicer.app.pauseRender() for nodeIndex in range(numberOfNodes): markupsNode = slicer.mrmlScene.AddNewNodeByClass(nodeType) markupsNode.CreateDefaultDisplayNodes() if locked: markupsNode.SetLocked(True) if labelsHidden: markupsNode.GetDisplayNode().SetPropertiesLabelVisibility( False) markupsNode.GetDisplayNode().SetPointLabelsVisibility(False) if usefewerModifyCalls: print("Start modify") mod = markupsNode.StartModify() for controlPointIndex in range(numberOfControlPoints): # print "controlPointIndex = ", controlPointIndex, "/", numberOfControlPoints, ", r = ", r, ", a = ", a, ", s = ", s t1 = time.process_time() markupsNode.AddControlPoint(vtk.vtkVector3d(r, a, s)) t2 = time.process_time() timeToAddThisFid = t2 - t1 dt = timeToAddThisFid - timeToAddLastFid # print '%(index)04d\t' % {'index': controlPointIndex}, timeToAddThisFid, "\t", dt r = float( controlPointIndex ) / numberOfControlPoints * 100.0 - 50.0 + random.uniform( -20.0, 20.0) a = float( controlPointIndex ) / numberOfControlPoints * 100.0 - 50.0 + random.uniform( -20.0, 20.0) s = random.uniform(-20.0, 20.0) timeToAddLastFid = timeToAddThisFid if usefewerModifyCalls: markupsNode.EndModify(mod) if usefewerModifyCalls: print("Resume render") slicer.app.resumeRender() testEndTime = time.process_time() testTime = testEndTime - testStartTime print("Total time to add ", numberOfControlPoints, " = ", testTime) return True
def main(argv): colors = vtk.vtkNamedColors() backgroundColor = colors.GetColor3d("DarkSlateGray") legendBackgroundColor = colors.GetColor3d("SlateGray") originColor = colors.GetColor3d("OrangeRed") centerColor = colors.GetColor3d("Gold") point1Color = colors.GetColor3d("MediumSpringGreen") point2Color = colors.GetColor3d("Brown") xAxisColor = colors.GetColor3d("lime") yAxisColor = colors.GetColor3d("orange") normalColor = colors.GetColor3d("Raspberry") # Create actors planeSource = vtk.vtkPlaneSource() planeSource.SetOrigin(0.0, 0.0, 0.0) planeSource.SetPoint1(1, 0, 0) planeSource.SetPoint2(0, 1.0, 0) planeSource.Update() bounds = planeSource.GetOutput().GetBounds() length = max(bounds[1] - bounds[0], bounds[3] - bounds[2]) planeMapper = vtk.vtkPolyDataMapper() planeMapper.SetInputConnection(planeSource.GetOutputPort()) planeActor = vtk.vtkActor() planeActor.SetMapper(planeMapper) sphereSource = vtk.vtkSphereSource() sphereSource.SetRadius(length * .04) originMapper = vtk.vtkPolyDataMapper() originMapper.SetInputConnection(sphereSource.GetOutputPort()) originActor = vtk.vtkActor() originActor.SetPosition(planeSource.GetOrigin()) originActor.SetMapper(originMapper) originActor.GetProperty().SetDiffuseColor(originColor) centerMapper = vtk.vtkPolyDataMapper() centerMapper.SetInputConnection(sphereSource.GetOutputPort()) centerActor = vtk.vtkActor() centerActor.SetPosition(planeSource.GetCenter()) centerActor.SetMapper(centerMapper) centerActor.GetProperty().SetDiffuseColor(centerColor) point1Mapper = vtk.vtkPolyDataMapper() point1Mapper.SetInputConnection(sphereSource.GetOutputPort()) point1Actor = vtk.vtkActor() point1Actor.SetPosition(planeSource.GetPoint1()) point1Actor.SetMapper(point1Mapper) point1Actor.GetProperty().SetDiffuseColor(point1Color) point2Mapper = vtk.vtkPolyDataMapper() point2Mapper.SetInputConnection(sphereSource.GetOutputPort()) point2Actor = vtk.vtkActor() point2Actor.SetPosition(planeSource.GetPoint2()) point2Actor.SetMapper(point2Mapper) point2Actor.GetProperty().SetDiffuseColor(point2Color) center = vtk.vtkVector3d() origin = vtk.vtkVector3d() normal = vtk.vtkVector3d() point1 = vtk.vtkVector3d() point2 = vtk.vtkVector3d() for i in range(3): point1[i] = planeSource.GetPoint1()[i] point2[i] = planeSource.GetPoint2()[i] origin[i] = planeSource.GetOrigin()[i] center[i] = planeSource.GetCenter()[i] normal[i] = planeSource.GetNormal()[i] * length xAxisPolyData = CreateArrow(length, origin, point1) xAxisMapper = vtk.vtkPolyDataMapper() xAxisMapper.SetInputData(xAxisPolyData) xAxisActor = vtk.vtkActor() xAxisActor.SetMapper(xAxisMapper) xAxisActor.GetProperty().SetDiffuseColor(xAxisColor) yAxisPolyData = CreateArrow(length, origin, point2) yAxisMapper = vtk.vtkPolyDataMapper() yAxisMapper.SetInputData(yAxisPolyData) yAxisActor = vtk.vtkActor() yAxisActor.SetMapper(yAxisMapper) yAxisActor.GetProperty().SetDiffuseColor(yAxisColor) normalPolyData = CreateArrow(length, origin, normal) normalMapper = vtk.vtkPolyDataMapper() normalMapper.SetInputData(normalPolyData) normalActor = vtk.vtkActor() normalActor.SetMapper(normalMapper) normalActor.GetProperty().SetDiffuseColor(normalColor) # Create the RenderWindow, Renderer renderer = vtk.vtkRenderer() legend = vtk.vtkLegendBoxActor() legend.SetNumberOfEntries(7) legend.UseBackgroundOn() legend.SetBackgroundColor(legendBackgroundColor) legend.GetPositionCoordinate().SetValue(.7, .7) legend.GetPosition2Coordinate().SetValue(.3, .3) entry = 0 legend.SetEntry(entry, sphereSource.GetOutput(), "center", centerColor) entry = entry + 1 legend.SetEntry(entry, sphereSource.GetOutput(), "origin", originColor) entry = entry + 1 legend.SetEntry(entry, sphereSource.GetOutput(), "point1", point1Color) entry = entry + 1 legend.SetEntry(entry, sphereSource.GetOutput(), "point2", point2Color) entry = entry + 1 legend.SetEntry(entry, xAxisPolyData, "xAxis", xAxisColor) entry = entry + 1 legend.SetEntry(entry, xAxisPolyData, "yAxis", yAxisColor) entry = entry + 1 legend.SetEntry(entry, xAxisPolyData, "normal", normalColor) renderWindow = vtk.vtkRenderWindow() renderWindow.AddRenderer(renderer) renderWindow.SetWindowName("PlaneSourceDemo") renderWindow.SetSize(640, 480) interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(renderWindow) renderer.SetBackground(backgroundColor) renderer.AddActor(planeActor) renderer.AddActor(originActor) renderer.AddActor(centerActor) renderer.AddActor(point1Actor) renderer.AddActor(point2Actor) renderer.AddActor(xAxisActor) renderer.AddActor(yAxisActor) renderer.AddActor(normalActor) renderer.AddActor(legend) renderWindow.Render() renderer.GetActiveCamera().SetPosition(1, 0, 0) renderer.GetActiveCamera().SetFocalPoint(0, 1, 0) renderer.GetActiveCamera().SetViewUp(0, 0, 1) renderer.GetActiveCamera().Azimuth(30) renderer.GetActiveCamera().Elevation(30) renderer.ResetCamera() renderWindow.Render() interactor.Start() return 0