Source code for cellcomplex.property_topomesh.utils.triangular_mesh_tools

# -*- coding: utf-8 -*-
# -*- python -*-
#
#       PropertyTopomesh
#
#       Copyright 2014-2016 INRIA - CIRAD - INRA
#
#       File author(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>
#
#       File contributor(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>
#
#       Distributed under the Cecill-C License.
#       See accompanying file LICENSE.txt or copy at
#           http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
#       OpenaleaLab Website : http://virtualplants.github.io/
#
###############################################################################


from time import time

import numpy as np
from scipy.cluster.vq import vq

try:
    import vtk
except ImportError:
    print("VTK needs to be installed to use these functionalities")
    raise

from copy import  deepcopy

from cellcomplex.utils import array_dict

from cellcomplex.property_topomesh import PropertyTopomesh
from cellcomplex.triangular_mesh import TriangularMesh

from cellcomplex.property_topomesh.analysis import compute_topomesh_property, is_triangular
from cellcomplex.property_topomesh.extraction import star_interface_topomesh

triangle_edge_list  = np.array([[1, 2],[0, 2],[0, 1]])

[docs]def SetInput(obj, _input): if vtk.VTK_MAJOR_VERSION <= 5: obj.SetInput(_input) else: obj.SetInputData(_input)
[docs]def topomesh_to_triangular_mesh(input_topomesh, degree=3, wids=None, coef=1.0, mesh_center=None, epidermis=False, cell_edges=False, property_name=None, property_degree=None): topomesh = deepcopy(input_topomesh) if not is_triangular(topomesh) and (degree > 1): topomesh = star_interface_topomesh(topomesh) start_time = time() print("--> Creating triangular mesh") triangular_mesh = TriangularMesh() if property_name is not None: if property_degree is None: property_degree = degree try: if not topomesh.has_wisp_property(property_name, degree=property_degree, is_computed=True): compute_topomesh_property(topomesh, property_name, degree=property_degree) assert len(topomesh.wisp_property(property_name, property_degree).keys()) == topomesh.nb_wisps(property_degree) except: property_name = None if mesh_center is None: mesh_center = topomesh.wisp_property('barycenter', 0).values().mean(axis=0) else: mesh_center = np.array(mesh_center) considered_start_time = time() if wids is None: wids = list(topomesh.wisps(degree)) considered_elements = {} for d in range(4): if d == degree: considered_elements[d] = list(wids) elif d < degree: considered_elements[d] = list(np.unique(np.concatenate([list(topomesh.borders(degree, w, degree - d)) for w in wids]))) else: considered_elements[d] = list(np.unique(np.concatenate([list(topomesh.regions(degree, w, d - degree)) for w in wids]))) if degree > 1: compute_topomesh_property(topomesh, 'vertices', degree=2) compute_topomesh_property(topomesh, 'faces', degree=3) compute_topomesh_property(topomesh, 'cells', degree=2) cell_triangles = np.concatenate(topomesh.wisp_property('faces', 3).values(considered_elements[3])).astype(int) # cell_triangles = [t for t in cell_triangles if t in considered_elements[2]] considered_end_time = time() print(" --> Filtering out mesh elements [", considered_end_time - considered_start_time, "s]") if degree == 3: if property_name is not None: property_data = topomesh.wisp_property(property_name, property_degree).values(considered_elements[3]) else: property_data = np.array(considered_elements[3]) vertices_positions = [] triangle_vertices = [] triangle_topomesh_cells = [] vertices_topomesh_vertices = [] # triangle_topomesh_triangles = [] if property_data.ndim == 1 or property_degree < 3: for c in considered_elements[3]: if len(list(topomesh.borders(3, c, 3))) > 0: cell_center = topomesh.wisp_property('barycenter', 0).values(list(topomesh.borders(3, c, 3))).mean(axis=0) cell_vertices_position = cell_center + coef * (topomesh.wisp_property('barycenter', 0).values(list(topomesh.borders(3, c, 3))) - cell_center) - mesh_center cell_vertices_index = array_dict(len(vertices_positions) + np.arange(len(list(topomesh.borders(3, c, 3)))), list(topomesh.borders(3, c, 3))) vertices_positions += list(cell_vertices_position) vertices_topomesh_vertices += list(topomesh.borders(3, c, 3)) triangle_vertices += list(cell_vertices_index.values(topomesh.wisp_property('vertices', 2).values(topomesh.wisp_property('faces', 3)[c]))) triangle_topomesh_cells += list(c * np.ones_like(topomesh.wisp_property('faces', 3)[c])) # triangle_topomesh_triangles += topomesh.wisp_property('faces',3)[c] print(len(cell_triangles), "Cell triangles") print(len(triangle_vertices), "Triangle vertices") vertices_positions = array_dict(vertices_positions, np.arange(len(vertices_positions))) vertices_topomesh_vertices = array_dict(vertices_topomesh_vertices, np.arange(len(vertices_positions))) if epidermis: compute_topomesh_property(topomesh, 'epidermis', 2) epidermis_triangles = topomesh.wisp_property('epidermis', 2).values(cell_triangles) triangle_vertices = array_dict(np.array(triangle_vertices)[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) triangle_topomesh_cells = array_dict(np.array(triangle_topomesh_cells)[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) triangle_topomesh_triangles = array_dict(cell_triangles[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) else: triangle_vertices = array_dict(triangle_vertices, np.arange(len(cell_triangles))) triangle_topomesh_cells = array_dict(triangle_topomesh_cells, np.arange(len(cell_triangles))) triangle_topomesh_triangles = array_dict(cell_triangles, np.arange(len(cell_triangles))) edge_topomesh_edges = {} triangular_mesh.points = vertices_positions.to_dict() triangular_mesh.triangles = triangle_vertices.to_dict() if property_name is not None: if property_degree == 2: triangle_topomesh_triangle_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(triangle_topomesh_triangles.values()), triangle_topomesh_triangles.keys()) triangular_mesh.triangle_data = triangle_topomesh_triangle_property.to_dict() elif property_degree == 0: vertex_topomesh_vertex_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(vertices_topomesh_vertices.values()), vertices_topomesh_vertices.keys()) triangular_mesh.point_data = vertex_topomesh_vertex_property.to_dict() elif property_degree == 3: triangle_topomesh_cell_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(triangle_topomesh_cells.values()), triangle_topomesh_cells.keys()) triangular_mesh.triangle_data = triangle_topomesh_cell_property.to_dict() else: triangular_mesh.triangle_data = triangle_topomesh_cells.to_dict() else: for c in considered_elements[3]: if len(list(topomesh.borders(3, c, 3))) > 0: cell_center = topomesh.wisp_property('barycenter', 0).values(list(topomesh.borders(3, c, 3))).mean(axis=0) vertices_positions += [cell_center] vertices_positions = array_dict(vertices_positions, np.array([c for c in topomesh.wisps(3) if len(list(topomesh.borders(3, c, 3))) > 0])) vertices_topomesh_vertices = {} edge_topomesh_edges = {} triangle_topomesh_triangles = {} triangle_topomesh_cells = {} cell_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(vertices_positions.keys()), vertices_positions.keys()) triangular_mesh.points = vertices_positions.to_dict() triangular_mesh.point_data = cell_property triangular_mesh.triangles = {} elif degree == 2: vertices_positions = [] triangle_vertices = [] vertices_topomesh_vertices = [] for t in cell_triangles: triangle_center = topomesh.wisp_property('barycenter', 0).values(list(topomesh.borders(2, t, 2))).mean(axis=0) triangle_vertices_position = triangle_center + coef * (topomesh.wisp_property('barycenter', 0).values(list(topomesh.borders(2, t, 2))) - triangle_center) - mesh_center triangle_vertices_index = array_dict(len(vertices_positions) + np.arange(3), list(topomesh.borders(2, t, 2))) vertices_positions += list(triangle_vertices_position) vertices_topomesh_vertices += list(topomesh.borders(2, t, 2)) triangle_vertices += list([triangle_vertices_index.values(topomesh.wisp_property('vertices', 2)[t])]) vertices_positions = array_dict(vertices_positions, np.arange(len(vertices_positions))) vertices_topomesh_vertices = array_dict(vertices_topomesh_vertices, np.arange(len(vertices_positions))) triangle_topomesh_cells = np.concatenate([c * np.ones_like([t for t in topomesh.wisp_property('faces', 3)[c] if t in considered_elements[2]]) for c in considered_elements[3]]).astype(int) if epidermis: compute_topomesh_property(topomesh, 'epidermis', 2) epidermis_triangles = topomesh.wisp_property('epidermis', 2).values(cell_triangles) triangle_vertices = array_dict(np.array(triangle_vertices)[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) triangle_topomesh_cells = array_dict(np.array(triangle_topomesh_cells)[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) triangle_topomesh_triangles = array_dict(cell_triangles[epidermis_triangles], np.arange(len(cell_triangles[epidermis_triangles]))) else: triangle_vertices = array_dict(triangle_vertices, np.arange(len(cell_triangles))) triangle_topomesh_cells = array_dict(triangle_topomesh_cells, np.arange(len(cell_triangles))) triangle_topomesh_triangles = array_dict(cell_triangles, np.arange(len(cell_triangles))) edge_topomesh_edges = {} triangular_mesh.points = vertices_positions.to_dict() triangular_mesh.triangles = triangle_vertices.to_dict() if property_name is not None: if property_degree == 2: triangle_topomesh_triangle_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(triangle_topomesh_triangles.values()), triangle_topomesh_triangles.keys()) triangular_mesh.triangle_data = triangle_topomesh_triangle_property.to_dict() elif property_degree == 0: vertex_topomesh_vertex_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(vertices_topomesh_vertices.values()), vertices_topomesh_vertices.keys()) triangular_mesh.point_data = vertex_topomesh_vertex_property.to_dict() elif property_degree == 3: triangle_topomesh_cell_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(triangle_topomesh_cells.values()), triangle_topomesh_cells.keys()) triangular_mesh.triangle_data = triangle_topomesh_cell_property.to_dict() else: triangular_mesh.triangle_data = triangle_topomesh_cells.to_dict() elif degree == 1: compute_topomesh_property(topomesh, 'vertices', degree=1) vertices_positions = array_dict(topomesh.wisp_property('barycenter', 0).values(considered_elements[0]), considered_elements[0]) edge_vertices = array_dict(topomesh.wisp_property('vertices', 1).values(considered_elements[1]), considered_elements[1]) triangular_mesh.points = vertices_positions.to_dict() triangular_mesh.edges = edge_vertices.to_dict() if property_name is not None: if property_degree == 1: edge_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(considered_elements[1]), considered_elements[1]) triangular_mesh.edge_data = edge_property.to_dict() triangle_topomesh_cells = {} triangle_topomesh_triangles = {} edge_topomesh_edges = dict(list(zip(triangular_mesh.edges.keys(), triangular_mesh.edges.keys()))) vertices_topomesh_vertices = {} if cell_edges: compute_topomesh_property(topomesh, 'epidermis', 1) compute_topomesh_property(topomesh, 'cells', 1) edge_n_cells = np.array(list(map(len, topomesh.wisp_property('cells', 1).values()))) edge_is_cell_edge = edge_n_cells > 2 edge_is_cell_edge = edge_is_cell_edge | (edge_n_cells > 1) & (topomesh.wisp_property('epidermis', 1).values()) edge_is_cell_edge = array_dict(edge_is_cell_edge, list(topomesh.wisps(1))) edges_to_remove = [] for eid in triangular_mesh.edges: if not edge_is_cell_edge[eid]: edges_to_remove += [eid] for eid in edges_to_remove: del triangular_mesh.edges[eid] del edge_topomesh_edges[eid] if eid in triangular_mesh.edge_data: del triangular_mesh.edge_data[eid] elif degree == 0: vertices_positions = array_dict(topomesh.wisp_property('barycenter', 0).values(considered_elements[0]), considered_elements[0]) triangular_mesh.points = vertices_positions.to_dict() if property_name is not None: if property_degree == 0: vertex_property = array_dict(topomesh.wisp_property(property_name, property_degree).values(considered_elements[0]), considered_elements[0]) triangular_mesh.point_data = vertex_property.to_dict() triangle_topomesh_cells = {} triangle_topomesh_triangles = {} edge_topomesh_edges = {} vertices_topomesh_vertices = dict(list(zip(triangular_mesh.points.keys(), triangular_mesh.points.keys()))) mesh_element_matching = {} mesh_element_matching[0] = vertices_topomesh_vertices mesh_element_matching[1] = edge_topomesh_edges mesh_element_matching[2] = triangle_topomesh_triangles mesh_element_matching[3] = triangle_topomesh_cells end_time = time() print("<-- Creating triangular mesh [", end_time - start_time, "s]") return triangular_mesh, mesh_element_matching
[docs]def vtk_polydata_to_triangular_mesh(polydata): mesh = TriangularMesh() start_time = time() print("--> Creating vertices") polydata_point_data = None if polydata.GetPointData().GetNumberOfComponents() > 0: polydata_point_data = polydata.GetPointData().GetArray(0) for v in range(polydata.GetPoints().GetNumberOfPoints()): mesh.points[v] = polydata.GetPoints().GetPoint(v) if polydata_point_data is not None: mesh.point_data[v] = polydata_point_data.GetTuple(v) end_time = time() print("<-- Creating vertices [",end_time-start_time,"s]") start_time = time() print("--> Creating triangles") triangles = {} triangle_data = {} polydata_cell_data = None if polydata.GetCellData().GetNumberOfComponents() > 0: polydata_cell_data = polydata.GetCellData().GetArray(0) for t in range(polydata.GetNumberOfCells()): mesh.triangles[t] = np.sort([polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)]) if polydata_cell_data is not None: mesh.triangle_data[t] = polydata_cell_data.GetTuple(t) end_time = time() print("<-- Creating triangles [",end_time-start_time,"s]") return mesh
[docs]def vtk_polydata_to_cell_triangular_meshes(polydata): mesh = {} polydata_cell_data = polydata.GetCellData().GetArray(0) triangle_cell_start_time = time() print(" --> Listing triangles") print(" - ", polydata.GetNumberOfCells(), " triangles") # polydata_triangles = np.sort([[polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)] for t in range(polydata.GetNumberOfCells())]) polydata_triangles = np.array([[polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)] for t in range(polydata.GetNumberOfCells())]) triangle_cell_end_time = time() print(" <-- Listing triangles [", triangle_cell_end_time - triangle_cell_start_time, "s]") triangle_cell_start_time = time() print(" --> Listing triangle cells") triangle_cell = np.array([polydata_cell_data.GetTuple(t)[0] for t in range(polydata.GetNumberOfCells())], np.uint16) triangle_cell_end_time = time() print(" <-- Listing triangle cells [", triangle_cell_end_time - triangle_cell_start_time, "s]") start_time = time() print(" --> Creating cell meshes") for c in np.unique(triangle_cell): mesh[c] = TriangularMesh() cell_triangles = np.arange(polydata.GetNumberOfCells())[np.where(triangle_cell == c)] # cell_triangle_points = np.sort([[polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)] for t in cell_triangles]) cell_triangle_points = np.array([[polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)] for t in cell_triangles]) cell_vertices = np.sort(np.unique(cell_triangle_points)) mesh[c].points = array_dict(np.array([polydata.GetPoints().GetPoint(v) for v in cell_vertices]), cell_vertices).to_dict() mesh[c].triangles = array_dict(cell_triangle_points, cell_triangles).to_dict() mesh[c].triangle_data = array_dict(np.ones_like(cell_triangles) * c, cell_triangles).to_dict() end_time = time() print(" <-- Creating cell meshes [", end_time - start_time, "s]") return mesh
[docs]def vtk_polydata_to_topomesh(polydata): topomesh = PropertyTopomesh(3) start_time = time() print("--> Creating vertices") # polydata_points = np.array([polydata.GetPoints().GetPoint(i) for i in range(polydata.GetPoints().GetNumberOfPoints())]) # unique_points = array_unique(polydata_points) # n_points = unique_points.shape[0] # polydata_point_point_matching = (vq(polydata_points,unique_points)[0]) vertex_positions = {} for v in range(polydata.GetPoints().GetNumberOfPoints()): # for v in range(n_points): vertex_positions[v] = polydata.GetPoints().GetPoint(v) # vertex_positions[v] = unique_points[v] topomesh.add_wisp(0, v) end_time = time() print("<-- Creating vertices [", end_time - start_time, "s]") start_time = time() print("--> Creating edges") polydata_triangles = np.sort([[polydata.GetCell(t).GetPointIds().GetId(i) for i in range(3)] for t in range(polydata.GetNumberOfCells())]) # polydata_triangles = np.sort(polydata_point_point_matching[polydata_triangles]) polydata_edges = np.unique(np.concatenate(polydata_triangles[:, triangle_edge_list]), axis=0) for e, edge_vertices in enumerate(polydata_edges): topomesh.add_wisp(1, e) for v in edge_vertices: topomesh.link(1, e, v) end_time = time() print("<-- Creating edges [", end_time - start_time, "s]") start_time = time() print("--> Linking triangle to edges") unique_triangles = np.unique(polydata_triangles, axis=0) n_triangles = unique_triangles.shape[0] polydata_triangle_triangle_matching = (vq(polydata_triangles, unique_triangles)[0]) polydata_triangle_edge_matching = (vq(np.concatenate(unique_triangles[:, triangle_edge_list]), polydata_edges)[0]).reshape((n_triangles, 3)) end_time = time() print("<-- Linking triangle to edges[", end_time - start_time, "s]") start_time = time() print("--> Creating triangles") for t in range(n_triangles): topomesh.add_wisp(2, t) for e in polydata_triangle_edge_matching[t]: topomesh.link(2, t, e) end_time = time() print("<-- Creating triangles [", end_time - start_time, "s]") start_time = time() print("--> Creating cells") polydata_cell_data = polydata.GetCellData().GetArray(0) polydata_cells = np.array(np.unique(np.concatenate([polydata_cell_data.GetTuple(t) for t in range(polydata.GetNumberOfCells())])), np.uint16) for c in polydata_cells: if c != 1: topomesh.add_wisp(3, c) for t in range(polydata.GetNumberOfCells()): for c in polydata_cell_data.GetTuple(t): if c != 1: topomesh.link(3, int(c), polydata_triangle_triangle_matching[t]) end_time = time() print("<-- Creating cells [", end_time - start_time, "s]") topomesh.update_wisp_property('barycenter', 0, vertex_positions) return topomesh
[docs]def topomesh_to_vtk_polydata(topomesh, degree=2, positions=None, topomesh_center=None, coef=1): if positions is None: positions = topomesh.wisp_property('barycenter', 0) if topomesh_center is None: topomesh_center = np.mean(positions.values(), axis=0) # topomesh_center = np.array([0,0,0]) print(topomesh_center) vtk_mesh = vtk.vtkPolyData() vtk_points = vtk.vtkPoints() vtk_edges = vtk.vtkCellArray() vtk_triangles = vtk.vtkCellArray() vtk_cells = vtk.vtkLongArray() start_time = time() print("--> Creating VTK PolyData") if degree == 3: for c in topomesh.wisps(3): cell_points = [] cell_center = np.mean([positions[v] for v in topomesh.borders(3, c, 3)], axis=0) for v in topomesh.borders(3, c, 3): position = cell_center + coef * (positions[v] - cell_center) - topomesh_center position[np.where(np.abs(position) < .001)] = 0. p = vtk_points.InsertNextPoint(position) cell_points.append(p) cell_points = array_dict(cell_points, list(topomesh.borders(3, c, 3))) for t in topomesh.borders(3, c): poly = vtk_triangles.InsertNextCell(3) for v in topomesh.borders(2, t, 2): vtk_triangles.InsertCellPoint(cell_points[v]) vtk_cells.InsertValue(poly, c) elif degree == 2: for t in topomesh.wisps(2): triangle_points = [] triangle_center = np.mean([positions[v] for v in topomesh.borders(2, t, 2)], axis=0) for v in topomesh.borders(2, t, 2): position = triangle_center + coef * (positions[v] - triangle_center) - topomesh_center position[np.where(np.abs(position) < .001)] = 0. p = vtk_points.InsertNextPoint(position) triangle_points.append(p) triangle_points = array_dict(triangle_points, list(topomesh.borders(2, t, 2))) poly = vtk_triangles.InsertNextCell(3) for v in topomesh.borders(2, t, 2): vtk_triangles.InsertCellPoint(triangle_points[v]) vtk_cells.InsertValue(poly, list(topomesh.regions(2, t))[0]) elif degree == 1: points = [] for v in topomesh.wisps(0): position = positions[v] position[np.where(np.abs(position) < .001)] = 0. p = vtk_points.InsertNextPoint(position) points.append(p) points = array_dict(points, list(topomesh.wisps(0))) for e in topomesh.wisps(1): # if topomesh.wisp_property('epidermis',1)[e]: # if True: if len(list(topomesh.regions(1, e))) > 2: c = vtk_edges.InsertNextCell(2) for v in topomesh.borders(1, e): vtk_edges.InsertCellPoint(points[v]) print(" --> Linking Mesh") vtk_mesh.SetPoints(vtk_points) vtk_mesh.SetPolys(vtk_triangles) vtk_mesh.SetLines(vtk_edges) vtk_mesh.GetCellData().SetScalars(vtk_cells) end_time = time() print("<-- Creating VTK PolyData [", end_time - start_time, "s]") return vtk_mesh
[docs]def composed_triangular_mesh(triangular_mesh_dict): start_time = time() print("--> Composing triangular mesh...") mesh = TriangularMesh() triangle_cell_matching = {} mesh_points = np.concatenate([triangular_mesh_dict[c].points.keys() for c in triangular_mesh_dict.keys()]) mesh_point_positions = np.concatenate([triangular_mesh_dict[c].points.values() for c in triangular_mesh_dict.keys()]) mesh.points = dict(list(zip(mesh_points,mesh_point_positions))) mesh_triangles = np.concatenate([triangular_mesh_dict[c].triangles.values() for c in triangular_mesh_dict.keys()]) mesh.triangles = dict(list(zip(np.arange(len(mesh_triangles)),mesh_triangles))) mesh_cells = np.concatenate([c*np.ones_like(triangular_mesh_dict[c].triangles.keys()) for c in triangular_mesh_dict.keys()]) triangle_cell_matching = dict(list(zip(np.arange(len(mesh_triangles)),mesh_cells))) end_time = time() print("<-- Composing triangular mesh [",end_time-start_time,"]") return mesh, triangle_cell_matching