20
20
Collection ,LineCollection ,PolyCollection ,PatchCollection ,PathCollection )
21
21
from matplotlib .colors import Normalize
22
22
from matplotlib .patches import Patch
23
- from .import proj3d
24
23
25
24
26
25
def _norm_angle (a ):
@@ -148,12 +147,11 @@ def set_3d_properties(self, z=0, zdir='z'):
148
147
@artist .allow_rasterization
149
148
def draw (self ,renderer ):
150
149
position3d = np .array ((self ._x ,self ._y ,self ._z ))
151
- proj = proj3d ._proj_trans_points (
152
- [position3d ,position3d + self ._dir_vec ],self .axes .M )
153
- dx = proj [0 ][1 ]- proj [0 ][0 ]
154
- dy = proj [1 ][1 ]- proj [1 ][0 ]
150
+ proj = self .axes .M .transform ([position3d ,position3d + self ._dir_vec ])
151
+ dx = proj [1 ][0 ]- proj [0 ][0 ]
152
+ dy = proj [1 ][1 ]- proj [0 ][1 ]
155
153
angle = math .degrees (math .atan2 (dy ,dx ))
156
- with cbook ._setattr_cm (self ,_x = proj [0 ][0 ],_y = proj [1 ][ 0 ],
154
+ with cbook ._setattr_cm (self ,_x = proj [0 ][0 ],_y = proj [0 ][ 1 ],
157
155
_rotation = _norm_text_angle (angle )):
158
156
mtext .Text .draw (self ,renderer )
159
157
self .stale = False
@@ -267,8 +265,8 @@ def get_data_3d(self):
267
265
@artist .allow_rasterization
268
266
def draw (self ,renderer ):
269
267
xs3d ,ys3d ,zs3d = self ._verts3d
270
- xs , ys , zs = proj3d . proj_transform ( xs3d ,ys3d ,zs3d , self . axes . M )
271
- self .set_data (xs , ys )
268
+ points = self . axes . M . transform ( np . column_stack (( xs3d ,ys3d ,zs3d )) )
269
+ self .set_data (points [:, 0 ], points [:, 1 ] )
272
270
super ().draw (renderer )
273
271
self .stale = False
274
272
@@ -349,11 +347,11 @@ class Collection3D(Collection):
349
347
350
348
def do_3d_projection (self ):
351
349
"""Project the points according to renderer matrix."""
352
- xyzs_list = [proj3d . proj_transform ( * vs . T , self .axes . M )
353
- for vs , _ in self . _3dverts_codes ]
354
- self . _paths = [ mpath . Path ( np . column_stack ([ xs , ys ]), cs )
355
- for ( xs , ys , _ ), ( _ , cs ) in zip (xyzs_list ,self ._3dverts_codes )]
356
- zs = np .concatenate ([ zs for _ , _ , zs in xyzs_list ])
350
+ path_vertices = [self . axes . M . transform ( vs ) for vs , _ in self ._3dverts_codes ]
351
+ self . _paths = [ mpath . Path ( vertices [:, : 2 ], codes )
352
+ for ( vertices , ( _ , codes ) )
353
+ in zip (path_vertices ,self ._3dverts_codes )]
354
+ zs = np .concatenate (path_vertices )[:, 2 ]
357
355
return zs .min ()if len (zs )else 1e9
358
356
359
357
@@ -390,15 +388,14 @@ def do_3d_projection(self):
390
388
"""
391
389
Project the points according to renderer matrix.
392
390
"""
393
- xyslist = [proj3d ._proj_trans_points (points ,self .axes .M )
394
- for points in self ._segments3d ]
395
- segments_2d = [np .column_stack ([xs ,ys ])for xs ,ys ,zs in xyslist ]
391
+ segments_3d = [self .axes .M .transform (segment )for segment in self ._segments3d ]
392
+ segments_2d = [segment [:, :2 ]for segment in segments_3d ]
396
393
LineCollection .set_segments (self ,segments_2d )
397
394
398
395
# FIXME
399
396
minz = 1e9
400
- for xs , ys , zs in xyslist :
401
- minz = min (minz ,min ( zs ) )
397
+ for segment in segments_3d :
398
+ minz = min (minz ,segment [ 0 ][ 2 ], segment [ 1 ][ 2 ] )
402
399
return minz
403
400
404
401
@@ -456,12 +453,10 @@ def get_path(self):
456
453
return self ._path2d
457
454
458
455
def do_3d_projection (self ):
459
- s = self ._segment3d
460
- xs ,ys ,zs = zip (* s )
461
- vxs ,vys ,vzs ,vis = proj3d .proj_transform_clip (xs ,ys ,zs ,
462
- self .axes .M )
463
- self ._path2d = mpath .Path (np .column_stack ([vxs ,vys ]))
464
- return min (vzs )
456
+ segments = self .axes .M .transform (self ._segment3d )
457
+ self ._path2d = mpath .Path (segments [:, :2 ])
458
+
459
+ return min (segments [:,2 ])
465
460
466
461
467
462
class PathPatch3D (Patch3D ):
@@ -503,12 +498,10 @@ def set_3d_properties(self, path, zs=0, zdir='z'):
503
498
self ._code3d = path .codes
504
499
505
500
def do_3d_projection (self ):
506
- s = self ._segment3d
507
- xs ,ys ,zs = zip (* s )
508
- vxs ,vys ,vzs ,vis = proj3d .proj_transform_clip (xs ,ys ,zs ,
509
- self .axes .M )
510
- self ._path2d = mpath .Path (np .column_stack ([vxs ,vys ]),self ._code3d )
511
- return min (vzs )
501
+ segments = self .axes .M .transform (self ._segment3d )
502
+ self ._path2d = mpath .Path (segments [:, :2 ],self ._code3d )
503
+
504
+ return min (segments [:,2 ])
512
505
513
506
514
507
def _get_patch_verts (patch ):
@@ -610,14 +603,13 @@ def set_3d_properties(self, zs, zdir):
610
603
self .stale = True
611
604
612
605
def do_3d_projection (self ):
613
- xs ,ys ,zs = self ._offsets3d
614
- vxs ,vys ,vzs ,vis = proj3d .proj_transform_clip (xs ,ys ,zs ,
615
- self .axes .M )
616
- self ._vzs = vzs
617
- super ().set_offsets (np .column_stack ([vxs ,vys ]))
606
+ points = self .axes .M .transform (np .column_stack (self ._offsets3d ))
607
+ super ().set_offsets (points [:, :2 ])
618
608
619
- if vzs .size > 0 :
620
- return min (vzs )
609
+ self ._vzs = points [:,2 ]
610
+
611
+ if self ._vzs .size > 0 :
612
+ return min (self ._vzs )
621
613
else :
622
614
return np .nan
623
615
@@ -751,37 +743,31 @@ def set_depthshade(self, depthshade):
751
743
self .stale = True
752
744
753
745
def do_3d_projection (self ):
754
- xs ,ys ,zs = self ._offsets3d
755
- vxs ,vys ,vzs ,vis = proj3d .proj_transform_clip (xs ,ys ,zs ,
756
- self .axes .M )
757
746
# Sort the points based on z coordinates
758
747
# Performance optimization: Create a sorted index array and reorder
759
748
# points and point properties according to the index array
760
- z_markers_idx = self ._z_markers_idx = np .argsort (vzs )[::- 1 ]
761
- self ._vzs = vzs
749
+ points = self .axes .M .transform (np .column_stack (self ._offsets3d ))
750
+ z_markers_idx = self ._z_markers_idx = np .argsort (points [:,2 ])[::- 1 ]
751
+ self ._vzs = points [:,2 ]
762
752
763
753
# we have to special case the sizes because of code in collections.py
764
754
# as the draw method does
765
755
# self.set_sizes(self._sizes, self.figure.dpi)
766
756
# so we cannot rely on doing the sorting on the way out via get_*
767
-
768
757
if len (self ._sizes3d )> 1 :
769
758
self ._sizes = self ._sizes3d [z_markers_idx ]
770
759
771
760
if len (self ._linewidths3d )> 1 :
772
761
self ._linewidths = self ._linewidths3d [z_markers_idx ]
773
762
774
- PathCollection .set_offsets (self ,np . column_stack (( vxs , vys )) )
763
+ PathCollection .set_offsets (self ,points [:, : 2 ] )
775
764
776
765
# Re-order items
777
- vzs = vzs [z_markers_idx ]
778
- vxs = vxs [z_markers_idx ]
779
- vys = vys [z_markers_idx ]
766
+ points = points [z_markers_idx ]
780
767
781
768
# Store ordered offset for drawing purpose
782
- self ._offset_zordered = np .column_stack ((vxs ,vys ))
783
-
784
- return np .min (vzs )if vzs .size else np .nan
769
+ self ._offset_zordered = points [:, :2 ]
770
+ return np .min (self ._vzs )if self ._vzs .size else np .nan
785
771
786
772
@contextmanager
787
773
def _use_zordered_offset (self ):
@@ -954,8 +940,7 @@ def get_vector(self, segments3d):
954
940
xs ,ys ,zs = np .vstack (segments3d ).T
955
941
else :# vstack can't stack zero arrays.
956
942
xs ,ys ,zs = [], [], []
957
- ones = np .ones (len (xs ))
958
- self ._vec = np .array ([xs ,ys ,zs ,ones ])
943
+ self ._vec = np .array ([xs ,ys ,zs ])
959
944
960
945
indices = [0 ,* np .cumsum ([len (segment )for segment in segments3d ])]
961
946
self ._segslices = [* map (slice ,indices [:- 1 ],indices [1 :])]
@@ -1020,27 +1005,28 @@ def do_3d_projection(self):
1020
1005
self ._facecolor3d = self ._facecolors
1021
1006
if self ._edge_is_mapped :
1022
1007
self ._edgecolor3d = self ._edgecolors
1023
- txs ,tys ,tzs = proj3d ._proj_transform_vec (self ._vec ,self .axes .M )
1024
- xyzlist = [(txs [sl ],tys [sl ],tzs [sl ])for sl in self ._segslices ]
1008
+
1009
+ verts = self .axes .M .transform (np .column_stack (self ._vec ))
1010
+ verts_slices = [verts [sl ]for sl in self ._segslices ]
1025
1011
1026
1012
# This extra fuss is to re-order face / edge colors
1027
1013
cface = self ._facecolor3d
1028
1014
cedge = self ._edgecolor3d
1029
- if len (cface )!= len (xyzlist ):
1030
- cface = cface .repeat (len (xyzlist ),axis = 0 )
1031
- if len (cedge )!= len (xyzlist ):
1015
+
1016
+ if len (cface )!= len (verts_slices ):
1017
+ cface = cface .repeat (len (verts_slices ),axis = 0 )
1018
+ if len (cedge )!= len (verts_slices ):
1032
1019
if len (cedge )== 0 :
1033
1020
cedge = cface
1034
1021
else :
1035
- cedge = cedge .repeat (len (xyzlist ),axis = 0 )
1022
+ cedge = cedge .repeat (len (verts_slices ),axis = 0 )
1036
1023
1037
- if xyzlist :
1038
- # sort by depth (furthest drawn first)
1024
+ if verts_slices :
1039
1025
z_segments_2d = sorted (
1040
- ((self ._zsortfunc (zs ),np . column_stack ([ xs , ys ]) ,fc ,ec ,idx )
1041
- for idx , (( xs , ys , zs ) ,fc ,ec )
1042
- in enumerate (zip (xyzlist ,cface ,cedge ))),
1043
- key = lambda x :x [0 ],reverse = True )
1026
+ ((self ._zsortfunc (verts [:, 2 ] ),verts [:, : 2 ] ,fc ,ec ,idx )
1027
+ for idx , (verts ,fc ,ec )
1028
+ in enumerate (zip (verts_slices ,cface ,cedge ))),
1029
+ key = lambda x :x [0 ],reverse = True )
1044
1030
1045
1031
_ ,segments_2d ,self ._facecolors2d ,self ._edgecolors2d ,idxs = \
1046
1032
zip (* z_segments_2d )
@@ -1061,14 +1047,12 @@ def do_3d_projection(self):
1061
1047
1062
1048
# Return zorder value
1063
1049
if self ._sort_zpos is not None :
1064
- zvec = np .array ([[0 ], [0 ], [self ._sort_zpos ], [1 ]])
1065
- ztrans = proj3d ._proj_transform_vec (zvec ,self .axes .M )
1066
- return ztrans [2 ][0 ]
1067
- elif tzs .size > 0 :
1050
+ return self .axes .M .transform ([0 ,0 ,self ._sort_zpos ])[2 ]
1051
+ elif len (verts )> 0 :
1068
1052
# FIXME: Some results still don't look quite right.
1069
1053
# In particular, examine contourf3d_demo2.py
1070
1054
# with az = -54 and elev = -45.
1071
- return np .min (tzs )
1055
+ return np .min (verts [:, 2 ] )
1072
1056
else :
1073
1057
return np .nan
1074
1058