108108 .format (MESH_DATA_TYPE , msg ))
109109
110110
111+
112+
113+ def normalise_mesh_type (mesh_data ):
114+ """Try to support as many of the mesh libraries out there as possible
115+ without having all of those libraries as dependencies.
116+ """
117+
118+ if isinstance (mesh_data , tuple ) and len (mesh_data ) == 2 :
119+ vertices , args = mesh_data
120+ if not isinstance (vertices , np .ndarray ):
121+ raise MESH_DATA_TYPE_EX ("First argument is of invalid type {}" \
122+ .format (type (vertices )))
123+
124+ if vertices .shape [1 :] != (3 ,):
125+ raise MESH_DATA_TYPE_EX ("First argument has invalid shape {}. Should be (..., 3)." \
126+ .format (vertices .shape ))
127+
128+ if not isinstance (args , np .ndarray ):
129+ raise MESH_DATA_TYPE_EX ("Second argument is of invalid type {}" \
130+ .format (type (args )))
131+
132+ if args .shape [1 :] != (3 ,):
133+ raise MESH_DATA_TYPE_EX ("Second argument has invalid shape {}. Should be (n, 3)." \
134+ .format (args .shape ))
135+
136+ if args .dtype != int :
137+ raise MESH_DATA_TYPE_EX ("Second argument must be an int dtype array" )
138+
139+ vectors = vertices [args ]
140+
141+
142+ else :
143+ if isinstance (mesh_data , np .ndarray ):
144+ vectors = mesh_data
145+
146+ elif hasattr (mesh_data , "vectors" ):
147+ vectors = mesh_data .vectors
148+ if vectors .shape [1 :] != (3 , 3 ):
149+ vectors = vectors [:, :3 , :3 ]
150+
151+ else :
152+ raise MESH_DATA_TYPE_EX ("" )
153+
154+ if vectors .shape [1 :] != (3 , 3 ):
155+ raise MESH_DATA_TYPE_EX ("mesh_data is invalid shape {}" .format (vectors .shape ))
156+
157+ return vectors
158+
159+
111160class MeshPlot (ConstructedPlot ):
112161 """Plot an STL (like) surface composed of lots of little triangles. Accepts
113162 mesh types from various 3rd party libraries. This was primarily written for
@@ -117,49 +166,8 @@ class MeshPlot(ConstructedPlot):
117166 def __init__ (self , mesh_data , tri_scalars = None , scalars = None , color = None , opacity = None , fig = "gcf" ):
118167 super ().__init__ (fig )
119168
120- # Try to support as many of the mesh libraries out there as possible
121- # without having all of those libraries as dependencies
122-
123- if isinstance (mesh_data , tuple ) and len (mesh_data ) == 2 :
124- vertices , args = mesh_data
125- if not isinstance (vertices , np .ndarray ):
126- raise MESH_DATA_TYPE_EX ("First argument is of invalid type {}" \
127- .format (type (vertices )))
128-
129- if vertices .shape [1 :] != (3 ,):
130- raise MESH_DATA_TYPE_EX ("First argument has invalid shape {}. Should be (..., 3)." \
131- .format (vertices .shape ))
132-
133- if not isinstance (args , np .ndarray ):
134- raise MESH_DATA_TYPE_EX ("Second argument is of invalid type {}" \
135- .format (type (args )))
136-
137- if args .shape [1 :] != (3 ,):
138- raise MESH_DATA_TYPE_EX ("Second argument has invalid shape {}. Should be (n, 3)." \
139- .format (args .shape ))
140-
141- if args .dtype != int :
142- raise MESH_DATA_TYPE_EX ("Second argument must be an int dtype array" )
143-
144- self .vectors = vertices [args ]
145-
146-
147- else :
148- if isinstance (mesh_data , np .ndarray ):
149- self .vectors = mesh_data
150-
151- elif hasattr (mesh_data , "vectors" ):
152- self .vectors = mesh_data .vectors
153- if self .vectors .shape [1 :] != (3 , 3 ):
154- self .vectors = self .vectors [:, :3 , :3 ]
155-
156- else :
157- raise MESH_DATA_TYPE_EX ("" )
158169
159- if self .vectors .shape [1 :] != (3 , 3 ):
160- raise MESH_DATA_TYPE_EX ("mesh_data is invalid shape {}" .format (self .vectors .shape ))
161-
162- self .vectors = numpy_vtk .contiguous_safe (self .vectors )
170+ self .vectors = numpy_vtk .contiguous_safe (normalise_mesh_type (mesh_data ))
163171
164172 triangles = np .empty ((len (self .vectors ), 4 ), np .int64 )
165173 triangles [:, 0 ] = 3
@@ -239,38 +247,52 @@ def set_scalars(self, scalars, min=None, max=None):
239247 self .mapper .SetScalarRange (min , max )
240248
241249
242-
250+ def mesh_plot_with_edge_scalars ( mesh_data , edge_scalars , centre_scalar = "mean" , opacity = None , fig = "gcf" ):
243251
252+ vectors = normalise_mesh_type (mesh_data )
253+ tri_centres = np .mean (vectors , 1 )
254+
255+ new_vectors = np .empty ((len (vectors ) * 3 , 3 , 3 ), vectors .dtype )
256+ # new_vectors.fill(np.nan)
257+
258+ for i in range (3 ):
259+ for j in range (2 ):
260+ new_vectors [i ::3 , j % 3 ] = vectors [:, (i + j ) % 3 ]
261+
262+ new_vectors [i ::3 , 2 % 3 ] = tri_centres
263+
264+ tri_scalars = edge_scalars .ravel ()
265+ if centre_scalar == "mean" :
266+ centre_scalars = np .mean (edge_scalars , 1 )
267+ else :
268+ centre_scalars = centre_scalar
269+ #
270+ new_scalars = np .empty ((len (tri_scalars ), 3 ), dtype = tri_scalars .dtype )
271+ new_scalars [:, 0 ] = new_scalars [:, 1 ] = tri_scalars
272+ for i in range (3 ):
273+ new_scalars [i ::3 , 2 ] = centre_scalars
274+
275+ return MeshPlot (new_vectors , scalars = new_scalars , opacity = opacity , fig = fig )
244276
245277
246278if __name__ == "__main__" :
247279 import time
248280 import vtkplotlib as vpl
249281 from stl .mesh import Mesh
250-
251-
282+ import geometry as geom
252283
253284 fig = vpl .gcf ()
254285
255286 path = vpl .data .get_rabbit_stl ()
256287 _mesh = Mesh .from_file (path )
257288
258- self = vpl .mesh_plot (_mesh .vectors )
289+ # self = _mesh# vpl.mesh_plot(_mesh.vectors)
259290
260-
261- fig .show (False )
291+ edge_scalars = geom .distance (_mesh .vectors [:, np .arange (1 , 4 ) % 3 ] - _mesh .vectors )
262292
263- t0 = time .perf_counter ()
264- for i in range (100 ):
265- # self.color = np.random.random(3)
266- # print(self.color)
267- self .set_tri_scalars ((_mesh .x [:, 0 ] + 3 * i ) % 20 )
268- _mesh .rotate (np .ones (3 ), .1 , np .mean (_mesh .vectors , (0 , 1 )))
269- fig .update ()
270- self .update_points ()
271- # time.sleep(.01)
272- if (time .perf_counter () - t0 ) > 2 :
273- break
293+ self = vpl .mesh_plot_with_edge_scalars (_mesh , edge_scalars )
294+
295+ mesh_data = _mesh
274296
275297
276298 fig .show ()
0 commit comments