Previous

Section

<<<

Isosurface Generation Using VTK

Next

Section

>>>

Creating the Application

 

 

4.2. VTKRender

 

This class is divided into a number of different functions.  Below is the code for the classes in addition to commentary on the code.

 

__init__: This function initializes the class, sets up the visualization pipeline (actually two since there are two actors at the end— one for the skin isosurface and one for the bone isosurface).  Other comments listed near to their appropriate areas:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

class VTKRender:

    def __init__(self, frame):

 

        self.__frame = frame       

        self.NONE = 0

        self.ISO = 10

        self.COMP = 20

        self.MIP = 30

 

        # ID numbers, not isovalue

        self.SKIN = 100

        self.BONE = 200

        self.OTHER = 300

 

        self.HEAD = 1000

        self.FEET = 2000

 

 

        self.SKIN_ISOSURFACE = 860

        self.BONE_ISOSURFACE = 1250

        self.__otherIso = 1100

 

        self.__lastActorID = self.NONE

       

  • Key parts of the pipeline are highlighted.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

        self.readerVolume = vtk.vtkImageReader()

        self.readerVolume.SetDataScalarType( vtk.VTK_UNSIGNED_SHORT )

        self.readerVolume.SetDataScalarType( 5 )

        self.readerVolume.SetDataByteOrder( 0 )

        self.readerVolume.SetFileDimensionality( 3 )

        self.readerVolume.SetDataExtent ( 0,255, 0,255, 0,576)

        self.readerVolume.SetDataSpacing( 1,1,1 )

        self.readerVolume.SetNumberOfScalarComponents( 1 )

        self.readerVolume.SetFileName( "./Female.raw" )

 

        self.voiFeet = vtk.vtkExtractVOI()

        self.voiFeet.SetInput( self.readerVolume.GetOutput() )

        self.voiFeet.SetVOI( 0,255, 60,255, 500,576 )

        self.voiFeet.SetSampleRate( 1,1,1 )               

 

        self.voiHead = vtk.vtkExtractVOI()

        self.voiHead.SetInput( self.readerVolume.GetOutput() )

        self.voiHead.SetVOI( 0,255, 60,255, 0,100 )

        self.voiHead.SetSampleRate( 1,1,1 )

 

 

        #### BONE

        self.contourBoneHead = vtk.vtkMarchingCubes()

  • Also note that besides having a skin actor and bone actor, there are actually four different vtkMarchingCubes classes.  This represents the total number of combinations of isovalues and volumes of interest (head and feet).

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

        self.contourBoneHead.SetInput( self.voiHead.GetOutput() )

        self.contourBoneHead.ComputeNormalsOn()

        self.contourBoneHead.SetValue( 0, self.BONE_ISOSURFACE )

 

        self.contourBoneFeet = vtk.vtkMarchingCubes()

        self.contourBoneFeet.SetInput( self.voiFeet.GetOutput() )

        self.contourBoneFeet.ComputeNormalsOn()

        self.contourBoneFeet.SetValue( 0, self.BONE_ISOSURFACE )

 

        self.geoBoneMapper = vtk.vtkPolyDataMapper()

        self.geoBoneMapper.SetInput( self.contourBoneFeet.GetOutput() )

        self.geoBoneMapper.ScalarVisibilityOff()

 

        self.actorBone = vtk.vtkLODActor()

        self.actorBone.SetNumberOfCloudPoints( 1000000 )

        self.actorBone.SetMapper( self.geoBoneMapper )

        self.actorBone.GetProperty().SetColor( 1, 1, 1 )

 

        ### SKIN

        self.contourSkinTop = vtk.vtkMarchingCubes()

        self.contourSkinTop.SetInput( self.voiHead.GetOutput() )

        self.contourSkinTop.SetValue( 0, self.SKIN_ISOSURFACE ) #860

        self.contourSkinTop.ComputeNormalsOn()

 

        self.contourSkinFeet = vtk.vtkMarchingCubes()

        self.contourSkinFeet.SetInput( self.voiFeet.GetOutput() )

        self.contourSkinFeet.ComputeNormalsOn()

        self.contourSkinFeet.SetValue( 0, self.SKIN_ISOSURFACE )

 

        self.geoSkinMapper = vtk.vtkPolyDataMapper()

        self.geoSkinMapper.SetInput( self.contourSkinFeet.GetOutput() )

        self.geoSkinMapper.ScalarVisibilityOff()

 

        self.actorSkin = vtk.vtkLODActor()

        self.actorSkin.SetNumberOfCloudPoints( 1000000 )

        self.actorSkin.SetMapper( self.geoSkinMapper )

        self.actorSkin.GetProperty().SetColor( 1, 0.547237, 0.319073 )

        self.actorSkin.GetProperty().SetOpacity( 0.3 )

 

 

        # Rendering structure taken from VTK Python example given by VTK

        self.renWin = vtk.vtkRenderWindow()

        self.ren = vtk.vtkRenderer()

        self.ren.SetBackground( 0.329412, 0.34902, 0.427451 )

        self.ren.AddActor( self.actorSkin )

        self.ren.AddActor( self.actorBone )

       

        self.ren.ResetCameraClippingRange()

 

       

        self.renWin.AddRenderer(self.ren)

        self.vtkw = vtkTkRenderWindowInteractor(self.__frame,

            rw=self.renWin, width=400, height=400)

 

  • Also notice the command self.renWin.Render().  This command will cause all of the attached actors to update their pipelines thus creating a new rendering.

 

        self.renWin.Render()

        self.renWin.PolygonSmoothingOn()

        self.vtkw.Initialize()

        self.vtkw.pack(side="top", fill='both', expand=1)

        self.vtkw.Start()

  • showIsosurfaceHead: This public member function is called by a GUI menu item to set the mappers to the head volume of interest for both the skin isovalue and bone isovalue. 

    def showIsosurfaceHead( self ):

        self.geoSkinMapper.SetInput( self.contourSkinTop.GetOutput() )

        self.geoBoneMapper.SetInput( self.contourBoneHead.GetOutput() )       

        self.renWin.Render()        

 

 

 

  • updateSurface: This function is called by the dialog box responsible for changing the color and opacity values of a particular isovalue actor.  Because the Tkinter.Scale widgets (part of the SliderWithValue class) cannot have floating point values, it is necessary to implicitly create them by having a scalar range equivalent to the desired decimal precision.  Since there are 256 values for red, green, and blue (typically), this was the chosen denominator to make the decimal value for each color component.  In the case of opacity, 100 seemed reasonable.  The display in these classes are the following: RGB values are displayed as values 0-255 while opacity values are specified as a % value from 0-100.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    def updateSurface( self, dictSettings ):

        if ( dictSettings[ 'tissue' ] == self.SKIN ):

            # ISOSURFACE

            self.actorSkin.GetProperty().SetColor(

                dictSettings[ 'red' ]/256.0,

                dictSettings[ 'green' ]/256.0,

                dictSettings[ 'blue' ]/256.0 )

            self.actorSkin.GetProperty().SetOpacity(

                dictSettings[ 'opaque' ]/100.0 )

 

           

        elif ( dictSettings[ 'tissue' ] == self.BONE ):

            # ISOSURFACE

            self.actorBone.GetProperty().SetColor(

                dictSettings[ 'red' ]/256.0,

                dictSettings[ 'green' ]/256.0,

                dictSettings[ 'blue' ]/256.0 )

            self.actorBone.GetProperty().SetOpacity(

                dictSettings[ 'opaque' ]/100.0 )

 

        self.renWin.Render()

 

  • updateSamplingRate: This member function is called by the dialog box responsible for adjusting the sampling rate of the volume of interest.  The values are passed as parameters to this function which then update the appropriate part of the pipeline.  The render call updates the display.

 

    def updateSamplingRate( self, xSample, ySample, zSample ):

        self.voiHead.SetSampleRate( xSample,ySample,zSample )

        self.voiFeet.SetSampleRate( xSample,ySample,zSample )

 

        self.renWin.Render()     

 

  • __removeOldActorsAndSetNewActor: This private member function removes the actors before changing the mappers to different volumes of interest.  In order to make sure the pipelines update properly, a render call is given.

    def __removeOldActorsAndSetNewActor( self, actorID ):

        if ( self.__lastActorID == self.ISO ):

            self.ren.RemoveActor( self.actorSkin )

            self.ren.RemoveActor( self.actorBone )

           

        self.renWin.Render()

        self.__lastActorID = actorID

 

  • destroy:  This public member function is called when the exit menu option is selected in the main window.  The order that the VTK rendering widgets are destroyed in not correct because it seems that an error appears every time the program exits with the menu item indicating that an incorrect destruction order occurred.

 

    def destroy( self ):

        del self.ren

        del self.renWin

        del self.vtkw

 

 

 

Example 4.2: Code for VTKRender class

 

 

 

<<< Previous

GUI

 

 

Table of Contents

 

 

Next >>>

DialogOptionVOI