def __add_label(self, cellid): # Add dataset: from mayavi.modules.labels import Labels indices = self.__vlsvReader.get_cell_indices(cellid) self.labels = Labels() self.labels.number_of_labels = 1 self.labels.mask.filter.random_mode = False self.labels.mask.filter.offset = int( indices[0] + (self.__cells[0] + 1) * indices[1] + (self.__cells[0] + 1) * (self.__cells[1] + 1) * (indices[2] + 1)) module_manager = self.__module_manager() # Add the label / marker: self.__engine.add_filter(self.labels, module_manager)
def do(self): ############################################################ # Imports. from mayavi.modules.api import ScalarCutPlane from mayavi.modules.labels import Labels from mayavi.sources.vtk_xml_file_reader import VTKXMLFileReader ############################################################ # Create a new scene and set up the visualization. s = self.new_scene() script = mayavi = self.script # Read a VTK (old style) data file. r = VTKXMLFileReader() r.initialize(get_example_data('fire_ug.vtu')) script.add_source(r) # Create the filters. cp = ScalarCutPlane() script.add_module(cp) l = Labels(object=cp) script.add_module(l) s.scene.isometric_view() GUI.process_events() self.check(saved=False) ############################################################ # Test if saving a visualization and restoring it works. # Save visualization. f = BytesIO() f.name = abspath('test.mv2') # We simulate a file. script.save_visualization(f) f.seek(0) # Remove existing scene. engine = script.engine engine.close_scene(s) # Load visualization script.load_visualization(f) s = engine.current_scene s.scene.isometric_view() # Seems to be needed for the test to pass. :( Just flushes the # pipeline. s.children[0].pipeline_changed = True GUI.process_events() # Check. # Now do the check. self.check(saved=True) ############################################################ # Test if the Mayavi2 visualization can be deep-copied. # Pop the source object. source = s.children.pop() # Add it back to see if that works without error. s.children.append(source) GUI.process_events() # Now do the check. s.scene.isometric_view() self.check(saved=True) # Now deepcopy the source and replace the existing one with # the copy. This basically simulates cutting/copying the # object from the UI via the right-click menu on the tree # view, and pasting the copy back. source1 = copy.deepcopy(source) s.children[0] = source1 GUI.process_events() # Now do the check. s.scene.isometric_view() self.check(saved=True) GUI.process_events()
def __init__(self): global LIST_AMF_OBJECTS, AMF_TREE, AMF_ROOT, DICT_MATERIAL self.engine1.start() amfFileToParse = str(Path(AMF_FOLDER) / AMF_FILE) try: AMF_TREE = ET.parse(amfFileToParse) except OSError as e: print("Error:", e) exit() AMF_ROOT = AMF_TREE.getroot() objectsDict = {} # By default, we add a material with ID 0 that corresponds to the case where no material is assigned to a volume # Obviously, this choice imposes to use Material ID in the library with an ID greater than 0 TODO: Check if it's the case once we know how to manage the material library noMaterialID = "0" DICT_MATERIAL[noMaterialID] = "No Material" # Start by handling the material in the AMF file to build the material library for tMaterial in AMF_ROOT.iter('material'): # Iterate through all the material in the scenario materialID = tMaterial.attrib['id'] for tName in tMaterial.iter('metadata'): materialName = tName.text # Get the material Name DICT_MATERIAL[ materialID] = materialName # Add the material to the material dictionary # Handle the case where no Material exists in the AMF file - For example NISTGaithersburg.xml # Here is just a placeholder for the default material library # In this implementation, we will create a fake material made of 100 materials (completely arbitrary choice) if len(DICT_MATERIAL) == 1: # No Material defined nbMaterial = 100 for i in range(1, nbMaterial + 1): DICT_MATERIAL[str(i)] = "FakematerialName" + str(i) for tObject in AMF_ROOT.iter('object'): # Iterate through all the objects in the AMF File coordinateX = [] coordinateY = [] coordinateZ = [] DONOTADD = False xmlObjectID = tObject.attrib['id'] # Get the Object ID for tName in tObject.iter('metadata'): xmlObjectName = tName.text # Get the object Name # There is a bug in the way geodata scenario are generated # It includes twice every object so we handle that here # TODO: Fix the geodata scenarios generation and update the code accordingly if xmlObjectName in objectsDict: # If an object with the same name has already been parsed, flag it DONOTADD = True else: # The object does not exist in the object dictionnary, just add it to the objects dictionary objectsDict[xmlObjectName] = True # Get the X, Y, Z coordinates corresponding to an object for tcoordinatesX in tObject.iter('x'): # Get x coordinates coordinateX.append(float(tcoordinatesX.text)) for tcoordinatesY in tObject.iter('y'): # Get y coordinates coordinateY.append(float(tcoordinatesY.text)) for tcoordinatesZ in tObject.iter('z'): # Get z coordinates coordinateZ.append(float(tcoordinatesZ.text)) for tVolume in tObject.iter('volume'): # Iterate over the volume, i.e., the triangles connections and material # Please note that an object can be defined with more than one volume try: materialId = tVolume.attrib[ 'materialid'] # Get the material ID associated to the triangles connections except KeyError: # It's possible that a volume is not having any material assigned - Handle it # print("Warning: Object :", xmlObjectName, " is not having any material associated to it") TODO Commented for now materialId = None v1 = [] # First vertex v2 = [] # Second vertex v3 = [] # Third vertex for tTriangles in tVolume.iter('triangle'): # Iterate over the triangles of a volume for tFirstPoint in tTriangles.iter('v1'): # Get First vertex v1.append(int(tFirstPoint.text)) for tSecondPoint in tTriangles.iter('v2'): # Get Second vertex v2.append(int(tSecondPoint.text)) for tThirdPoint in tTriangles.iter('v3'): # Get Third vertex v3.append(int(tThirdPoint.text)) # Get the final triangles coordinates by connecting the vertices to their associated coordinates finalX = [] finalY = [] finalZ = [] for index in range(len(v1)): finalX.append([ coordinateX[v1[index]], coordinateX[v2[index]], coordinateX[v3[index]] ]) finalY.append([ coordinateY[v1[index]], coordinateY[v2[index]], coordinateY[v3[index]] ]) finalZ.append([ coordinateZ[v1[index]], coordinateZ[v2[index]], coordinateZ[v3[index]] ]) # Create the triangles connections triangles = [(i * 3, (i * 3) + 1, (i * 3) + 2) for i in range(0, len(finalX))] # Manage automatically the color of each volume depending on the material ID # The colormap is having 0:nbMaterial+1 possible values # We define a scalar that we associate with the volume if materialId == None: # Assign the No Material ID in case no material was assigned to a volume materialId = noMaterialID color = np.ones(np.asarray(finalX).shape) * int(materialId) if DONOTADD == False: # Add the volume to the visualization only it it was not added previously # Create the volume to visualize volume = mlab.triangular_mesh( finalX, finalY, finalZ, triangles, scalars=color, vmin=0, vmax=len(DICT_MATERIAL) - 1, colormap='Spectral', representation='wireframe', name="volume:" + xmlObjectName, figure=self.sceneView1.mayavi_scene, reset_zoom=False) volume.module_manager.scalar_lut_manager.lut.number_of_colors = 256 # Create a label for each volume labels = Labels() vtk_data_source = volume self.engine1.add_filter(labels, vtk_data_source) labels.mapper.label_format = (xmlObjectName) labels.number_of_labels = 1 labels.mask.filter.random_mode = False # Store the objects currentObject = ObjectGeometry(xmlObjectID, xmlObjectName, volume, materialId) LIST_AMF_OBJECTS.append(currentObject) # Present the Material ID library ordered in the GUI materialIDSorted = sorted(list(DICT_MATERIAL.keys()), key=int) self.GUI_MATERIAL_LIBRARY = materialIDSorted HasTraits.__init__(self)