class ZincScene(QtOpenGL.QGLWidget): # init start def __init__(self, parent=None): ''' Call the super class init functions, create a Zinc context and set the scene viewer handle to None. ''' QtOpenGL.QGLWidget.__init__(self, parent) self._initZincContext() self._imageDataLocation = None self._slider_value = 0 self._component = 0 self._action_transfrom = True self._undoRedoStack = QtGui.QUndoStack(self) def setImageDataLocation(self, imageDataLocation): self._imageDataLocation = imageDataLocation def _initZincContext(self): self._context = Context("digitiser") self._scene_viewer = None def initializeGL(self): ''' Initialise the Zinc scene, create the finite element, and the surface to visualise it. ''' # From the context get the default scene veiwer package and set up a scene_viewer. scene_viewer_package_ = self._context.getDefaultSceneViewerPackage() self._scene_viewer = scene_viewer_package_.createSceneViewer(SceneViewer.BUFFERING_MODE_DOUBLE, SceneViewer.STEREO_MODE_ANY) # ## childRegionCreate start self.root_region = self._context.getDefaultRegion() # create a number of independant 3D meshes - one for each image. # automatically alter the range depending on the number of slices. # for i in range(0, self.number_of_images): # ## childRegionCreate end # Get the default graphics module from the context and enable renditions graphics_module = self._context.getDefaultGraphicsModule() graphics_module.enableRenditions(self.root_region) graphics_module.defineStandardMaterials() # Create a filter for visibility flags which will allow us to see our graphic. graphics_filter = graphics_module.createFilterVisibilityFlags() # Create a scene and set the _surface_region tree for it to show. We also set the graphics filter for the scene # otherwise nothing will be visible. scene = graphics_module.createScene() scene.setRegion(self.root_region) scene.setFilter(graphics_filter) # Set the scene to our scene viewer. self._scene_viewer.setScene(scene) # function calls # self._() self.createMaterialUsingImageField() self.createSurfaceRegion() self.createFiniteElements() self.createSurfaceGraphics() self.createNodeRegion() self.createNodeGraphics() self._scene_viewer.viewAll() def createMaterialUsingImageField(self): ''' Use an image field in a grpahics material to create a n OpenGL texture ''' # create a graphics material from the graphics module, assign it a name # and set flag to true graphics_module = self._context.getDefaultGraphicsModule() self._material = graphics_module.createMaterial() self._material.setName('texture_block') self._material.setAttributeInteger(GraphicsMaterial.ATTRIBUTE_IS_MANAGED, 1) # Get a handle to the root _surface_region root_region = self._context.getDefaultRegion() # The field module allows us to create a field image to # store the image data into. field_module = root_region.getFieldModule() # Create an image field. A temporary xi source field is created for us. image_field = field_module.createImage() image_field.setName('image_field') image_field.setFilterMode(image_field.FILTER_LINEAR) # Create a stream information object that we can use to read the # image file from disk stream_information = image_field.createStreamInformation() # specify depth of texture block i.e. number of images # stream_information.setAttributeInteger(stream_information.IMAGE_ATTRIBUTE_, self.number_of_images) # Load images onto an invidual texture blocks. directory = self._imageDataLocation.location() files = os.listdir(directory) files.sort(key=alphanum_key) for filename in files: # We are reading in a file from the local disk so our resource is a file. stream_information.createResourceFile(os.path.join(directory, filename)) # Actually read in the image file into the image field. image_field.read(stream_information) self._material.setImageField(1, image_field) def create3DFiniteElement(self, field_module, finite_element_field, node_coordinate_set): ''' Create finite element from a template ''' # Find a special node set named 'cmiss_nodes' nodeset = field_module.findNodesetByName('cmiss_nodes') node_template = nodeset.createNodeTemplate() # Set the finite element coordinate field for the nodes to use node_template.defineField(finite_element_field) field_cache = field_module.createCache() node_identifiers = [] # Create eight nodes to define a cube finite element for node_coordinate in node_coordinate_set: node = nodeset.createNode(-1, node_template) node_identifiers.append(node.getIdentifier()) # Set the node coordinates, first set the field cache to use the current node field_cache.setNode(node) # Pass in floats as an array finite_element_field.assignReal(field_cache, node_coordinate) # Use a 3D mesh to to create the 3D finite element. mesh = field_module.findMeshByDimension(3) element_template = mesh.createElementTemplate() element_template.setShapeType(Element.SHAPE_CUBE) element_node_count = 8 element_template.setNumberOfNodes(element_node_count) # Specify the dimension and the interpolation function for the element basis function linear_basis = field_module.createElementBasis(3, ElementBasis.FUNCTION_LINEAR_LAGRANGE) # the indecies of the nodes in the node template we want to use. node_indexes = [1, 2, 3, 4, 5, 6, 7, 8] # Define a nodally interpolated element field or field component in the # element_template element_template.defineFieldSimpleNodal(finite_element_field, -1, linear_basis, node_indexes) for i, node_identifier in enumerate(node_identifiers): node = nodeset.findNodeByIdentifier(node_identifier) element_template.setNode(i + 1, node) mesh.defineElement(-1, element_template) def createSurfaceRegion(self): self._surface_region = self.root_region.createChild('surface') def createSurfaceGraphics(self): ''' To visualize the 3D finite element that we have created for each _surface_region, we use a surface graphic then set a _material for that surface to use. ''' graphics_module = self._context.getDefaultGraphicsModule() # we iterate over the regions that we kept a handle to and use an index to get a # matching list of graphic _material names # for i, _surface_region in enumerate(self.regions_): rendition = graphics_module.getRendition(self._surface_region) field_module = self._surface_region.getFieldModule() # search the graphic module for the current graphic _material self._material = graphics_module.findMaterialByName('texture_block') rendition.beginChange() # Create a surface graphic and set it's coordinate field to the finite element coordinate field # named coordinates outline = rendition.createGraphic(Graphic.GRAPHIC_LINES) finite_element_field = field_module.findFieldByName('coordinates') outline.setCoordinateField(finite_element_field) # Create three isosurface planes in the x, y and z directions whose positions in the texture block # can be altered using sliders # ## x component self._iso_graphic = rendition.createGraphicIsoSurface() self._iso_graphic.setCoordinateField(finite_element_field) self._iso_graphic.setMaterial(self._material) xi_field = field_module.findFieldByName('xi') self._iso_graphic.setTextureCoordinateField(xi_field) # set the yz scalar field to our isosurface self._iso_graphic.setScalarField(self._scalar_field[0]) # define the initial position of the isosurface on the texture block self._iso_graphic.setIsoValues([0.0]) # Range(1, self.initial_positions[0], self.initial_positions[0]) # Outline the isosurface plane with a green border self._iso_line = rendition.createGraphicIsoSurface() self._iso_line.setCoordinateField(finite_element_field) self.setIsoLineMaterial('green') self._iso_line.setUseElementType(Graphic.USE_ELEMENT_FACES) self._iso_line.setScalarField(self._scalar_field[0]) self._iso_line.setIsoValues([0.0]) # (1, self.initial_positions[0], self.initial_positions[0]) rendition.endChange() def createNodeRegion(self): self._points_region = self.root_region.createChild('points') field_module = self._points_region.getFieldModule() field_module.beginChange() # Create a finite element field with 3 components to represent 3 dimensions finite_element_field = field_module.createFiniteElement(3) # Set the name of the field finite_element_field.setName('coordinates') # Set the attribute is managed to 1 so the field module will manage the field for us finite_element_field.setAttributeInteger(Field.ATTRIBUTE_IS_MANAGED, 1) finite_element_field.setAttributeInteger(Field.ATTRIBUTE_IS_COORDINATE, 1) field_module.endChange() def createNodeGraphics(self): graphics_module = self._context.getDefaultGraphicsModule() rendition = graphics_module.getRendition(self._points_region) field_module = self._points_region.getFieldModule() coordinate_field = field_module.findFieldByName('coordinates') rendition.beginChange() node_graphic = rendition.createGraphic(Graphic.GRAPHIC_NODE_POINTS) node_graphic.setCoordinateField(coordinate_field) node_graphic.setGlyphType(Graphic.GLYPH_TYPE_SPHERE) node_graphic.setGlyphSize([0.01, 0.01, 0.01]) rendition.endChange() def setIsoLineMaterial(self, name): graphics_module = self._context.getDefaultGraphicsModule() material = graphics_module.findMaterialByName(name) self._iso_line.setMaterial(material) def getPointCloud(self): point_cloud = [] field_module = self._points_region.getFieldModule() field_module.beginChange() field_cache = field_module.createCache() coordinate_field = field_module.findFieldByName('coordinates') nodeset = field_module.findNodesetByName('cmiss_nodes') template = nodeset.createNodeTemplate() template.defineField(coordinate_field) node_iterator = nodeset.createNodeIterator() node = node_iterator.next() while node.isValid(): field_cache.setNode(node) position = coordinate_field.evaluateReal(field_cache, 3)[1] node = node_iterator.next() point_cloud.append(position) field_module.endChange() return point_cloud def createFiniteElements(self): ''' Create finite element meshes for each of the images ''' # Define the coordinates for each 3D element node_coordinate_set = [[0, 0, 0], [1, 0, 0], [0, 0, 1], [1, 0, 1], [0, 1, 0], [1, 1, 0], [0, 1, 1], [1, 1, 1]] field_module = self._surface_region.getFieldModule() field_module.beginChange() # Create a finite element field with 3 components to represent 3 dimensions finite_element_field = field_module.createFiniteElement(3) # Set the name of the field finite_element_field.setName('coordinates') # Set the attribute is managed to 1 so the field module will manage the field for us finite_element_field.setAttributeInteger(Field.ATTRIBUTE_IS_MANAGED, 1) finite_element_field.setAttributeInteger(Field.ATTRIBUTE_IS_COORDINATE, 1) self.create3DFiniteElement(field_module, finite_element_field, node_coordinate_set) field_module.defineAllFaces() field_module.endChange() # Create the three scalar fields in the x, y, z directions # ## x component self._scalar_field = [] sf = field_module.createComponent(finite_element_field, 0) sf.setAttributeInteger(Field.ATTRIBUTE_IS_MANAGED, 1) self._scalar_field.append(sf) sf = field_module.createComponent(finite_element_field, 1) sf.setAttributeInteger(Field.ATTRIBUTE_IS_MANAGED, 1) self._scalar_field.append(sf) sf = field_module.createComponent(finite_element_field, 2) sf.setAttributeInteger(Field.ATTRIBUTE_IS_MANAGED, 1) self._scalar_field.append(sf) def setSliderValue(self, value): self._slider_value = value self._iso_graphic.setIsoValues([value / 100]) self._iso_line.setIsoValues([value / 100]) self.updateGL() def setFieldComponent(self, component): self._component = component self._iso_graphic.setScalarField(self._scalar_field[component]) self._iso_line.setScalarField(self._scalar_field[component]) self._iso_graphic.setIsoValues([self._slider_value / 100]) self._iso_line.setIsoValues([self._slider_value / 100]) self.updateGL() def actionButtonClicked(self): self._action_transfrom = not self._action_transfrom if self._action_transfrom: self.setIsoLineMaterial('green') else: self.setIsoLineMaterial('red') self.updateGL() def destroy(self): ''' Destroys the contents inside the scene ''' del self._scene_viewer del self._context self._initZincContext() newContext = QtOpenGL.QGLContext(self.format(), self) newContext.create() newContext.makeCurrent() self.setContext(newContext, None, True) self.makeCurrent() def paintGL(self): ''' Render the scene for this scene viewer. The QGLWidget has already set up the correct OpenGL buffer for us so all we need do is render into it. The scene viewer will clear the background so any OpenGL drawing of your own needs to go after this API call. ''' self._scene_viewer.renderScene() def resizeGL(self, width, height): ''' Respond to widget resize events. ''' self._scene_viewer.setViewportSize(width, height) def getPlaneCoordinate2(self, x, y): size = self.size() width = size.width() height = size.height() _, eyex, eyey, eyez, lookatx, lookaty, lookatz, upx, upy, upz = self._scene_viewer.getLookatParameters() _, left, right, bottom, top, near_plane, far_plane = self._scene_viewer.getViewingVolume() # print(volume) eye = numpy.array([eyex, eyey, eyez]) lookat = numpy.array([lookatx, lookaty, lookatz]) up = numpy.array([upx, upy, upz]) hclip = numpy.array([(x - width / 2.0) / (width / 2.0), (y - height / 2.0) / (height / 2.0), 0.0, 1.0]) pr = numpy.array([[1.0 / right, 0.0, 0.0, 0.0], [0.0, 1.0 / top, 0.0, 0.0], [0.0, 0.0, -2.0 / (far_plane - near_plane), -(far_plane + near_plane) / (far_plane - near_plane)], [0.0, 0.0, 0.0, 1.0]]) pr_inv = numpy.linalg.inv(pr) heye = numpy.dot(pr_inv, hclip) zaxis = lookat - eye zaxis = zaxis / numpy.linalg.norm(zaxis) # print(zaxis) xaxis = numpy.cross(up, zaxis) xaxis = xaxis / numpy.linalg.norm(xaxis) yaxis = numpy.cross(zaxis, xaxis) yaxis = yaxis / numpy.linalg.norm(yaxis) # print(xaxis) # print(yaxis) # print(zaxis) # print(heye) mv_rot = numpy.array([xaxis, yaxis, zaxis]) # print(mv_rot) mv_rot = numpy.transpose(mv_rot) # print(mv_rot) mv_tr = numpy.array([numpy.dot(-xaxis, eye), numpy.dot(-yaxis, eye), numpy.dot(-zaxis, eye)]) mv = numpy.array([[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]]) for i in [0, 1, 2]: for j in [0, 1, 2]: mv[i, j] = mv_rot[i, j] mv[0, 3] = mv_tr[0] mv[1, 3] = mv_tr[1] mv[2, 3] = mv_tr[2] # print(mv_tr) # print(mv) mv_inv = numpy.linalg.inv(mv) hposition = numpy.dot(mv_inv, heye) return [hposition[0] / hposition[3], hposition[1] / hposition[3], hposition[2] / hposition[3]] def unproject(self, x, y, z): return self._scene_viewer.unproject(x, y, z)[1:] def getPlaneCoordinate(self, x, y): unproject_near = self.unproject(x, y, 0.0) unproject_far = self.unproject(x, y, 1.0) p0 = numpy.array([0.0, 0.0, 0.0]) p0[self._component] = self._slider_value / 100.0 n = numpy.array([0, 0, 0]) n[self._component] = 1.0 l0 = numpy.array(unproject_near) l = numpy.array(unproject_far) - l0 num = numpy.dot(p0 - l0, n) den = numpy.dot(l, n) if -0.0001 < den < 0.0001: return None d = num / den pos = d * l + l0 return [pos[0], pos[1], pos[2]] def addNode(self, x, y): position = self.getPlaneCoordinate(x, y) if position: field_module = self._points_region.getFieldModule() self._undoRedoStack.push(CommandAdd(field_module, position, self.updateGL)) def mousePressEvent(self, mouseevent): ''' Inform the scene viewer of a mouse press event. ''' if self._action_transfrom: scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_BUTTON_PRESS) if mouseevent.button() == QtCore.Qt.LeftButton: scene_input.setButtonNumber(1) elif mouseevent.button() == QtCore.Qt.MiddleButton: scene_input.setButtonNumber(2) elif mouseevent.button() == QtCore.Qt.RightButton: scene_input.setButtonNumber(3) self._scene_viewer.processInput( scene_input) else: self.addNode(mouseevent.x(), mouseevent.y()) def mouseReleaseEvent(self, mouseevent): ''' Inform the scene viewer of a mouse release event. ''' if self._action_transfrom: scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_BUTTON_RELEASE) if mouseevent.button() == QtCore.Qt.LeftButton: scene_input.setButtonNumber(1) elif mouseevent.button() == QtCore.Qt.MiddleButton: scene_input.setButtonNumber(2) elif mouseevent.button() == QtCore.Qt.RightButton: scene_input.setButtonNumber(3) self._scene_viewer.processInput( scene_input) def mouseMoveEvent(self, mouseevent): ''' Inform the scene viewer of a mouse move event and update the OpenGL scene to reflect this change to the viewport. ''' if self._action_transfrom: scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_MOTION_NOTIFY) if mouseevent.type() == QtCore.QEvent.Leave: scene_input.setPosition(-1, -1) self._scene_viewer.processInput( scene_input) # The viewport has been changed so update the OpenGL scene. self.updateGL()
class ZincScene(QtOpenGL.QGLWidget): # init start def __init__(self, parent = None): ''' Call the super class init functions, create a Zinc context and set the scene viewer handle to None. ''' QtOpenGL.QGLWidget.__init__(self, parent) # Create a Zinc context from which all other objects can be derived either directly or indirectly. self._context = Context("autosegmenter") self._scene_viewer = None self._imageDataLocation = None # init end def setImageDataLocation(self, imageDataLocation): self._imageDataLocation = imageDataLocation def getPointCloud(self): point_cloud = [] field_module = self._point_cloud_region.getFieldModule() field_module.beginChange() field_cache = field_module.createCache() coordinate_field = field_module.findFieldByName('coordinates') nodeset = field_module.findNodesetByName('cmiss_nodes') template = nodeset.createNodeTemplate() template.defineField(coordinate_field) node_iterator = nodeset.createNodeIterator() node = node_iterator.next() while node.isValid(): field_cache.setNode(node) position = coordinate_field.evaluateReal(field_cache, 3)[1] node = node_iterator.next() point_cloud.append(position) field_module.endChange() return point_cloud def setImagePlaneVisibility(self, state): self._iso_graphic.setVisibilityFlag(state != 0) self.updateGL() def setSegmentationVisibility(self, state): self._contour.setVisibilityFlag(state != 0) self.updateGL() def setPointCloudVisibility(self, state): self._point_cloud.setVisibilityFlag(state != 0) self.updateGL() # initializeGL start def initializeGL(self): ''' Initialise the Zinc scene for drawing the axis glyph at a point. ''' # From the context get the default scene viewer module. scene_viewer_module = self._context.getDefaultSceneViewerModule() # From the scene viewer module we can create a scene viewer, we set up the scene viewer to have the same OpenGL properties as # the QGLWidget. self._scene_viewer = scene_viewer_module.createSceneViewer(SceneViewer.BUFFERING_MODE_DOUBLE, SceneViewer.STEREO_MODE_ANY) # Get a the root region to create the point in. Every context has a default region called the root region. root_region = self._context.getDefaultRegion() # output_region = root_region.createChild('output') # Get the default graphics module from the context and enable renditions graphics_module = self._context.getDefaultGraphicsModule() graphics_module.enableRenditions(root_region) glyph_module = graphics_module.getGlyphModule() glyph_module.createStandardGlyphs() graphics_module.defineStandardMaterials() gold = graphics_module.findMaterialByName('gold') # Once the renditions have been enabled for a region tree you can get a valid # handle for a rendition and create graphics for it. rendition = graphics_module.getRendition(root_region) tessellation_module = graphics_module.getTessellationModule() tessellation = tessellation_module.getDefaultTessellation() tessellation.setMinimumDivisions([100]) tessellation_module.setDefaultTessellation(tessellation) # We use the beginChange and endChange to wrap any immediate changes and will # streamline the rendering of the scene. rendition.beginChange() # Visualise images self.createFiniteElements(root_region) self.createMaterialUsingImageField() # Create a filter for visibility flags which will allow us to see our graphic. By default graphics # are created with their visibility flags set to true. graphics_filter = graphics_module.createFilterVisibilityFlags() # Create a scene and set the region tree for it to show. We also set the graphics filter for the scene # otherwise nothing will be visible. scene = graphics_module.createScene() scene.setRegion(root_region) scene.setFilter(graphics_filter) field_module = root_region.getFieldModule() xi_field = field_module.findFieldByName('xi') finite_element_field = field_module.findFieldByName('coordinates') self._segmented_image_field = field_module.createImageFromSource(xi_field, self._segmented_field) self._contour = rendition.createGraphicContours() self._contour.setCoordinateField(finite_element_field) # self._contour.setMaterial(self._material) # print(self._contour2.setTextureCoordinateField(xi_field)) # set the yz scalar field to our isosurface self._contour.setIsoscalarField(self._segmented_image_field) self._contour.setMaterial(gold) # define the initial position of the isosurface on the texture block self._contour.setListIsovalues([0.2]) # Range(1, self.initial_positions[0], self.initial_positions[0]) nodeset, output_coordinates = self.setupOutputRegion(root_region) rendition.convertToPointCloud(graphics_filter, nodeset, output_coordinates, 0.0, 0.0, 10000.0, 1.0) # Create a graphic point in our rendition and set it's glyph type to axes. # Set the scene to our scene viewer. self.createSurfaceGraphics(root_region) self._scene_viewer.setScene(scene) rendition.endChange() # Let the rendition render the scene. # initializeGL end self._scene_viewer.viewAll() def setupOutputRegion(self, root_region): self._point_cloud_region = root_region.createChild('output') field_module = self._point_cloud_region.getFieldModule() finite_element_field = field_module.createFiniteElement(3) # Set the name of the field, we give it label to help us understand it's purpose finite_element_field.setName('coordinates') # Set the attribute is managed to 1 so the field module will manage the field for us finite_element_field.setManaged(True) nodeset = field_module.findNodesetByDomainType(Field.DOMAIN_NODES) graphics_module = self._context.getDefaultGraphicsModule() rendition = graphics_module.getRendition(self._point_cloud_region) self._point_cloud = rendition.createGraphicPoints() self._point_cloud.setDomainType(Field.DOMAIN_NODES) self._point_cloud.setCoordinateField(finite_element_field) attributes = self._point_cloud.getPointAttributes() attributes.setGlyphType(Graphic.GLYPH_TYPE_SPHERE) attributes.setBaseSize([0.01]) return (nodeset, finite_element_field) def createSurfaceGraphics(self, region): ''' To visualize the 3D finite element that we have created for each _surface_region, we use a surface graphic then set a _material for that surface to use. ''' graphics_module = self._context.getDefaultGraphicsModule() # we iterate over the regions that we kept a handle to and use an index to get a # matching list of graphic _material names # for i, _surface_region in enumerate(self.regions_): rendition = graphics_module.getRendition(region) field_module = region.getFieldModule() finite_element_field = field_module.findFieldByName('coordinates') # Create three isosurface planes in the x, y and z directions whose positions in the texture block # can be altered using sliders # ## x component self._iso_graphic = rendition.createGraphicContours() self._iso_graphic.setCoordinateField(finite_element_field) self._iso_graphic.setMaterial(self._material) xi_field = field_module.findFieldByName('xi') self._iso_graphic.setTextureCoordinateField(xi_field) # set the yz scalar field to our isosurface self._iso_graphic.setIsoscalarField(self._scalar_field) # define the initial position of the isosurface on the texture block self._iso_graphic.setListIsovalues([0.0]) def createMaterialUsingImageField(self): ''' Use an image field in a grpahics material to create a n OpenGL texture ''' # create a graphics material from the graphics module, assign it a name # and set flag to true graphics_module = self._context.getDefaultGraphicsModule() self._material = graphics_module.createMaterial() self._material.setName('texture_block') # self._material.setManaged(True) # Get a handle to the root _surface_region root_region = self._context.getDefaultRegion() # The field module allows us to create a field image to # store the image data into. field_module = root_region.getFieldModule() xi_field = field_module.findFieldByName('coordinates') # Create an image field. A temporary xi source field is created for us. self._image_field = field_module.createImageWithDomain(xi_field) # self._image_field.setName('image_field') self._image_field.setFilterMode(self._image_field.FILTER_LINEAR) # Create a stream information object that we can use to read the # image file from disk stream_information = self._image_field.createStreamInformation() # specify depth of texture block i.e. number of images # stream_information.setAttributeInteger(stream_information.IMAGE_ATTRIBUTE_, self.number_of_images) # Load images onto an invidual texture blocks. directory = self._imageDataLocation.location() files = os.listdir(directory) files.sort(key=alphanum_key) for filename in files: # We are reading in a file from the local disk so our resource is a file. string_name = str(os.path.join(directory, filename)) stream_information.createResourceFile(string_name) # Actually read in the image file into the image field. self._image_field.setAttributeReal(FieldImage.IMAGE_ATTRIBUTE_PHYSICAL_WIDTH_PIXELS, 1) self._image_field.setAttributeReal(FieldImage.IMAGE_ATTRIBUTE_PHYSICAL_HEIGHT_PIXELS, 1) self._image_field.setAttributeReal(FieldImage.IMAGE_ATTRIBUTE_PHYSICAL_DEPTH_PIXELS, 1) self._image_field.read(stream_information) self._material.setImageField(1, self._image_field) self._smooth_field = field_module.createCurvatureAnisotropicDiffusionImageFilter(self._image_field, 0.0625, 2, 5) self._segmented_field = field_module.createConnectedThresholdImageFilter(self._smooth_field, 0.2, 1.0, 1, 1, [0.5, 0.6111, 0.3889]) def setSliderValue(self, value): self._iso_graphic.setListIsovalues([value / 100.0]) self.updateGL() def createFiniteElements(self, region): ''' Create finite element meshes for each of the images ''' # Define the coordinates for each 3D element # node_coordinate_set = [[0, 0, 0], [101, 0, 0], [0, 0, 52.0], [101, 0, 52.0], [0, 109, 0], [101, 109, 0], [0, 109, 52.0], [101, 109, 52.0]] # a , b, c = 53.192, 49.288, 36.4 # node_coordinate_set = [[a, 0, 0], [a, 0, c], [0, 0, 0], [0, 0, c], [a, b, 0], [a, b, c], [0, b, 0], [0, b, c]] # a , b, c = 101, 109, 52 field_module = region.getFieldModule() field_module.beginChange() # Create a finite element field with 3 components to represent 3 dimensions finite_element_field = field_module.createFiniteElement(3) # Set the name of the field finite_element_field.setName('coordinates') # Set the attribute is managed to 1 so the field module will manage the field for us finite_element_field.setManaged(True) finite_element_field.setAttributeInteger(Field.ATTRIBUTE_IS_COORDINATE, 1) a, b, c = 1, 1, 1 node_coordinate_set = [[0, 0, 0], [a, 0, 0], [0, b, 0], [a, b, 0], [0, 0, c], [a, 0, c], [0, b, c], [a, b, c]] self.create3DFiniteElement(field_module, finite_element_field, node_coordinate_set) self._scalar_field = field_module.createComponent(finite_element_field, 3) field_module.defineAllFaces() field_module.endChange() def create3DFiniteElement(self, field_module, finite_element_field, node_coordinate_set): ''' Create finite element from a template ''' # Find a special node set named 'cmiss_nodes' nodeset = field_module.findNodesetByName('cmiss_nodes') node_template = nodeset.createNodeTemplate() # Set the finite element coordinate field for the nodes to use node_template.defineField(finite_element_field) field_cache = field_module.createCache() node_identifiers = [] # Create eight nodes to define a cube finite element for node_coordinate in node_coordinate_set: node = nodeset.createNode(-1, node_template) node_identifiers.append(node.getIdentifier()) # Set the node coordinates, first set the field cache to use the current node field_cache.setNode(node) # Pass in floats as an array finite_element_field.assignReal(field_cache, node_coordinate) # Use a 3D mesh to to create the 3D finite element. mesh = field_module.findMeshByDimension(3) element_template = mesh.createElementTemplate() element_template.setShapeType(Element.SHAPE_CUBE) element_node_count = 8 element_template.setNumberOfNodes(element_node_count) # Specify the dimension and the interpolation function for the element basis function linear_basis = field_module.createElementBasis(3, ElementBasis.FUNCTION_LINEAR_LAGRANGE) # the indecies of the nodes in the node template we want to use. node_indexes = [1, 2, 3, 4, 5, 6, 7, 8] # Define a nodally interpolated element field or field component in the # element_template element_template.defineFieldSimpleNodal(finite_element_field, -1, linear_basis, node_indexes) for i, node_identifier in enumerate(node_identifiers): node = nodeset.findNodeByIdentifier(node_identifier) element_template.setNode(i + 1, node) mesh.defineElement(-1, element_template) # paintGL start def paintGL(self): ''' Render the scene for this scene viewer. The QGLWidget has already set up the correct OpenGL buffer for us so all we need do is render into it. The scene viewer will clear the background so any OpenGL drawing of your own needs to go after this API call. ''' self._scene_viewer.renderScene() # paintGL end # resizeGL start def resizeGL(self, width, height): ''' Respond to widget resize events. ''' self._scene_viewer.setViewportSize(width, height) # resizeGL end def mousePressEvent(self, mouseevent): ''' Inform the scene viewer of a mouse press event. ''' scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_BUTTON_PRESS) scene_input.setButton(button_map[mouseevent.button()]) self._scene_viewer.processInput(scene_input) def mouseReleaseEvent(self, mouseevent): ''' Inform the scene viewer of a mouse release event. ''' scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_BUTTON_RELEASE) scene_input.setButton(button_map[mouseevent.button()]) self._scene_viewer.processInput(scene_input) def mouseMoveEvent(self, mouseevent): ''' Inform the scene viewer of a mouse move event and update the OpenGL scene to reflect this change to the viewport. ''' scene_input = self._scene_viewer.getInput() scene_input.setPosition(mouseevent.x(), mouseevent.y()) scene_input.setType(SceneViewerInput.INPUT_EVENT_TYPE_MOTION_NOTIFY) if mouseevent.type() == QtCore.QEvent.Leave: scene_input.setPosition(-1, -1) self._scene_viewer.processInput(scene_input) # The viewport has been changed so update the OpenGL scene. self.updateGL()