Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6315961

Browse files
Use a contiguous representation in memory and views for the segments
1 parent c4de047 commit 6315961

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

lib/mpl_toolkits/mplot3d/art3d.py

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -217,23 +217,39 @@ def set_segments(self, segments):
217217
'''
218218
Set 3D segments
219219
'''
220-
self._segments3d = np.asanyarray(segments)
220+
self._seg_sizes = [len(c) for c in segments]
221+
self._segments3d = []
222+
if len(segments) > 0:
223+
# Store the points in a single array for easier projection
224+
n_segments = np.sum(self._seg_sizes)
225+
# Put all segments in a big array
226+
self._segments3d_data = np.vstack(segments)
227+
# Add a fourth dimension for quaternions
228+
self._segments3d_data = np.hstack([self._segments3d_data,
229+
np.ones((n_segments, 1))])
230+
231+
# For coveniency, store a view of the array in the original shape
232+
cum_s = 0
233+
for s in self._seg_sizes:
234+
self._segments3d.append(
235+
self._segments3d_data[cum_s:cum_s + s, :3])
236+
cum_s += s
221237
LineCollection.set_segments(self, [])
222238

223239
def do_3d_projection(self, renderer):
224240
'''
225241
Project the points according to renderer matrix.
226242
'''
227-
shape = self._segments3d.shape
228-
segments3d = np.transpose(self._segments3d, axes=[2, 0, 1])
229-
segments3d = segments3d.reshape((3, -1))
230-
# Pad ones
231-
segments3d = np.vstack([segments3d, np.ones((1, segments3d.shape[1]))])
232-
xys = proj3d.proj_transform_vec(segments3d, renderer.M)
233-
xys = np.reshape(xys.T, shape)
234-
segments_2d = xys[:, :, 0:2]
243+
if len(self._segments3d) == 0:
244+
return 1e9
245+
xys = proj3d.proj_transform_vec(self._segments3d_data.T, renderer.M).T
246+
segments_2d = []
247+
cum_s = 0
248+
for s in self._seg_sizes:
249+
segments_2d.append(xys[cum_s:cum_s + s, :2])
250+
cum_s += s
235251
LineCollection.set_segments(self, segments_2d)
236-
minz = np.min(xys[:, :, 2]) if xys.size > 0 else 1e9
252+
minz = np.min(xys[:, 2])
237253
return minz
238254

239255
def draw(self, renderer, project=False):
@@ -301,7 +317,7 @@ def set_3d_properties(self, path, zs=0, zdir='z'):
301317

302318
def do_3d_projection(self, renderer):
303319
# pad ones
304-
s = np.vstack(self._segmenta3d, np.ones(self._segment3d.shape[1]))
320+
s = np.vstack(self._segments3d, np.ones(self._segments3d.shape[1]))
305321
vxyzis = proj3d.proj_transform_vec_clip(s, renderer.M)
306322
self._path2d = mpath.Path(vxyzis[0:2].T, self._code3d)
307323
# FIXME: coloring
@@ -433,8 +449,10 @@ def set_3d_properties(self, zs, zdir):
433449
# Force the collection to initialize the face and edgecolors
434450
# just in case it is a scalarmappable with a colormap.
435451
self.update_scalarmappable()
436-
offsets = np.vstack(self.get_offsets(), np.ones(len(verts)) * zs)
437-
self._offsets3d = juggle_axes_vec(offsets, zdir)
452+
offsets = self.get_offsets()
453+
offsets = np.hstack([offsets,
454+
(np.ones(len(offsets)) * zs)[:, np.newaxis]])
455+
self._offsets3d = juggle_axes_vec(offsets, zdir).T
438456
self._facecolor3d = self.get_facecolor()
439457
self._edgecolor3d = self.get_edgecolor()
440458
self.stale = True
@@ -539,14 +557,16 @@ def set_zsort(self, zsort):
539557

540558
def get_vector(self, segments3d):
541559
"""Optimize points for projection"""
542-
segments3d = np.asarray(segments3d)
543-
# Segments 3d are given in shape (n_segments, segsize, 3)
544-
self._segsize = segments3d.shape[1]
545-
# Flatten
546-
xyz = segments3d.T.reshape((3, -1))
547-
# Add a fourth dimension with only ones
548-
ones = np.ones(xyz.shape[1])
549-
self._vec = np.vstack([xyz, ones])
560+
561+
self._seg_sizes = [len(c) for c in segments3d]
562+
self._vec = []
563+
if len(segments3d) > 0:
564+
# Store the points in a single array for easier projection
565+
n_segments = np.sum(self._seg_sizes)
566+
# Put all segments in a big array
567+
self._vec = np.vstack(segments3d)
568+
# Add a fourth dimension for quaternions
569+
self._vec = np.hstack([self._vec, np.ones((n_segments, 1))]).T
550570

551571
def set_verts(self, verts, closed=True):
552572
'''Set 3D vertices.'''
@@ -574,7 +594,7 @@ def set_3d_properties(self):
574594
self._alpha3d = PolyCollection.get_alpha(self)
575595
self.stale = True
576596

577-
def set_sort_zpos(self,val):
597+
def set_sort_zpos(self, val):
578598
'''Set the position to use for z-sorting.'''
579599
self._sort_zpos = val
580600
self.stale = True
@@ -588,9 +608,12 @@ def do_3d_projection(self, renderer):
588608
self.update_scalarmappable()
589609
self._facecolors3d = self._facecolors
590610

591-
xys = proj3d.proj_transform_vec(self._vec, renderer.M)
592-
xys = np.reshape(xys, (3, self._segsize, -1))
593-
xyzlist = xys.T
611+
xys = proj3d.proj_transform_vec(self._vec, renderer.M).T
612+
xyzlist = []
613+
cum_s = 0
614+
for s in self._seg_sizes:
615+
xyzlist.append(xys[cum_s:cum_s + s, :3])
616+
cum_s += s
594617

595618
# This extra fuss is to re-order face / edge colors
596619
cface = self._facecolors3d
@@ -605,11 +628,11 @@ def do_3d_projection(self, renderer):
605628
# if required sort by depth (furthest drawn first)
606629
if self._zsort:
607630
z_argsort = np.argsort(
608-
self._zsortfunc(xyzlist[:, :, 2], axis=1))[::-1]
631+
[self._zsortfunc(xyz[:, 2]) for xyz in xyzlist])[::-1]
609632
else:
610633
raise ValueError("whoops")
611634

612-
segments_2d = xyzlist[z_argsort, :, 0:2]
635+
segments_2d = [xyzlist[i][:, 0:2] for i in z_argsort]
613636
if self._codes3d is not None:
614637
codes = self._codes3d[z_argsort]
615638
PolyCollection.set_verts_and_codes(self, segments_2d, codes)

0 commit comments

Comments
 (0)