def create_material_using_image_field(region: Region, image_field: Field, colour_mapping_type=None, image_range=None)\ -> Material: """ Use an image field in a material to create an OpenGL texture. Returns the created material. :param region: Used to obtain materialmodule, spectrummodule. :param image_field: Zinc FieldImage. :param colour_mapping_type: Zinc Spectrumcomponent colour mapping type or None for default rainbow. :param image_range: Sequence of minimum, maximum, or None to use default. :return: The material that contains the image field as a texture. """ scene = region.getScene() materialmodule = scene.getMaterialmodule() spectrummodule = scene.getSpectrummodule() with ChangeManager(materialmodule), ChangeManager(spectrummodule): material = materialmodule.createMaterial() spectrum = spectrummodule.createSpectrum() component = spectrum.createSpectrumcomponent() if colour_mapping_type is None: colour_mapping_type = component.COLOUR_MAPPING_TYPE_RAINBOW component.setColourMappingType(colour_mapping_type) if image_range is not None: component.setRangeMinimum(image_range[0]) component.setRangeMaximum(image_range[1]) material.setTextureField(1, image_field) return material
def setPathParameters(region, nodeValueLabels, nodeValues, editGroupName=None): ''' Set node parameters for coordinates field in path from listed values. :param nodeValueLabels: List of nodeValueLabels to set e.g. [ Node.VALUE_LABEL_VALUE, Node.VALUE_LABEL_D_DS1 ] :param nodeValues: List of values for each type e.g. [ xlist, d1list ] :param editGroupName: Optional name of existing or new Zinc group to record modified nodes in. ''' fieldmodule = region.getFieldmodule() coordinates = fieldmodule.findFieldByName('coordinates').castFiniteElement() componentsCount = coordinates.getNumberOfComponents() # following requires at least one value label and node, assumes consistent values and components counts nodeValueLabelsCount = len(nodeValueLabels) nodesCount = len(nodeValues[0]) nodes = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) assert nodesCount == nodes.getSize() with ChangeManager(fieldmodule): if editGroupName: editGroup = findOrCreateFieldGroup(fieldmodule, editGroupName, managed=True) editNodeGroup = editGroup.getFieldNodeGroup(nodes) if not editNodeGroup.isValid(): editNodeGroup = editGroup.createFieldNodeGroup(nodes) editNodesetGroup = editNodeGroup.getNodesetGroup() cache = fieldmodule.createFieldcache() nodeIter = nodes.createNodeiterator() node = nodeIter.next() n = 0 while node.isValid(): cache.setNode(node) for v in range(nodeValueLabelsCount): coordinates.setNodeParameters(cache, -1, nodeValueLabels[v], 1, nodeValues[v][n]) if editGroupName: editNodesetGroup.addNode(node) node = nodeIter.next() n += 1
def _manage_groups(self, group): with ChangeManager(self._field_module): print(group) term_group = self._field_module.findFieldByName(group).castGroup() term_group.setSubelementHandlingMode(FieldGroup.SUBELEMENT_HANDLING_MODE_FULL) mesh2d = self._field_module.findMeshByDimension(2) term_face_group = term_group.getFieldElementGroup(mesh2d) if not term_face_group.isValid(): term_face_group = term_group.createFieldElementGroup(mesh2d) term_mesh_group = term_face_group.getMeshGroup() is_exterior = self._field_module.createFieldIsExterior() is_endo = self._field_module.createFieldAnd(is_exterior, self._field_module.createFieldIsOnFace(Element.FACE_TYPE_XI3_0)) tmp_element_group = self._field_module.createFieldElementGroup(mesh2d) tmp_mesh_group = tmp_element_group.getMeshGroup() tmp_mesh_group.addElementsConditional(self._field_module.createFieldAnd(term_face_group, is_endo)) term_group.clear() term_mesh_group.addElementsConditional(tmp_element_group) # delete any temporary fields del tmp_element_group del tmp_mesh_group del is_endo filename = os.path.basename(self._scaffold_file).split('.')[0] + '_regrouped.exf' path = os.path.dirname(self._scaffold_file) self._output_filename = os.path.join(path, filename) self._region.writeFile(self._output_filename)
def generate(self, region, applyTransformation=True): ''' Generate the finite element scaffold and define annotation groups. :param applyTransformation: If True (default) apply scale, rotation and translation to node coordinates. Specify False if client will transform, e.g. with graphics transformations. ''' self._region = region with ChangeManager(region.getFieldmodule()): self._autoAnnotationGroups = self._scaffoldType.generateMesh( region, self._scaffoldSettings) # need next node identifier for creating user-defined marker points nodes = region.getFieldmodule().findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) self._nextNodeIdentifier = get_maximum_node_identifier(nodes) + 1 if self._meshEdits: # apply mesh edits, a Zinc-readable model file containing node edits # Note: these are untransformed coordinates sir = region.createStreaminformationRegion() srm = sir.createStreamresourceMemoryBuffer(self._meshEdits) region.read(sir) # define user AnnotationGroups from serialised Dict self._userAnnotationGroups = [ AnnotationGroup.fromDict(dct, self._region) for dct in self._userAnnotationGroupsDict ] self._isGenerated = True if applyTransformation: self.applyTransformation()
def getNearestNodeAndGraphics(self, x, y): ''' :return: Node, Graphics OR None, None if none found. ''' scenefiltermodule = self._context.getScenefiltermodule() with ChangeManager(scenefiltermodule): oldSelectionfilter = self.getSelectionfilter() self.setSelectionfilter( scenefiltermodule.createScenefilterFieldDomainType( Field.DOMAIN_TYPE_NODES)) #print('pick',x,y,self._selectTol, 'DpiX', self.physicalDpiX(), self.logicalDpiX(), 'DpiY', self.physicalDpiY(), self.logicalDpiY()) #print(' width', self.width(), 'widthMM',self.widthMM(),'dpi',25.4*self.width()/self.widthMM(), # 'height', self.height(), 'heightMM',self.heightMM(),'dpi',25.4*self.height()/self.heightMM()) #app = QtCore.QCoreApplication.instance() #desktop = app.desktop() #dpmm = self.width()/self.widthMM() #print('dpmm',dpmm,'physicalDpiX',desktop.physicalDpiX(),'screenGeometry',desktop.screenGeometry(self)) tol = self._selectTol # *0.1*dpmm #print('tol',tol) self._scenepicker.setSceneviewerRectangle( self._sceneviewer, SCENECOORDINATESYSTEM_WINDOW_PIXEL_TOP_LEFT, x - tol, y - tol, x + tol, y + tol) node = self._scenepicker.getNearestNode() if node.isValid(): graphics = self._scenepicker.getNearestNodeGraphics() else: node = None graphics = None self.setSelectionfilter(oldSelectionfilter) return node, graphics
def setMarkerLocation(self, element: Element, xi: list): """ If the annotation group is a created marker point, set its element:xi location. If the marker also has a materialCoordinatesField, it is updated to the value at the supplied element:xi location. :param element: Element to set location in :param xi: xi coordinates (list of float) """ assert self._isMarker fieldmodule = self._group.getFieldmodule() mesh = get_highest_dimension_mesh(fieldmodule) assert mesh.containsElement( element), "Invalid element, not in highest dimension mesh" assert isinstance(xi, list) and (len(xi) >= mesh.getDimension()) with ChangeManager(fieldmodule): markerLocation = getAnnotationMarkerLocationField( fieldmodule, mesh) fieldcache = fieldmodule.createFieldcache() nodes = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) markerNode = self.getNodesetGroup( nodes).createNodeiterator().next() fieldcache.setNode(markerNode) markerLocation.assignMeshLocation(fieldcache, element, xi) if self._markerMaterialCoordinatesField: fieldcache.setMeshLocation(element, xi) result, materialCoordinates = self._markerMaterialCoordinatesField.evaluateReal( fieldcache, self._markerMaterialCoordinatesField.getNumberOfComponents( )) fieldcache.setNode(markerNode) self._markerMaterialCoordinatesField.assignReal( fieldcache, materialCoordinates)
def create_square_element(mesh: Mesh, finite_element_field: Field, node_coordinate_set): """ Create a single square 2-D finite element using the supplied finite element field and sequence of 4 n-D node coordinates. :param mesh: The Zinc Mesh to create elements in. :param finite_element_field: Zinc FieldFiniteElement to interpolate on element. :param node_coordinate_set: Sequence of 4 coordinates each with as many components as finite element field. :return: None """ assert mesh.getDimension() == 2 assert finite_element_field.castFiniteElement().isValid() assert len(node_coordinate_set) == 4 fieldmodule = finite_element_field.getFieldmodule() nodeset = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) node_template = nodeset.createNodetemplate() node_template.defineField(finite_element_field) element_template = mesh.createElementtemplate() element_template.setElementShapeType(Element.SHAPE_TYPE_SQUARE) linear_basis = fieldmodule.createElementbasis( 2, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE) eft = mesh.createElementfieldtemplate(linear_basis) element_template.defineField(finite_element_field, -1, eft) field_cache = fieldmodule.createFieldcache() with ChangeManager(fieldmodule): node_identifiers = [] for node_coordinate in node_coordinate_set: node = nodeset.createNode(-1, node_template) node_identifiers.append(node.getIdentifier()) field_cache.setNode(node) finite_element_field.assignReal(field_cache, node_coordinate) element = mesh.createElement(-1, element_template) element.setNodesByIdentifier(eft, node_identifiers) fieldmodule.defineAllFaces()
def fromDict(cls, dct, region): ''' Instantiate from dict. See toDict() :param region: Zinc region. :return: AnnotationGroup ''' assert dct['_AnnotationGroup'] name = dct['name'] ontId = dct['ontId'] dimension = dct['dimension'] identifierRangesString = dct['identifierRanges'] markerDct = dct.get('marker') identifierRanges = identifier_ranges_from_string( identifierRangesString) fieldmodule = region.getFieldmodule() with ChangeManager(fieldmodule): annotationGroup = cls(region, (name, ontId)) annotationGroup._group.setSubelementHandlingMode( FieldGroup.SUBELEMENT_HANDLING_MODE_FULL) if dimension > 0: meshGroup = annotationGroup.getMeshGroup( fieldmodule.findMeshByDimension(dimension)) mesh_group_add_identifier_ranges(meshGroup, identifierRanges) else: if markerDct: nodeIdentifier = int(identifierRanges[0][0]) annotationGroup._markerFromDict(nodeIdentifier, markerDct) nodesetGroup = annotationGroup.getNodesetGroup( fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES)) nodeset_group_add_identifier_ranges(nodesetGroup, identifierRanges) return annotationGroup
def group_add_group_elements(group: FieldGroup, other_group: FieldGroup, only_dimension=None): ''' Add to group elements and/or nodes from other_group. :param only_dimension: If set, only add objects of this dimension. ''' fieldmodule = group.getFieldmodule() with ChangeManager(fieldmodule): for dimension in [only_dimension] if only_dimension else range(4): if dimension > 0: mesh = fieldmodule.findMeshByDimension(dimension) element_group = group.getFieldElementGroup(mesh) if not element_group.isValid(): element_group = group.createFieldElementGroup(mesh) mesh_group = element_group.getMeshGroup() mesh_group.addElementsConditional( other_group.getFieldElementGroup(mesh)) elif dimension == 0: nodeset = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) node_group = group.getFieldNodeGroup(nodeset) if not node_group.isValid(): node_group = group.createFieldNodeGroup(nodeset) nodeset_group = node_group.getNodesetGroup() nodeset_group.addNodesConditional( other_group.getFieldNodeGroup(nodeset))
def test_mousecolonsegment1(self): """ Test creation of mouse colon segment scaffold. """ options = MeshType_3d_colonsegment1.getDefaultOptions("Mouse 1") context = Context("Test") region = context.getDefaultRegion() self.assertTrue(region.isValid()) annotationGroups = MeshType_3d_colonsegment1.generateBaseMesh(region, options) self.assertEqual(7, len(annotationGroups)) fieldmodule = region.getFieldmodule() self.assertEqual(RESULT_OK, fieldmodule.defineAllFaces()) mesh3d = fieldmodule.findMeshByDimension(3) self.assertEqual(160, mesh3d.getSize()) coordinates = fieldmodule.findFieldByName("coordinates").castFiniteElement() self.assertTrue(coordinates.isValid()) flatCoordinates = fieldmodule.findFieldByName("flat coordinates").castFiniteElement() self.assertTrue(flatCoordinates.isValid()) with ChangeManager(fieldmodule): one = fieldmodule.createFieldConstant(1.0) faceMeshGroup = createFaceMeshGroupExteriorOnFace(fieldmodule, Element.FACE_TYPE_XI3_1) surfaceAreaField = fieldmodule.createFieldMeshIntegral(one, coordinates, faceMeshGroup) surfaceAreaField.setNumbersOfPoints(4) flatSurfaceAreaField = fieldmodule.createFieldMeshIntegral(one, flatCoordinates, faceMeshGroup) flatSurfaceAreaField.setNumbersOfPoints(4) fieldcache = fieldmodule.createFieldcache() result, surfaceArea = surfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) self.assertAlmostEqual(surfaceArea, 468.17062489996886, delta=1.0E-6) result, flatSurfaceArea = flatSurfaceAreaField.evaluateReal(fieldcache, 1) self.assertEqual(result, RESULT_OK) self.assertAlmostEqual(flatSurfaceArea, surfaceArea, delta=1.0E-3)
def create_fields_transformations(coordinates: Field, rotation_angles=None, scale_value=1.0, translation_offsets=None): """ Create constant fields for rotation, scale and translation containing the supplied values, plus the transformed coordinates applying them in the supplied order. :param coordinates: The coordinate field to scale, 3 components. :param rotation_angles: List of euler angles, length = number of components. See create_field_euler_angles_rotation_matrix. :param scale_value: Scalar to multiply all components of coordinates. :param translation_offsets: List of offsets, length = number of components. :return: 4 fields: transformedCoordinates, rotation, scale, translation """ if rotation_angles is None: rotation_angles = [0.0, 0.0, 0.0] if translation_offsets is None: translation_offsets = [0.0, 0.0, 0.0] components_count = coordinates.getNumberOfComponents() assert (components_count == 3) and (len(rotation_angles) == components_count) and isinstance(scale_value, float) \ and (len(translation_offsets) == components_count), "createTransformationFields. Invalid arguments" fieldmodule = coordinates.getFieldmodule() with ChangeManager(fieldmodule): # scale, translate and rotate model, in that order rotation = fieldmodule.createFieldConstant(rotation_angles) scale = fieldmodule.createFieldConstant(scale_value) translation = fieldmodule.createFieldConstant(translation_offsets) rotation_matrix = create_field_euler_angles_rotation_matrix( fieldmodule, rotation) rotated_coordinates = fieldmodule.createFieldMatrixMultiply( components_count, rotation_matrix, coordinates) transformed_coordinates = rotated_coordinates * scale + translation assert transformed_coordinates.isValid() return transformed_coordinates, rotation, scale, translation
def generateMesh(cls, region, options): """ Generate base or refined mesh. Some classes may override to a simpler version just generating the base mesh. :param region: Zinc region to create mesh in. Must be empty. :param options: Dict containing options. See getDefaultOptions(). :return: list of AnnotationGroup for mesh. """ fieldmodule = region.getFieldmodule() with ChangeManager(fieldmodule): if options.get('Refine'): baseRegion = region.createRegion() annotationGroups = cls.generateBaseMesh(baseRegion, options) meshrefinement = MeshRefinement(baseRegion, region, annotationGroups) cls.refineMesh(meshrefinement, options) annotationGroups = meshrefinement.getAnnotationGroups() else: annotationGroups = cls.generateBaseMesh(region, options) fieldmodule.defineAllFaces() oldAnnotationGroups = copy.copy(annotationGroups) for annotationGroup in annotationGroups: annotationGroup.addSubelements() cls.defineFaceAnnotations(region, options, annotationGroups) for annotation in annotationGroups: if annotation not in oldAnnotationGroups: annotationGroup.addSubelements() return annotationGroups
def run(self, modelFileNameStem=None): """ Perform align and scale. :param modelFileNameStem: Optional name stem of intermediate output file to write. """ modelCoordinates = self._fitter.getModelCoordinatesField() assert modelCoordinates, "Align: Missing model coordinates" if self._alignGroups or self._alignMarkers: self._doAutoAlign() fieldmodule = self._fitter._fieldmodule with ChangeManager(fieldmodule): # rotate, scale and translate model modelCoordinatesTransformed = createFieldsTransformations( modelCoordinates, self._rotation, self._scale, self._translation)[0] fieldassignment = self._fitter._modelCoordinatesField.createFieldassignment( modelCoordinatesTransformed) result = fieldassignment.assign() assert result in [RESULT_OK, RESULT_WARNING_PART_DONE ], "Align: Failed to transform model" self._fitter.updateModelReferenceCoordinates() del fieldassignment del modelCoordinatesTransformed self._fitter.calculateDataProjections(self) if modelFileNameStem: self._fitter.writeModel(modelFileNameStem + "_align.exf") self.setHasRun(True)
def create_scene_selection_group( scene: Scene, subelementHandlingMode=FieldGroup.SUBELEMENT_HANDLING_MODE_FULL): """ Create empty, unmanaged scene selection group of standard name. Should have already called get_selection_group with None returned. Can discover orphaned group of that name. :param scene: Zinc Scene to create selection for. :param subelementHandlingMode: Mode controlling how faces, lines and nodes are automatically added or removed with higher dimensional elements. Defaults to on/full. :return: Selection group for scene. """ region = scene.getRegion() fieldmodule = region.getFieldmodule() with ChangeManager(fieldmodule): selection_group = fieldmodule.findFieldByName(selection_group_name) if selection_group.isValid(): selection_group = selection_group.castGroup() if selection_group.isValid(): selection_group.clear() selection_group.setManaged(False) if not selection_group.isValid(): selection_group = fieldmodule.createFieldGroup() selection_group.setName(selection_group_name) selection_group.setSubelementHandlingMode(subelementHandlingMode) scene.setSelectionField(selection_group) return selection_group
def createFieldsTransformations(coordinates: Field, rotation_angles=None, scale_value=1.0, \ translation_offsets=None, translation_scale_factor=1.0): """ Create constant fields for rotation, scale and translation containing the supplied values, plus the transformed coordinates applying them in the supplied order. :param coordinates: The coordinate field to scale, 3 components. :param rotation_angles: List of euler angles, length = number of components. See create_field_euler_angles_rotation_matrix. :param scale_value: Scalar to multiply all components of coordinates. :param translation_offsets: List of offsets, length = number of components. :param translation_scale_factor: Scaling to multiply translation by so it's magnitude can remain close to other parameters for rotation (radians) and scale (assumed close to unit). :return: 4 fields: transformedCoordinates, rotation, scale, translation """ if rotation_angles is None: rotation_angles = [0.0, 0.0, 0.0] if translation_offsets is None: translation_offsets = [0.0, 0.0, 0.0] components_count = coordinates.getNumberOfComponents() assert (components_count == 3) and (len(rotation_angles) == components_count) and isinstance(scale_value, float) \ and (len(translation_offsets) == components_count), "createFieldsTransformations. Invalid arguments" fieldmodule = coordinates.getFieldmodule() with ChangeManager(fieldmodule): # Rotate, scale, and translate model, in that order rotation = fieldmodule.createFieldConstant(rotation_angles) scale = fieldmodule.createFieldConstant(scale_value) translation = fieldmodule.createFieldConstant(translation_offsets) rotation_matrix = create_field_euler_angles_rotation_matrix( fieldmodule, rotation) rotated_coordinates = fieldmodule.createFieldMatrixMultiply( components_count, rotation_matrix, coordinates) transformed_coordinates = rotated_coordinates*scale + (translation if (translation_scale_factor == 1.0) else \ translation*fieldmodule.createFieldConstant([ translation_scale_factor ]*components_count)) assert transformed_coordinates.isValid() return transformed_coordinates, rotation, scale, translation
def _initGraphicsModules(self): context = self._fitter.getContext() self._materialmodule = context.getMaterialmodule() with ChangeManager(self._materialmodule): self._materialmodule.defineStandardMaterials() solid_blue = self._materialmodule.createMaterial() solid_blue.setName("solid_blue") solid_blue.setManaged(True) solid_blue.setAttributeReal3(Material.ATTRIBUTE_AMBIENT, [0.0, 0.2, 0.6]) solid_blue.setAttributeReal3(Material.ATTRIBUTE_DIFFUSE, [0.0, 0.7, 1.0]) solid_blue.setAttributeReal3(Material.ATTRIBUTE_EMISSION, [0.0, 0.0, 0.0]) solid_blue.setAttributeReal3(Material.ATTRIBUTE_SPECULAR, [0.1, 0.1, 0.1]) solid_blue.setAttributeReal(Material.ATTRIBUTE_SHININESS, 0.2) trans_blue = self._materialmodule.createMaterial() trans_blue.setName("trans_blue") trans_blue.setManaged(True) trans_blue.setAttributeReal3(Material.ATTRIBUTE_AMBIENT, [0.0, 0.2, 0.6]) trans_blue.setAttributeReal3(Material.ATTRIBUTE_DIFFUSE, [0.0, 0.7, 1.0]) trans_blue.setAttributeReal3(Material.ATTRIBUTE_EMISSION, [0.0, 0.0, 0.0]) trans_blue.setAttributeReal3(Material.ATTRIBUTE_SPECULAR, [0.1, 0.1, 0.1]) trans_blue.setAttributeReal(Material.ATTRIBUTE_ALPHA, 0.3) trans_blue.setAttributeReal(Material.ATTRIBUTE_SHININESS, 0.2) glyphmodule = context.getGlyphmodule() glyphmodule.defineStandardGlyphs() tessellationmodule = context.getTessellationmodule() defaultTessellation = tessellationmodule.getDefaultTessellation() defaultTessellation.setRefinementFactors([12])
def setSelectHighlightGroup(self, group: FieldGroup): """ Select and highlight objects in the group. :param group: FieldGroup to select, or None to clear selection. """ fieldmodule = self.getFieldmodule() with ChangeManager(fieldmodule): scene = self.getScene() # can't use SUBELEMENT_HANDLING_MODE_FULL as some groups have been tweaked to omit some faces selectionGroup = get_scene_selection_group( scene, subelementHandlingMode=FieldGroup.SUBELEMENT_HANDLING_MODE_NONE ) if group: if selectionGroup: selectionGroup.clear() else: selectionGroup = create_scene_selection_group( scene, subelementHandlingMode=FieldGroup. SUBELEMENT_HANDLING_MODE_NONE) group_add_group_elements(selectionGroup, group, highest_dimension_only=False) for fieldDomainType in (Field.DOMAIN_TYPE_NODES, Field.DOMAIN_TYPE_DATAPOINTS): group_add_group_nodes( selectionGroup, group, fieldmodule.findNodesetByFieldDomainType( fieldDomainType)) else: if selectionGroup: selectionGroup.clear() scene.setSelectionField(Field())
def setName(self, name): ''' Client must ensure name is unique for all annotation groups. First tries to rename zinc group field; if that fails, it won't rename group as the name is already in use. :return: True on success, otherwise False ''' if self._name == name: return True fieldmodule = self._group.getFieldmodule() # use ChangeManager so multiple name changes are atomic with ChangeManager(fieldmodule): if RESULT_OK == self._group.setName(name): # workaround for zinc issue: must rename subelement groups for dimension in range(3, 0, -1): mesh = fieldmodule.findMeshByDimension(dimension) elementGroup = self._group.getFieldElementGroup(mesh) if elementGroup.isValid(): elementGroup.setName(name + '.' + mesh.getName()) nodes = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) nodeGroup = self._group.getFieldNodeGroup(nodes) if nodeGroup.isValid(): nodeGroup.setName(name + '.' + nodes.getName()) self._name = name if self._isMarker: # assign marker name to be same as this group's name. This needs to be maintained markerName = getAnnotationMarkerNameField(fieldmodule) fieldcache = fieldmodule.createFieldcache() markerNode = self.getNodesetGroup( nodes).createNodeiterator().next() fieldcache.setNode(markerNode) markerName.assignString(fieldcache, self._name) return True return False
def create_field_fibres(fieldmodule: Fieldmodule, name="fibres", components_count=3, managed=False)\ -> FieldFiniteElement: """ Finds or creates a finite element fibre field. New field has component names: "fibre angle", "imbrication angle", "sheet angle". New field is not managed by default. :param fieldmodule: Zinc fieldmodule to find or create field in. :param name: Name of field to find or create. :param components_count: Number of components of field, from 1 to 3. :param managed: Managed state of field if created here. :return: Zinc FieldFiniteElement """ assert 1 <= components_count <= 3 with ChangeManager(fieldmodule): fibres = create_field_finite_element(fieldmodule, name, components_count, component_names=[ "fibre angle", "imbrication angle", "sheet angle" ], managed=managed) fibres.setCoordinateSystemType(Field.COORDINATE_SYSTEM_TYPE_FIBRE) return fibres
def applyTransformation(self): ''' If rotation, scale or transformation are set, transform node coordinates. Only call after generate(). ''' assert self._region fieldmodule = self._region.getFieldmodule() coordinates = fieldmodule.findFieldByName('coordinates').castFiniteElement() if not coordinates.isValid(): print('Warning: ScaffoldPackage.applyTransformation: Missing coordinates field') return with ChangeManager(fieldmodule): componentsCount = coordinates.getNumberOfComponents() if componentsCount < 3: # pad with zeros coordinates = fieldmodule.createFieldConcatenate([ coordinates ] + [ fieldmodule.createFieldConstant([ 0.0 ]*(3 - componentsCount)) ]) newCoordinates = coordinates # apply scale first so variable scaling in x, y, z doesn't interplay with rotation if not all((v == 1.0) for v in self._scale): #print("applyTransformation: apply scale", self._scale) newCoordinates = newCoordinates*fieldmodule.createFieldConstant(self._scale) if not all((v == 0.0) for v in self._rotation): #print("applyTransformation: apply rotation", self._rotation) newCoordinates = fieldmodule.createFieldMatrixMultiply(3, createFieldEulerAnglesRotationMatrix(fieldmodule, fieldmodule.createFieldConstant([ deg*math.pi/180.0 for deg in self._rotation ])), newCoordinates) if not all((v == 0.0) for v in self._translation): #print("applyTransformation: apply translation", self._translation) newCoordinates = newCoordinates + fieldmodule.createFieldConstant(self._translation) # be sure to delete temporary fields and fieldassignment to reduce messages if newCoordinates is not coordinates: fieldassignment = coordinates.createFieldassignment(newCoordinates) fieldassignment.assign() del fieldassignment del newCoordinates del coordinates
def generateZincModel(self, region, nextNodeIdentifier=1, nextElementIdentifier=1): ''' Generate Zinc nodes and elements in region to represent tree. :return: Final nextNodeIdentifier, nextElementIdentifier. ''' self._fieldmodule = region.getFieldmodule() self._nodes = self._fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) self._mesh1d = self._fieldmodule.findMeshByDimension(1) self._cubicHermiteBasis = self._fieldmodule.createElementbasis( 1, Elementbasis.FUNCTION_TYPE_CUBIC_HERMITE) self._linearBasis = self._fieldmodule.createElementbasis( 1, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE) self._nodetemplates = { } # indexed by (d1VersionsCount, rVersionsCount) self._elementtemplates = {} # indexed by start (d1Version, rVersion) with ChangeManager(self._fieldmodule): self._coordinates = findOrCreateFieldCoordinates(self._fieldmodule) self._radius = findOrCreateFieldFiniteElement(self._fieldmodule, "radius", components_count=1, managed=True) self._fieldcache = self._fieldmodule.createFieldcache() parentNode = None self._generateZincModelTree(self._rootNode, parentNode, nextNodeIdentifier, nextElementIdentifier) return nextNodeIdentifier, nextElementIdentifier
def mesh_destroy_elements_and_nodes_by_identifiers(mesh, element_identifiers): ''' Deletes elements and related nodes using element identifiers. :param element_identifiers: Element identifiers for elements to be deleted. ''' fm = mesh.getFieldmodule() nodes = fm.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) with ChangeManager(fm): # put the elements in a group and use subelement handling to get nodes in use by it destroyGroup = fm.createFieldGroup() destroyGroup.setSubelementHandlingMode( FieldGroup.SUBELEMENT_HANDLING_MODE_FULL) destroyElementGroup = destroyGroup.createFieldElementGroup(mesh) destroyMesh = destroyElementGroup.getMeshGroup() for elementIdentifier in element_identifiers: element = mesh.findElementByIdentifier(elementIdentifier) destroyMesh.addElement(element) if destroyMesh.getSize() > 0: destroyNodeGroup = destroyGroup.getFieldNodeGroup(nodes) destroyNodes = destroyNodeGroup.getNodesetGroup() # must destroy elements first as Zinc won't destroy nodes that are in use mesh.destroyElementsConditional(destroyElementGroup) nodes.destroyNodesConditional(destroyNodeGroup) # clean up group so no external code hears is notified of its existence del destroyNodes del destroyNodeGroup del destroyMesh del destroyElementGroup del destroyGroup return
def setName(self, name): ''' Client must ensure name is unique for all annotation groups. First tries to rename zinc group field; if that fails, it won't rename group as the name is already in use. :return: True on success, otherwise False ''' fieldmodule = self._group.getFieldmodule() # use ChangeManager so multiple name changes are atomic with ChangeManager(fieldmodule): if RESULT_OK == self._group.setName(name): # workaround for zinc issue: must rename subelement groups for dimension in range(3, 0, -1): mesh = fieldmodule.findMeshByDimension(dimension) elementGroup = self._group.getFieldElementGroup(mesh) if elementGroup.isValid(): elementGroup.setName(name + '.' + mesh.getName()) nodes = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) nodeGroup = self._group.getFieldNodeGroup(nodes) if nodeGroup.isValid(): nodeGroup.setName(name + '.' + nodes.getName()) self._name = name return True return False
def _markerFromDict(self, nodeIdentifier, markerDct: dict): """ Define a new marker point node with nodeIdentifier and fields defined as in markerDct. Warn but do nothing if node with that identifier exists. :param nodeIdentifier: :param markerDct: A dict mapping names of fields to values, e.g. { "heart coordinates": [11.5, 16.2, 7.6], "marker_location": [5, [0.0, 0.0, 1.0]] } """ assert not self._isMarker fieldmodule = self._group.getFieldmodule() nodes = fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_NODES) node = nodes.findNodeByIdentifier(nodeIdentifier) if node.isValid(): print("Error: Read annotation group " + self._name + ". "\ "Marker point node " + str(nodeIdentifier) + " already exists", file=sys.stderr) return mesh = get_highest_dimension_mesh(fieldmodule) if not mesh: print("Error: Read annotation group " + self._name + ". Marker cannot be made for empty mesh", file=sys.stderr) return with ChangeManager(fieldmodule): materialCoordinatesField = None materialCoordinates = None element = None xi = None for key in markerDct.keys(): if key != "marker_location": fieldName = key materialCoordinatesField = fieldmodule.findFieldByName( fieldName).castFiniteElement() materialCoordinates = markerDct[fieldName] if materialCoordinatesField.isValid() and isinstance( materialCoordinates, list): break print("Error: Read annotation group " + self._name + ". " \ "Invalid marker material coordinates field " + fieldName + " or value.", file=sys.stderr) materialCoordinatesField = None materialCoordinates = None break if not materialCoordinatesField: element_xi = markerDct.get("marker_location") if not element_xi: print("Error: Read annotation group " + self._name + ". " \ "Marker missing marker_location entry", file=sys.stderr) return elementIdentifier, xi = element_xi element = mesh.findElementByIdentifier(elementIdentifier) if not element.isValid(): print("Error: Read annotation group " + self._name + ". " \ "Marker element " + str(elementIdentifier) + " not found", file=sys.stderr) return self.createMarkerNode(nodeIdentifier, materialCoordinatesField, materialCoordinates, element, xi)
def selectNode(self, node): nodeset = node.getNodeset() fieldmodule = nodeset.getFieldmodule() with ChangeManager(fieldmodule): selectionGroup = self.getOrCreateSelectionGroup() selectionGroup.clear() nodegroup = selectionGroup.getFieldNodeGroup(nodeset) if not nodegroup.isValid(): nodegroup = selectionGroup.createFieldNodeGroup(nodeset) nodesetGroup = nodegroup.getNodesetGroup() result = nodesetGroup.addNode(node)
def addData(self): index = self.index(-1, 0) row_count = len(self._material_names) self.beginInsertRows(index, row_count, row_count) mm = self._material_module with ChangeManager(mm): material = mm.createMaterial() name = material.getName() material.setManaged(True) self._material_names.append(name) self.endInsertRows()
def _updateMarkerCoordinatesField(self): if self._modelCoordinatesField and self._markerLocationField: with ChangeManager(self._fieldmodule): markerPrefix = self._markerGroup.getName() self._markerCoordinatesField = self._fieldmodule.createFieldEmbedded( self._modelCoordinatesField, self._markerLocationField) self._markerCoordinatesField.setName( getUniqueFieldName(self._fieldmodule, markerPrefix + "_coordinates")) else: self._markerCoordinatesField = None
def nodeset_group_add_identifier_ranges(nodeset_group, identifier_ranges): ''' Add nodes with the supplied identifier ranges to nodeset_group. :param nodeset_group: Zinc NodesetGroup to modify. ''' nodeset = nodeset_group.getMasterNodeset() fieldmodule = nodeset.getFieldmodule() with ChangeManager(fieldmodule): for identifier_range in identifier_ranges: for identifier in range(identifier_range[0], identifier_range[1] + 1): node = nodeset.findNodeByIdentifier(identifier) nodeset_group.addNode(node)
def _setupPreviewScene(self, sceneviewer): with ChangeManager(sceneviewer): sceneviewer.setScene(self._previewZincScene) sceneviewer.setZoomRate(0) sceneviewer.setTumbleRate(0) sceneviewer.setTranslationRate(0) sceneviewer.setLookatParametersNonSkew([3.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 1.0]) sceneviewer.setViewAngle(0.679673818908244) sceneviewer.setNearClippingPlane(2.4) sceneviewer.setFarClippingPlane(3.0)
def _defineDataProjectionFields(self): self._dataProjectionLocationFields = [] self._dataProjectionCoordinatesFields = [] self._dataProjectionDeltaFields = [] self._dataProjectionErrorFields = [] self._dataProjectionNodeGroupFields = [] self._dataProjectionNodesetGroups = [] with ChangeManager(self._fieldmodule): datapoints = self._fieldmodule.findNodesetByFieldDomainType( Field.DOMAIN_TYPE_DATAPOINTS) for d in range(2): mesh = self._mesh[d] dataProjectionLocation = findOrCreateFieldStoredMeshLocation( self._fieldmodule, mesh, name="data_projection_location_" + mesh.getName(), managed=False) self._dataProjectionLocationFields.append( dataProjectionLocation) dataProjectionCoordinates = self._fieldmodule.createFieldEmbedded( self._modelCoordinatesField, dataProjectionLocation) dataProjectionCoordinates.setName( getUniqueFieldName( self._fieldmodule, "data_projection_coordinates_" + mesh.getName())) self._dataProjectionCoordinatesFields.append( dataProjectionCoordinates) dataProjectionDelta = dataProjectionCoordinates - self._dataCoordinatesField dataProjectionDelta.setName( getUniqueFieldName( self._fieldmodule, "data_projection_delta_" + mesh.getName())) self._dataProjectionDeltaFields.append(dataProjectionDelta) dataProjectionError = self._fieldmodule.createFieldMagnitude( dataProjectionDelta) dataProjectionError.setName( getUniqueFieldName( self._fieldmodule, "data_projection_error_" + mesh.getName())) self._dataProjectionErrorFields.append(dataProjectionError) field = self._fieldmodule.createFieldNodeGroup(datapoints) field.setName( getUniqueFieldName( self._fieldmodule, "data_projection_group_" + mesh.getName())) self._dataProjectionNodeGroupFields.append(field) self._dataProjectionNodesetGroups.append( field.getNodesetGroup()) self._dataProjectionDirectionField = findOrCreateFieldFiniteElement( self._fieldmodule, "data_projection_direction", components_count=3, component_names=["x", "y", "z"])