def fill_vtk_unstructured_grid_results(model: pyNastranH5, vtk_ugrid: vtk.vtkUnstructuredGrid, eids: np.ndarray) -> None: point_data = vtk_ugrid.GetPointData() cell_data = vtk_ugrid.GetCellData() for i, res in model.results.items(): if res.location == 'node': names, resultsi = res.get_results() for name, result in zip(names, resultsi): print(name) #name = 'cat' result.SetName(name) point_data.AddArray(result) # remove #point_data.SetActiveVectors(name) #point_data.SetVectors(result) elif res.location == 'element': res.eids = eids names, resultsi = res.get_results() for name, result in zip(names, resultsi): print(name) #name = 'cat' result.SetName(name) cell_data.AddArray(result) #cell_data.SetScalars(result) else: raise NotImplementedError(res)
def add_user_geometry(alt_grid: vtk.vtkUnstructuredGrid, geom_grid: vtk.vtkUnstructuredGrid, xyz: np.ndarray, nid_map: Dict[int, int], nnodes: int, bars: np.ndarray, tris: np.ndarray, quads: np.ndarray, nelements: int, nbars: int, ntris: int, nquads: int) -> vtk.vtkPoints: """helper method for ``_add_user_geometry``""" # set points points = numpy_to_vtk_points(xyz, dtype='<f') if nelements > 0: for i in range(nnodes): elem = vtk.vtkVertex() elem.GetPointIds().SetId(0, i) alt_grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) geom_grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) else: for i in range(nnodes): elem = vtk.vtkVertex() elem.GetPointIds().SetId(0, i) alt_grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) if nbars: for i, bar in enumerate(bars[:, 1:]): g1 = nid_map[bar[0]] g2 = nid_map[bar[1]] elem = vtk.vtkLine() elem.GetPointIds().SetId(0, g1) elem.GetPointIds().SetId(1, g2) geom_grid.InsertNextCell(elem.GetCellType(), elem.GetPointIds()) if ntris: for i, tri in enumerate(tris[:, 1:]): g1 = nid_map[tri[0]] g2 = nid_map[tri[1]] g3 = nid_map[tri[2]] elem = vtk.vtkTriangle() elem.GetPointIds().SetId(0, g1) elem.GetPointIds().SetId(1, g2) elem.GetPointIds().SetId(2, g3) geom_grid.InsertNextCell(5, elem.GetPointIds()) if nquads: for i, quad in enumerate(quads[:, 1:]): g1 = nid_map[quad[0]] g2 = nid_map[quad[1]] g3 = nid_map[quad[2]] g4 = nid_map[quad[3]] elem = vtk.vtkQuad() point_ids = elem.GetPointIds() point_ids.SetId(0, g1) point_ids.SetId(1, g2) point_ids.SetId(2, g3) point_ids.SetId(3, g4) geom_grid.InsertNextCell(9, elem.GetPointIds()) alt_grid.SetPoints(points) if nelements > 0: geom_grid.SetPoints(points) return points
def _add_nastran_lines_to_grid(alt_grid: vtk.vtkUnstructuredGrid, nid_map: Dict[int, int], name: str, lines, model: BDF, nid_to_pid_map=None): """used to create MPC lines""" nlines = lines.shape[0] #nids = np.unique(lines) #nnodes = len(nids) nnodes = nlines * 2 if nnodes == 0: return #self.gui.follower_nodes[name] = lines.ravel() points = vtk.vtkPoints() points.SetNumberOfPoints(nnodes) j = 0 etype = 3 # vtkLine #nid_map = self.gui.nid_map #alt_grid = self.gui.alt_grids[name] for nid1, nid2 in lines: try: unused_i1 = nid_map[nid1] except KeyError: model.log.warning('nid=%s does not exist' % nid1) continue try: unused_i2 = nid_map[nid2] except KeyError: model.log.warning('nid=%s does not exist' % nid2) continue if nid1 not in model.nodes or nid2 not in model.nodes: continue node = model.nodes[nid1] point = node.get_position() points.InsertPoint(j, *point) node = model.nodes[nid2] point = node.get_position() points.InsertPoint(j + 1, *point) elem = vtk.vtkLine() point_ids = elem.GetPointIds() point_ids.SetId(0, j) point_ids.SetId(1, j + 1) alt_grid.InsertNextCell(etype, point_ids) j += 2 alt_grid.SetPoints(points)
def create_highlighted_actors( gui, grid: vtk.vtkUnstructuredGrid, all_nodes=None, nodes=None, set_node_scalars=True, all_elements=None, elements=None, set_element_scalars=True, add_actors: bool = False) -> List[vtk.vtkLODActor]: """creates nodes & element highlighted objects""" actors = [] nnodes = 0 nelements = 0 if nodes is not None: nnodes = len(nodes) assert len(all_nodes) >= nnodes if elements is not None: nelements = len(elements) assert len(all_elements) >= nelements assert nnodes + nelements > 0 if nnodes: point_ids = np.searchsorted(all_nodes, nodes) output_data = grid.GetPoints().GetData() points_array = vtk_to_numpy(output_data) # yeah! point_array2 = points_array[point_ids, :] points2 = numpy_to_vtk_points(point_array2) ugrid = create_unstructured_point_grid(points2, nnodes) if set_node_scalars: point_ids_array = numpy_to_vtk(nodes) ugrid.GetPointData().SetScalars(point_ids_array) actor = create_highlighted_actor(gui, ugrid, representation='points', add_actor=add_actors) actors.append(actor) if nelements: cell_ids = np.searchsorted(all_elements, elements) selection_node = create_vtk_selection_node_by_cell_ids(cell_ids) ugrid = extract_selection_node_from_grid_to_ugrid(grid, selection_node) if set_element_scalars: element_ids_array = numpy_to_vtk(elements) ugrid.GetPointData().SetScalars(None) ugrid.GetCellData().SetScalars(element_ids_array) actor = create_highlighted_actor(gui, ugrid, representation='wire', add_actor=add_actors) actors.append(actor) return actors
def add_lines(grid: vtk.vtkUnstructuredGrid, nids, eids_lines: np.ndarray, nid_offset: int) -> int: """adds line elements to the vtkUnstructuredGrid""" nelements = 0 if eids_lines is not None: nelements = eids_lines.shape[0] eids = eids_lines[:, 0] elem_nids = eids_lines[:, 1:] #inids = np.searchsorted(nids, elem_nids) node_ids = elem_nids + nid_offset for unused_eid, node_idsi in zip(eids, node_ids): elem = vtkLine() point_ids = elem.GetPointIds() point_ids.SetId(0, node_idsi[0]) point_ids.SetId(1, node_idsi[1]) grid.InsertNextCell(3, point_ids) return nelements
def _elements_to_vtk(vtk_ugrid: vtk.vtkUnstructuredGrid, etype_nids: np.ndarray, cell_offsets_array: np.ndarray, cell_types_array: np.ndarray): # Create the array of cells nelements = len(cell_offsets_array) cells_id_type = numpy_to_vtkIdTypeArray(etype_nids, deep=1) vtk_cells = vtk.vtkCellArray() vtk_cells.SetCells(nelements, cells_id_type) # Cell types deep = False vtk_cell_types = numpy_to_vtk( cell_types_array, deep=deep, array_type=vtk.vtkUnsignedCharArray().GetDataType()) vtk_cell_offsets = numpy_to_vtk(cell_offsets_array, deep=deep, array_type=vtk.VTK_ID_TYPE) #grid = vtk.vtkUnstructuredGrid() vtk_ugrid.SetCells(vtk_cell_types, vtk_cell_offsets, vtk_cells)
def add_quads(grid: vtk.vtkUnstructuredGrid, nids, eids_quads: np.ndarray, nid_offset: int) -> int: """adds quad elements to the vtkUnstructuredGrid""" nelements = 0 if eids_quads is not None: nelements = eids_quads.shape[0] eids = eids_quads[:, 0] elem_nids = eids_quads[:, 1:] #inids = np.searchsorted(nids, elem_nids) #print(inids) node_ids = elem_nids + nid_offset #node_ids = inids # + nid_offset + 1 for unused_eid, node_idsi in zip(eids, node_ids): elem = vtkQuad() point_ids = elem.GetPointIds() point_ids.SetId(0, node_idsi[0]) point_ids.SetId(1, node_idsi[1]) point_ids.SetId(2, node_idsi[2]) point_ids.SetId(3, node_idsi[3]) grid.InsertNextCell(9, point_ids) return nelements
def create_filtered_point_ugrid(ugrid: vtk.vtkUnstructuredGrid, nids, nids2) -> vtk.vtkUnstructuredGrid: """ We need to filter the nodes that were filtered by the numpy setdiff1d, so we don't show extra points """ #unused_pointsu = ugrid.GetPoints() output_data = ugrid.GetPoints().GetData() points_array = vtk_to_numpy(output_data) # yeah! isort_nids = np.argsort(nids) nids = nids[isort_nids] inids = np.searchsorted(nids, nids2) points_array_sorted = points_array[isort_nids, :] point_array2 = points_array_sorted[inids, :] points2 = numpy_to_vtk_points(point_array2) npoints = len(nids2) ugrid = create_unstructured_point_grid(points2, npoints) return ugrid
def add_hexas(grid: vtk.vtkUnstructuredGrid, nids, eids_hexas: np.ndarray, nid_offset: int) -> int: """adds hex elements to the vtkUnstructuredGrid""" nelements = 0 if eids_hexas is not None: nelements = eids_hexas.shape[0] eids = eids_hexas[:, 0] elem_nids = eids_hexas[:, 1:] #inids = np.searchsorted(nids, elem_nids) node_ids = elem_nids + nid_offset for unused_eid, node_idsi in zip(eids, node_ids): elem = vtkHexahedron() point_ids = elem.GetPointIds() point_ids.SetId(0, node_idsi[0]) point_ids.SetId(1, node_idsi[1]) point_ids.SetId(2, node_idsi[2]) point_ids.SetId(3, node_idsi[3]) point_ids.SetId(4, node_idsi[4]) point_ids.SetId(5, node_idsi[5]) point_ids.SetId(6, node_idsi[6]) point_ids.SetId(7, node_idsi[7]) grid.InsertNextCell(elem.GetCellType(), point_ids) return nelements
def create_vtk_cells_of_constant_element_types(grid: vtk.vtkUnstructuredGrid, elements_list, etypes_list): """ Adding constant type elements is overly complicated enough as in ``create_vtk_cells_of_constant_element_type``. Now we extend this to multiple element types. grid : vtk.vtkUnstructuredGrid() the unstructured grid elements_list : List[elements, ...] elements : (nelements, nnodes_per_element) int ndarray the elements to add etypes_list : List[etype, ...] etype : int the VTK flag as defined in ``create_vtk_cells_of_constant_element_type`` """ if isinstance(etypes_list, list) and len(etypes_list) == 1: create_vtk_cells_of_constant_element_type(grid, elements_list[0], etypes_list[0]) return dtype = get_numpy_idtype_for_vtk() cell_offsets_list2 = [] cell_types_list2 = [] elements_list2 = [] nelements = 0 noffsets = 0 for element, etype in zip(elements_list, etypes_list): nelement, nnodes_per_element = element.shape nnodesp1 = nnodes_per_element + 1 # TODO: was 4; for a tri??? cell_offset = np.arange(0, nelement, dtype='int32') * nnodesp1 + noffsets noffset = nelement * nnodesp1 cell_type = np.ones(nelement, dtype='int32') * etype assert len(cell_offset) == nelement nnodesp1 = nnodes_per_element + 1 element_vtk = np.zeros((nelement, nnodesp1), dtype=dtype) element_vtk[:, 0] = nnodes_per_element # 3 nodes/tri element_vtk[:, 1:] = element cell_offsets_list2.append(cell_offset) cell_types_list2.append(cell_type) elements_list2.append(element_vtk.ravel()) nelements += nelement noffsets += noffset cell_types_array = np.hstack(cell_types_list2) cell_offsets_array = np.hstack(cell_offsets_list2) elements_array = np.hstack(elements_list2) # Create the array of cells cells_id_type = numpy_to_vtkIdTypeArray(elements_array.ravel(), deep=1) vtk_cells = vtk.vtkCellArray() vtk_cells.SetCells(nelements, cells_id_type) # Cell types vtk_cell_types = numpy_to_vtk( cell_types_array, deep=0, array_type=vtk.vtkUnsignedCharArray().GetDataType()) vtk_cell_offsets = numpy_to_vtk(cell_offsets_array, deep=0, array_type=vtkConstants.VTK_ID_TYPE) grid.SetCells(vtk_cell_types, vtk_cell_offsets, vtk_cells)
def get_inside_point_ids( gui, ugrid: vtk.vtkUnstructuredGrid, ugrid_flipped: vtk.vtkUnstructuredGrid, model_name: str, representation: str = 'points' ) -> Tuple[vtk.vtkUnstructuredGrid, List[int]]: """ The points that are returned from the frustum, despite being defined as inside are not all inside. The cells are correct though. If you determine the cells outside the volume and the points associated with that, and boolean the two, you can find the points that are actually inside. In other words, ``points`` corresponds to the points inside the volume and barely outside. ``point_ids_flipped`` corresponds to the points entirely outside the volume. Parameters ========== ugrid : vtk.vtkUnstructuredGrid() the "inside" grid ugrid_flipped : vtk.vtkUnstructuredGrid() the outside grid Returns ======= ugrid : vtk.vtkUnstructuredGrid() an updated grid that has the correct points nids : (n, ) int ndarray the node_ids """ nids = None points = ugrid.GetPointData() if points is None: return ugrid, nids ids = points.GetArray('Ids') if ids is None: return ugrid, nids # all points associated with the correctly selected cells are returned # but we get extra points for the cells that are inside and out point_ids = vtk_to_numpy(ids) nids = gui.get_node_ids(model_name, point_ids) # these are the points outside the box/frustum (and also include the bad point) points_flipped = ugrid_flipped.GetPointData() ids_flipped = points_flipped.GetArray('Ids') point_ids_flipped = vtk_to_numpy(ids_flipped) nids_flipped = gui.get_node_ids(model_name, point_ids_flipped) #nids = gui.gui.get_reverse_node_ids(model_name, point_ids_flipped) # setA - setB nids2 = np.setdiff1d(nids, nids_flipped, assume_unique=True) #narrays = points.GetNumberOfArrays() #for iarray in range(narrays): #name = points.GetArrayName(iarray) #print('iarray=%s name=%r' % (iarray, name)) #------------------ if representation == 'points': # we need to filter the nodes that were filtered by the # numpy setdiff1d, so we don't show extra points ugrid = create_filtered_point_ugrid(ugrid, nids, nids2) nids = nids2 return ugrid, nids
def create_vtk_cells_of_constant_element_type(grid: vtk.vtkUnstructuredGrid, elements: np.ndarray, etype: int) -> None: """ Adding constant type elements is overly complicated. Parameters ---------- grid : vtk.vtkUnstructuredGrid() the unstructured grid elements : (nelements, nnodes_per_element) int ndarray the elements to add etype : int VTK cell type Notes ----- The documentation in this method is triangle-specific as it was developed for a tri mesh. It's more general than that though. """ nelements, nnodes_per_element = elements.shape _check_shape(etype, elements, nnodes_per_element) # We were careful about how we defined the arrays, so the data # is contiguous when we ravel it. Otherwise, you need to # deepcopy the arrays (deep=1). However, numpy_to_vtk isn't so # good, so we could use np.copy, which is better, but it's # ultimately unnecessary. #nodes = numpy_to_vtk(elements, deep=0, array_type=vtk.VTK_ID_TYPE) # (nnodes_per_element + 1) # TODO: was 4; for a tri...didn't seem to crash??? # int8: [-128 to 127] # int32: [-2_147_483_648 to 2_147_483_647] # 2.1 billion # int64: [-9223372036854775808 to 9223372036854775807] cell_offsets = np.arange(0, nelements, dtype='int32') * (nnodes_per_element + 1) assert len(cell_offsets) == nelements # Create the array of cells vtk_cells = vtk.vtkCellArray() dtype = get_numpy_idtype_for_vtk() elements_vtk = np.zeros((nelements, nnodes_per_element + 1), dtype=dtype) elements_vtk[:, 0] = nnodes_per_element # 3 nodes/tri element elements_vtk[:, 1:] = elements cells_id_type = numpy_to_vtkIdTypeArray(elements_vtk.ravel(), deep=1) vtk_cells.SetCells(nelements, cells_id_type) # Cell types # 5 = vtkTriangle().GetCellType() cell_types = np.full(nelements, etype, dtype='int8') vtk_cell_types = numpy_to_vtk( cell_types, deep=0, array_type=vtk.vtkUnsignedCharArray().GetDataType()) vtk_cell_offsets = numpy_to_vtk(cell_offsets, deep=0, array_type=vtkConstants.VTK_ID_TYPE) grid.SetCells(vtk_cell_types, vtk_cell_offsets, vtk_cells)
def fill_vtk_unstructured_grid(geom_model: BDF, vtk_ugrid: vtk.vtkUnstructuredGrid, add_property=True, add_material=True): #cell_type_point = 1 # vtk.vtkVertex().GetCellType() #cell_type_line = 3 # vtk.vtkLine().GetCellType() #cell_type_tri3 = 5 #cell_type_tri6 = 22 #cell_type_quad4 = 9 #cell_type_quad8 = 23 #cell_type_tetra4 = 10 #cell_type_tetra10 = 24 #cell_type_pyram5 = 14 # vtk.vtkPyramid().GetCellType() #cell_type_pyram13 = 27 # vtk.vtkQuadraticPyramid().GetCellType() #cell_type_hexa8 = 12 #cell_type_hexa20 = 25 #cell_type_penta6 = 13 #cell_type_penta15 = 26 #nodes, node_ids, nid_map, idtype = _load_nodes(geom_model) nodes = geom_model._nodes node_ids = geom_model._node_ids #nid_map = geom_model._nid_map idtype = geom_model._idtype vtk_points = numpy_to_vtk_points(nodes, points=None, dtype='<f', deep=1) vtk_ugrid.SetPoints(vtk_points) etype_nids, cell_offsets_array, cell_types_array, eids, pids = _load_elements( geom_model, node_ids, idtype=idtype) nelements = len(eids) # build the grid _elements_to_vtk(vtk_ugrid, etype_nids, cell_offsets_array, cell_types_array) # fill the grid with results #point_data = vtk_ugrid.GetPointData() cell_data = vtk_ugrid.GetCellData() eid_array = numpy_to_vtk(eids, deep=0, array_type=None) eid_array.SetName('ElementID') cell_data.AddArray(eid_array) if add_property: pid_array = numpy_to_vtk(pids, deep=0, array_type=None) pid_array.SetName('PropertyID') cell_data.AddArray(pid_array) #if add_property: #pid_array = numpy_to_vtk(pids, deep=0, array_type=None) #pid_array.SetName('PropertyID') #cell_data.AddArray(pid_array) if add_material: psolid_mids = np.full(nelements, -1, dtype='int64') pshell_mids = np.full((nelements, 4), -1, dtype='int64') thickness = np.full(nelements, np.nan, dtype='float32') upids = np.unique(pids) is_solid = False is_shell = False for pid in upids: ipid = np.where(pid == pids) prop = geom_model.properties[pid] if prop.type == 'PSOLID': is_solid = True psolid_mids[ipid] = prop.mid elif prop.type == 'PSHELL': is_shell = True thickness[ipid] = prop.t for imid, mid in enumerate([prop.mid1, prop.mid2, prop.mid3, prop.mid4]): if mid is None: continue pshell_mids[ipid, imid] = mid else: geom_model.log.warning(f'skipping:\n{prop}') if is_solid: mid_array = numpy_to_vtk(psolid_mids, deep=0, array_type=None) mid_array.SetName('Solid Material') cell_data.AddArray(mid_array) if is_shell: thickness_array = numpy_to_vtk(thickness, deep=0, array_type=None) thickness_array.SetName('Shell Thickness') cell_data.AddArray(thickness_array) for imid in range(4): mids = pshell_mids[:, imid] shell_mid_array = numpy_to_vtk(mids, deep=0, array_type=None) thickness_array.SetName(f'Shell Material {imid+1}') cell_data.AddArray(shell_mid_array) #print(point_data) return eids