@@ -29,7 +29,6 @@ def plotsurf(node, face, *args, **kwargs):
29
29
from matplotlib .colors import Normalize
30
30
31
31
rngstate = np .random .get_state ()
32
- h = []
33
32
34
33
randseed = int ("623F9A9E" , 16 ) + COLOR_OFFSET
35
34
@@ -39,11 +38,11 @@ def plotsurf(node, face, *args, **kwargs):
39
38
40
39
sc = np .random .rand (10 , 3 )
41
40
42
- ax = plt . gca ( )
41
+ ax = _createaxis ( * args , ** kwargs )
43
42
44
- if ax . name != "3d" :
45
- plt .figure () # Create a new figure
46
- ax = plt . gcf (). add_subplot ( projection = "3d" ) # Add 3D axes to the current figure
43
+ h = { "fig" : [], "ax" : [], "obj" : []}
44
+ h [ "fig" ]. append ( plt .gcf ())
45
+ h [ "ax" ]. append ( ax )
47
46
48
47
if not "color" in kwargs and not "cmap" in kwargs :
49
48
kwargs ["cmap" ] = plt .get_cmap ("jet" )
@@ -127,7 +126,7 @@ def plotsurf(node, face, *args, **kwargs):
127
126
128
127
ax .add_collection3d (patch )
129
128
_autoscale_3d (ax , node )
130
- h .append (ax )
129
+ h [ "obj" ] .append (patch )
131
130
132
131
np .random .set_state (rngstate )
133
132
# plt.axis("equal")
@@ -181,16 +180,15 @@ def plottetra(node, elem, *args, **kwargs):
181
180
182
181
np .random .seed (randseed )
183
182
184
- ax = plt . gca ( )
183
+ ax = _createaxis ( * args , ** kwargs )
185
184
186
- if ax . name != "3d" :
187
- plt .figure () # Create a new figure
188
- ax = plt . gcf (). add_subplot ( projection = "3d" ) # Add 3D axes to the current figure
185
+ h = { "fig" : [], "ax" : [], "obj" : []}
186
+ h [ "fig" ]. append ( plt .gcf ())
187
+ h [ "ax" ]. append ( ax )
189
188
190
189
if not "color" in kwargs and not "cmap" in kwargs :
191
190
kwargs ["cmap" ] = plt .get_cmap ("jet" )
192
191
193
- h = []
194
192
polydata = []
195
193
colormap = []
196
194
@@ -224,16 +222,15 @@ def plottetra(node, elem, *args, **kwargs):
224
222
225
223
patch = Poly3DCollection (polydata , edgecolors = "k" , ** kwargs )
226
224
ax .add_collection3d (patch )
227
-
228
225
_autoscale_3d (ax , node )
229
- h .append (ax )
226
+
227
+ h ["obj" ].append (patch )
230
228
231
229
# Restore RNG state
232
230
np .random .set_state (rngstate )
233
231
234
232
# Return handle if needed
235
- if h :
236
- return h
233
+ return h
237
234
238
235
239
236
# _________________________________________________________________________________________________________
@@ -260,14 +257,19 @@ def plotedges(node, edges, *args, **kwargs):
260
257
Handles to plotted elements.
261
258
"""
262
259
edges = np .asarray (edges , order = "F" ) # Flatten in F order if needed
263
- hh = []
264
260
265
261
if edges .size == 0 :
266
262
return hh
267
263
268
264
edlen = edges .shape [0 ]
269
265
rng_state = np .random .get_state ()
270
266
267
+ ax = _createaxis (* args , ** kwargs )
268
+
269
+ hh = {"fig" : [], "ax" : [], "obj" : []}
270
+ hh ["fig" ].append (plt .gcf ())
271
+ hh ["ax" ].append (ax )
272
+
271
273
if edges .ndim == 1 or edges .shape [1 ] == 1 :
272
274
# Loop: NaN-separated index list
273
275
randseed = int ("623F9A9E" , 16 ) + COLOR_OFFSET
@@ -296,7 +298,7 @@ def plotedges(node, edges, *args, **kwargs):
296
298
* args ,
297
299
** kwargs ,
298
300
)
299
- hh .append (h )
301
+ hh [ "obj" ] .append (h )
300
302
seghead = i + 1
301
303
else :
302
304
from mpl_toolkits .mplot3d .art3d import Line3DCollection
@@ -318,13 +320,12 @@ def plotedges(node, edges, *args, **kwargs):
318
320
ax .add_collection3d (h )
319
321
_autoscale_3d (ax , node )
320
322
321
- hh .append (h )
322
323
else :
323
324
x = node [:, 0 ].flatten ()
324
325
y = node [:, 1 ].flatten ()
325
326
h = plt .plot (x [edges .T ], y [edges .T ], * args , ** kwargs )
326
327
327
- hh .append (h )
328
+ hh [ "obj" ] .append (h )
328
329
329
330
np .random .set_state (rng_state )
330
331
return hh
@@ -335,7 +336,7 @@ def plotedges(node, edges, *args, **kwargs):
335
336
336
337
def plotmesh (node , * args , ** kwargs ):
337
338
"""
338
- plotmesh(node, face, elem, opt) → hm
339
+ handles = plotmesh(node, face, elem, selector, ...)
339
340
Plot surface and volumetric meshes in 3D.
340
341
Converts 1-based MATLAB indices in `face` and `elem` to 0-based.
341
342
Supports optional selector strings and stylistic options.
@@ -376,18 +377,18 @@ def plotmesh(node, *args, **kwargs):
376
377
elem = a
377
378
378
379
extraarg = {}
379
- if len ( opt ) > 1 and len ( opt ) % 2 == 0 :
380
- extraarg = dict ( zip ( opt [:: 2 ], opt [ 1 :: 2 ]))
380
+ if "hold" in kwargs :
381
+ extraarg [ "hold" ] = kwargs [ "hold" ]
381
382
382
- handles = []
383
+ ax = _createaxis ( True , * args , ** kwargs )
383
384
384
- ax = kwargs .get ("parent" , None )
385
+ handles = {"fig" : [], "ax" : [], "obj" : []}
386
+ handles ["fig" ].append (plt .gcf ())
387
+ handles ["ax" ].append (ax )
385
388
386
- if ax is None :
387
- fig = plt .figure ()
388
- ax = fig .add_subplot (111 , projection = "3d" )
389
- else :
390
- del kwargs ["parent" ]
389
+ for extraopt in ["hold" , "parent" , "subplot" ]:
390
+ if extraopt in kwargs :
391
+ del kwargs [extraopt ]
391
392
392
393
# Plot points if no face/elem
393
394
if face is None and elem is None :
@@ -400,17 +401,17 @@ def plotmesh(node, *args, **kwargs):
400
401
if getattr (idx , "size" , None ) == 0 :
401
402
print ("Warning: nothing to plot" )
402
403
return None
403
- ax .plot (x [idx ], y [idx ], z [idx ], ** kwargs )
404
+ (h ,) = ax .plot (x [idx ], y [idx ], z [idx ], * opt , ** kwargs )
405
+ handles ["obj" ].append (h )
404
406
_autoscale_3d (ax , node )
405
407
if not "hold" in extraarg or not extraarg ["hold" ] or extraarg ["hold" ] == "off" :
406
408
plt .show (block = False )
407
- return ax
409
+ return handles
408
410
409
411
# Plot surface mesh
410
412
if face is not None :
411
413
if isinstance (face , list ):
412
- ax = plotsurf (node , face , opt , * args , ** kwargs )
413
- handles .append (ax )
414
+ handles = plotsurf (node , face , opt , * args , ** kwargs )
414
415
else :
415
416
c0 = meshcentroid (node [:, :3 ], face [:, :3 ])
416
417
x , y , z = c0 [:, 0 ], c0 [:, 1 ], c0 [:, 2 ]
@@ -422,8 +423,7 @@ def plotmesh(node, *args, **kwargs):
422
423
if getattr (idx , "size" , None ) == 0 :
423
424
print ("Warning: nothing to plot" )
424
425
return None
425
- ax = plotsurf (node , face [idx , :], opt , * args , ** kwargs )
426
- handles .append (ax )
426
+ handles = plotsurf (node , face [idx , :], opt , * args , ** kwargs )
427
427
428
428
# Plot tetrahedral mesh
429
429
if elem is not None :
@@ -437,13 +437,12 @@ def plotmesh(node, *args, **kwargs):
437
437
if getattr (idx , "size" , None ) == 0 :
438
438
print ("Warning: nothing to plot" )
439
439
return None
440
- ax = plottetra (node , elem [idx , :], opt , * args , ** kwargs )
441
- handles .append (ax )
440
+ handles = plottetra (node , elem [idx , :], opt , * args , ** kwargs )
442
441
443
442
if not "hold" in extraarg or not extraarg ["hold" ] or extraarg ["hold" ] == "off" :
444
443
plt .show (block = False )
445
444
446
- return handles if len ( handles ) > 1 else handles [ 0 ]
445
+ return handles
447
446
448
447
449
448
def _autoscale_3d (ax , points ):
@@ -453,3 +452,27 @@ def _autoscale_3d(ax, points):
453
452
ax .set_zlim ([z .min (), z .max ()])
454
453
boxas = [x .max () - x .min (), y .max () - y .min (), z .max () - z .min ()]
455
454
ax .set_box_aspect (boxas )
455
+
456
+
457
+ def _createaxis (* args , ** kwargs ):
458
+ subplotid = kwargs .get ("subplot" , 111 )
459
+ docreate = False if len (args ) == 0 else args [0 ]
460
+
461
+ if "parent" in kwargs :
462
+ ax = kwargs ["parent" ]
463
+ if isinstance (ax , dict ):
464
+ ax = ax ["ax" ][- 1 ]
465
+ elif isinstance (ax , list ):
466
+ ax = ax [- 1 ]
467
+ elif not docreate and len (plt .get_fignums ()) > 0 and len (plt .gcf ().axes ) > 0 :
468
+ ax = plt .gcf ().axes [- 1 ]
469
+ else :
470
+ if docreate :
471
+ plt .figure ()
472
+ ax = plt .gcf ().add_subplot (subplotid , projection = "3d" )
473
+
474
+ if ax .name != "3d" :
475
+ plt .figure () # Create a new figure
476
+ ax = plt .gcf ().add_subplot (subplotid , projection = "3d" )
477
+
478
+ return ax
0 commit comments