Source code for cellcomplex.property_topomesh.visualization.vtk_actor_topomesh

# Version: $Id$
#
#

# Commentary:
#
#

# Change Log:
#
#

# Code:

import numpy as np

import matplotlib.pyplot as plt
import matplotlib as mpl

import vtk
from vtk.util.numpy_support import numpy_to_vtk, vtk_to_numpy, get_vtk_array_type

from cellcomplex.property_topomesh.analysis import compute_topomesh_property
from cellcomplex.utils import array_dict


from cellcomplex.property_topomesh.visualization.vtk_tools import vtk_combine_polydatas, face_scalar_vertex_property_polydata
from cellcomplex.property_topomesh.visualization.vtk_tools import vtk_lookuptable_from_mpl_cmap, vtk_glyph_polydata
from cellcomplex.property_topomesh.visualization.vtk_tools import vertex_scalar_property_polydata, edge_scalar_property_polydata, face_scalar_property_polydata, vertex_vector_property_polydata, vertex_tensor_property_polydata

from time import time as current_time
import logging

[docs]class VtkActorTopomesh(): def __init__(self, topomesh=None, degree=None, property_name=None, property_degree=None, **kwargs): """ Parameters ---------- topomesh degree property_name kwargs """ self.topomesh = topomesh self._degree = degree self._property_name = property_name self._property_degree = property_degree if property_degree is not None else self._degree self._modified = True self.tensor_glyph = kwargs.get('tensor_glyph', 'ellipsoid') self.vector_glyph = kwargs.get('vector_glyph','arrow') self.point_glyph= kwargs.get('point_glyph','sphere') self.line_glyph = kwargs.get('line_glyph','line') self.glyph_scale = kwargs.get('glyph_scale',1.) self.polydata = None self.display_polydata = None self.actor = None self.scalar_mode = None @property def degree(self): return self._degree @degree.setter def degree(self, value): logging.info("Setting degree :"+str(self._degree)+" --> "+str(value)) if self._degree != value: self._modified = True self._degree = value if self._property_degree is None: self._property_degree = self.degree @property def property_name(self): return self._property_name @property_name.setter def property_name(self, value): logging.info("Setting property name :"+str(self._property_name)+" --> "+str(value)) if self.property_name != value: if self.topomesh is not None: if self.topomesh.has_wisp_property(self._property_name, self.degree, is_computed=True): property_data = self.topomesh.wisp_property(self._property_name, self.degree).values() ndim = property_data.ndim else: ndim = 1 if self.topomesh.has_wisp_property(value, self.degree, is_computed=True): property_data = self.topomesh.wisp_property(value, self.degree).values() new_ndim = property_data.ndim else: new_ndim = 1 self._modified = ndim != new_ndim self._property_name = value
[docs] def set_topomesh(self, topomesh, degree, property_name=None): self.topomesh = topomesh self._degree = degree if self._property_degree is None: self._property_degree = degree self.property_name = property_name
[docs] def update_polydata(self): logging.info("--> Update polydata (modified="+str(self._modified)+")") self.display_polydata = None self._modified = True if self.degree == 3: positions = self.topomesh.wisp_property("barycenter", 0) compute_topomesh_property(self.topomesh,"oriented_vertices",2) if self.topomesh.has_wisp_property(self.property_name,3,is_computed=True): cell_property = self.topomesh.wisp_property(self.property_name,3) else: cell_property = array_dict(dict(zip(self.topomesh.wisps(3),np.ones(self.topomesh.nb_wisps(3))))) if cell_property.values().ndim == 1: cell_polydatas = [] for cid in self.topomesh.wisps(3): face_vertices = self.topomesh.wisp_property("oriented_vertices", 2).values(list(self.topomesh.borders(3,cid))) property_data = np.array([cell_property[cid] for fid in self.topomesh.borders(3,cid)]) cell_polydata = face_scalar_property_polydata(positions, face_vertices, property_data) wisp_ids = numpy_to_vtk(np.array([cid for fid in self.topomesh.borders(3,cid)]), deep=True, array_type=vtk.VTK_LONG) wisp_ids.SetName("WispId") cell_polydata.GetCellData().AddArray(wisp_ids) cell_polydatas += [cell_polydata] self.polydata = vtk_combine_polydatas(cell_polydatas) self.scalar_mode = 'cell_data' else: compute_topomesh_property(self.topomesh,"barycenter",3) positions = self.topomesh.wisp_property("barycenter", 3) property_data = cell_property.values(list(self.topomesh.wisps(3))) wisp_ids = numpy_to_vtk(np.array([cid for cid in self.topomesh.wisps(3)]), deep=True, array_type=vtk.VTK_LONG) wisp_ids.SetName("WispId") if property_data.ndim == 3: if property_data.shape[1] == 3 and property_data.shape[2] == 3: self.polydata = vertex_tensor_property_polydata(positions, property_data, self.polydata) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata,tensor_glyph=self.tensor_glyph, glyph_scale=self.glyph_scale) elif property_data.ndim == 2: self.polydata = vertex_vector_property_polydata(positions, property_data, self.polydata, update_polydata=self._modified) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata,vector_glyph=self.vector_glyph, glyph_scale=self.glyph_scale) wisp_ids.SetName("WispId") if self.scalar_mode == 'point_data': self.polydata.GetPointData().AddArray(wisp_ids) elif self.scalar_mode == 'cell_data': self.polydata.GetCellData().AddArray(wisp_ids) elif self.degree == 2: wisp_ids = numpy_to_vtk(np.array([fid for fid in self.topomesh.wisps(2)]), deep=True, array_type=vtk.VTK_LONG) wisp_ids.SetName("WispId") positions = self.topomesh.wisp_property("barycenter", 0) compute_topomesh_property(self.topomesh,"oriented_vertices",2) face_vertices = self.topomesh.wisp_property("oriented_vertices", 2).values() if self._property_degree == self.degree: if self.topomesh.has_wisp_property(self.property_name,2,is_computed=True): property_data = self.topomesh.wisp_property(self.property_name,2).values() else: # property_data = np.ones(self.topomesh.nb_wisps(2)) property_data = np.array(list(self.topomesh.wisps(2))) if property_data.ndim == 3: compute_topomesh_property(self.topomesh, 'barycenter', 2) positions = self.topomesh.wisp_property("barycenter", 2) if property_data.shape[1] == 3 and property_data.shape[2] == 3: self.polydata = vertex_tensor_property_polydata(positions, property_data, self.polydata) self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata, tensor_glyph=self.tensor_glyph, glyph_scale=self.glyph_scale) self.scalar_mode = 'point_data' elif property_data.ndim == 2: print("VERTEX VECTOR PROP") compute_topomesh_property(self.topomesh, 'barycenter', 2) positions = self.topomesh.wisp_property("barycenter", 2) self.polydata = vertex_vector_property_polydata(positions, property_data, self.polydata, update_polydata=self._modified) self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata, vector_glyph=self.vector_glyph, glyph_scale=self.glyph_scale) self.scalar_mode = 'point_data' elif property_data.ndim == 1: self.polydata = face_scalar_property_polydata(positions, face_vertices, property_data, self.polydata, update_polydata=self._modified) self.polydata.GetCellData().AddArray(wisp_ids) self.scalar_mode = 'cell_data' else: if self.topomesh.has_wisp_property(self.property_name,self._property_degree,is_computed=True): property_data = self.topomesh.wisp_property(self.property_name,self._property_degree).values() if property_data.ndim == 1: self.polydata = face_scalar_vertex_property_polydata(positions, face_vertices, property_data, self.polydata, update_polydata=self._modified) self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata, vector_glyph=self.vector_glyph, glyph_scale=self.glyph_scale) self.scalar_mode = 'point_data' elif self.degree == 1: wisp_ids = numpy_to_vtk(np.array([fid for fid in self.topomesh.wisps(1)]), deep=True, array_type=vtk.VTK_LONG) positions = self.topomesh.wisp_property("barycenter", 0) compute_topomesh_property(self.topomesh,"vertices",1) edge_vertices = self.topomesh.wisp_property("vertices", 1).values(list(self.topomesh.wisps(1))) if self.topomesh.has_wisp_property(self.property_name, 1, is_computed=True): property_data = self.topomesh.wisp_property(self.property_name,1).values(list(self.topomesh.wisps(1))) else: property_data = np.ones(self.topomesh.nb_wisps(1)) self.polydata = edge_scalar_property_polydata(positions, edge_vertices, property_data, self.polydata, line_glyph=self.line_glyph, glyph_scale=self.glyph_scale) self.scalar_mode = 'point_data' wisp_ids.SetName("WispId") if self.scalar_mode == 'point_data': self.polydata.GetPointData().AddArray(wisp_ids) elif self.scalar_mode == 'cell_data': self.polydata.GetCellData().AddArray(wisp_ids) elif self.degree == 0: wisp_ids = numpy_to_vtk(np.array([pid for pid in self.topomesh.wisps(0)]), deep=True, array_type=vtk.VTK_LONG) wisp_ids.SetName("WispId") positions = array_dict(dict(zip(self.topomesh.wisps(0),self.topomesh.wisp_property("barycenter", 0).values(list(self.topomesh.wisps(0)))))) if self.topomesh.has_wisp_property(self.property_name,0,is_computed=True): property_data = self.topomesh.wisp_property(self.property_name,0).values(positions.keys()) print(len(property_data)) if property_data.ndim == 3: if property_data.shape[1] == 3 and property_data.shape[2] == 3: self.polydata = vertex_tensor_property_polydata(positions, property_data) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata,tensor_glyph=self.tensor_glyph,glyph_scale=self.glyph_scale) elif property_data.ndim == 2: self.polydata = vertex_vector_property_polydata(positions, property_data) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata,vector_glyph=self.vector_glyph, glyph_scale=self.glyph_scale) elif property_data.ndim == 1: self.polydata = vertex_scalar_property_polydata(positions, property_data) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata, point_glyph=self.point_glyph, glyph_scale=self.glyph_scale) else: property_data = np.ones(self.topomesh.nb_wisps(0)) self.polydata = vertex_scalar_property_polydata(positions, property_data) self.scalar_mode = 'point_data' self.polydata.GetPointData().AddArray(wisp_ids) self.display_polydata = vtk_glyph_polydata(self.polydata, point_glyph=self.point_glyph, glyph_scale=self.glyph_scale)
[docs] def update_actor(self, colormap='viridis', value_range=None, opacity=1, linewidth=1): print("Value range:",value_range) if value_range is None: if self.polydata.GetCellData().GetNumberOfArrays()>0: scalars = vtk_to_numpy(self.polydata.GetCellData().GetArray(0)) value_range = (np.nanmin(scalars),np.nanmax(scalars)) elif self.polydata.GetPointData().GetNumberOfArrays()>0: scalars = vtk_to_numpy(self.polydata.GetPointData().GetArray(0)) value_range = (np.nanmin(scalars),np.nanmax(scalars)) else: value_range = (0,1) print("Value range:",value_range) logging.info("--> Value range : "+str(value_range)) lut = vtk_lookuptable_from_mpl_cmap(colormap, value_range) mapper = vtk.vtkPolyDataMapper() if self.scalar_mode == 'cell_data': mapper.SetScalarModeToUseCellData() elif self.scalar_mode == 'point_data': mapper.SetScalarModeToUsePointData() if self.display_polydata is not None: mapper.SetInputData(self.display_polydata) else: mapper.SetInputData(self.polydata) mapper.SetLookupTable(lut) if self.actor is None: self.actor = vtk.vtkActor() self.actor.SetMapper(mapper) self.actor.GetProperty().SetOpacity(opacity) self.actor.GetProperty().SetLineWidth(linewidth)
[docs] def update(self, colormap='viridis',value_range=None, opacity=1, linewidth=1): self.update_polydata() self.update_actor(colormap=colormap, value_range=value_range, opacity=opacity, linewidth=linewidth) self._modified = False
[docs] def clean(self): self.polydata.Initialize()