@@ -79,7 +79,7 @@ def _viewlim_mask(xs, ys, zs, axes):
7979 Parameters
8080 ----------
8181 xs, ys, zs : array-like
82- The points to mask.
82+ The points to mask. These should be in data coordinates.
8383 axes : Axes3D
8484 The axes to use for the view limits.
8585
@@ -198,7 +198,10 @@ def draw(self, renderer):
198198 else :
199199 pos3d = np .array ([self ._x , self ._y , self ._z ], dtype = float )
200200
201- proj = proj3d ._proj_trans_points ([pos3d , pos3d + self ._dir_vec ], self .axes .M )
201+ dir_end = pos3d + self ._dir_vec
202+ points = np .asarray ([pos3d , dir_end ])
203+ proj = proj3d ._scale_proj_transform (
204+ points [:, 0 ], points [:, 1 ], points [:, 2 ], self .axes )
202205 dx = proj [0 ][1 ] - proj [0 ][0 ]
203206 dy = proj [1 ][1 ] - proj [1 ][0 ]
204207 angle = math .degrees (math .atan2 (dy , dx ))
@@ -334,9 +337,7 @@ def draw(self, renderer):
334337 dtype = float , mask = mask ).filled (np .nan )
335338 else :
336339 xs3d , ys3d , zs3d = self ._verts3d
337- xs , ys , zs , tis = proj3d ._proj_transform_clip (xs3d , ys3d , zs3d ,
338- self .axes .M ,
339- self .axes ._focal_length )
340+ xs , ys , zs , tis = proj3d ._scale_proj_transform_clip (xs3d , ys3d , zs3d , self .axes )
340341 self .set_data (xs , ys )
341342 super ().draw (renderer )
342343 self .stale = False
@@ -427,7 +428,8 @@ def do_3d_projection(self):
427428 vs_list = [np .ma .array (vs , mask = np .broadcast_to (
428429 _viewlim_mask (* vs .T , self .axes ), vs .shape ))
429430 for vs in vs_list ]
430- xyzs_list = [proj3d .proj_transform (* vs .T , self .axes .M ) for vs in vs_list ]
431+ xyzs_list = [proj3d ._scale_proj_transform (
432+ vs [:, 0 ], vs [:, 1 ], vs [:, 2 ], self .axes ) for vs in vs_list ]
431433 self ._paths = [mpath .Path (np .ma .column_stack ([xs , ys ]), cs )
432434 for (xs , ys , _ ), (_ , cs ) in zip (xyzs_list , self ._3dverts_codes )]
433435 zs = np .concatenate ([zs for _ , _ , zs in xyzs_list ])
@@ -497,6 +499,11 @@ def do_3d_projection(self):
497499 """
498500 segments = np .asanyarray (self ._segments3d )
499501
502+ # Handle empty segments
503+ if segments .size == 0 :
504+ LineCollection .set_segments (self , [])
505+ return np .nan
506+
500507 mask = False
501508 if np .ma .isMA (segments ):
502509 mask = segments .mask
@@ -511,8 +518,9 @@ def do_3d_projection(self):
511518 viewlim_mask = np .broadcast_to (viewlim_mask [..., np .newaxis ],
512519 (* viewlim_mask .shape , 3 ))
513520 mask = mask | viewlim_mask
514- xyzs = np .ma .array (proj3d ._proj_transform_vectors (segments , self .axes .M ),
515- mask = mask )
521+
522+ xyzs = np .ma .array (
523+ proj3d ._scale_proj_transform_vectors (segments , self .axes ), mask = mask )
516524 segments_2d = xyzs [..., 0 :2 ]
517525 LineCollection .set_segments (self , segments_2d )
518526
@@ -595,9 +603,7 @@ def do_3d_projection(self):
595603 dtype = float , mask = mask ).filled (np .nan )
596604 else :
597605 xs , ys , zs = zip (* s )
598- vxs , vys , vzs , vis = proj3d ._proj_transform_clip (xs , ys , zs ,
599- self .axes .M ,
600- self .axes ._focal_length )
606+ vxs , vys , vzs , vis = proj3d ._scale_proj_transform_clip (xs , ys , zs , self .axes )
601607 self ._path2d = mpath .Path (np .ma .column_stack ([vxs , vys ]))
602608 return min (vzs )
603609
@@ -657,9 +663,7 @@ def do_3d_projection(self):
657663 dtype = float , mask = mask ).filled (np .nan )
658664 else :
659665 xs , ys , zs = zip (* s )
660- vxs , vys , vzs , vis = proj3d ._proj_transform_clip (xs , ys , zs ,
661- self .axes .M ,
662- self .axes ._focal_length )
666+ vxs , vys , vzs , vis = proj3d ._scale_proj_transform_clip (xs , ys , zs , self .axes )
663667 self ._path2d = mpath .Path (np .ma .column_stack ([vxs , vys ]), self ._code3d )
664668 return min (vzs )
665669
@@ -802,9 +806,7 @@ def do_3d_projection(self):
802806 xs , ys , zs = np .ma .array (self ._offsets3d , mask = mask )
803807 else :
804808 xs , ys , zs = self ._offsets3d
805- vxs , vys , vzs , vis = proj3d ._proj_transform_clip (xs , ys , zs ,
806- self .axes .M ,
807- self .axes ._focal_length )
809+ vxs , vys , vzs , vis = proj3d ._scale_proj_transform_clip (xs , ys , zs , self .axes )
808810 self ._vzs = vzs
809811 if np .ma .isMA (vxs ):
810812 super ().set_offsets (np .ma .column_stack ([vxs , vys ]))
@@ -1020,9 +1022,7 @@ def do_3d_projection(self):
10201022 xyzs = np .ma .array (self ._offsets3d , mask = mask )
10211023 else :
10221024 xyzs = self ._offsets3d
1023- vxs , vys , vzs , vis = proj3d ._proj_transform_clip (* xyzs ,
1024- self .axes .M ,
1025- self .axes ._focal_length )
1025+ vxs , vys , vzs , vis = proj3d ._scale_proj_transform_clip (* xyzs , self .axes )
10261026 self ._data_scale = _get_data_scale (vxs , vys , vzs )
10271027 # Sort the points based on z coordinates
10281028 # Performance optimization: Create a sorted index array and reorder
@@ -1356,7 +1356,7 @@ def do_3d_projection(self):
13561356 # Some faces might contain masked vertices, so we want to ignore any
13571357 # errors that those might cause
13581358 with np .errstate (invalid = 'ignore' , divide = 'ignore' ):
1359- pfaces = proj3d ._proj_transform_vectors (self ._faces , self .axes . M )
1359+ pfaces = proj3d ._scale_proj_transform_vectors (self ._faces , self .axes )
13601360
13611361 if self ._axlim_clip :
13621362 viewlim_mask = _viewlim_mask (self ._faces [..., 0 ], self ._faces [..., 1 ],
0 commit comments