Skip to content

Move 3D attribute sorting into overridden draw methods #18932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 42 additions & 65 deletions lib/mpl_toolkits/mplot3d/art3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,16 +454,6 @@ def set_depthshade(self, depthshade):
self._depthshade = depthshade
self.stale = True

def set_facecolor(self, c):
# docstring inherited
super().set_facecolor(c)
self._facecolor3d = self.get_facecolor()

def set_edgecolor(self, c):
# docstring inherited
super().set_edgecolor(c)
self._edgecolor3d = self.get_edgecolor()

def set_sort_zpos(self, val):
"""Set the position to use for z-sorting."""
self._sort_zpos = val
Expand All @@ -480,32 +470,39 @@ def set_3d_properties(self, zs, zdir):
xs = []
ys = []
self._offsets3d = juggle_axes(xs, ys, np.atleast_1d(zs), zdir)
self._facecolor3d = self.get_facecolor()
self._edgecolor3d = self.get_edgecolor()
self.stale = True

@cbook._delete_parameter('3.4', 'renderer')
def do_3d_projection(self, renderer=None):
xs, ys, zs = self._offsets3d
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs,
self.axes.M)

fcs = (_zalpha(self._facecolor3d, vzs) if self._depthshade else
self._facecolor3d)
fcs = mcolors.to_rgba_array(fcs, self._alpha)
super().set_facecolor(fcs)

ecs = (_zalpha(self._edgecolor3d, vzs) if self._depthshade else
self._edgecolor3d)
ecs = mcolors.to_rgba_array(ecs, self._alpha)
super().set_edgecolor(ecs)
super().set_offsets(np.column_stack([vxs, vys]))

if vzs.size > 0:
return min(vzs)
else:
return np.nan

@artist.allow_rasterization
def draw(self, renderer):
# docstring inherited
xs, ys, zs = self._offsets3d
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs,
self.axes.M)

fcs = self.get_facecolor()
ecs = self.get_edgecolor()
if self._depthshade:
fcs = _zalpha(fcs, vzs)
ecs = _zalpha(ecs, vzs)
fcs = mcolors.to_rgba_array(fcs, self._alpha)
ecs = mcolors.to_rgba_array(ecs, self._alpha)

offsets = np.column_stack([vxs, vys])

with cbook._setattr_cm(self, _edgecolors=ecs, _facecolors=fcs,
_offsets=offsets):
super().draw(renderer)


class Path3DCollection(PathCollection):
"""
Expand Down Expand Up @@ -548,10 +545,6 @@ def set_3d_properties(self, zs, zdir):
xs = []
ys = []
self._offsets3d = juggle_axes(xs, ys, np.atleast_1d(zs), zdir)
self._facecolor3d = self.get_facecolor()
self._edgecolor3d = self.get_edgecolor()
self._sizes3d = self.get_sizes()
self._linewidth3d = self.get_linewidth()
self.stale = True

def get_depthshade(self):
Expand All @@ -570,46 +563,38 @@ def set_depthshade(self, depthshade):
self._depthshade = depthshade
self.stale = True

def set_facecolor(self, c):
# docstring inherited
super().set_facecolor(c)
self._facecolor3d = self.get_facecolor()

def set_edgecolor(self, c):
# docstring inherited
super().set_edgecolor(c)
self._edgecolor3d = self.get_edgecolor()

def set_sizes(self, sizes, dpi=72.0):
# docstring inherited
super().set_sizes(sizes, dpi=dpi)
self._sizes3d = self.get_sizes()
@cbook._delete_parameter('3.4', 'renderer')
def do_3d_projection(self, renderer=None):
xs, ys, zs = self._offsets3d
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs,
self.axes.M)
return np.min(vzs) if vzs.size else np.nan

def set_linewidth(self, lw):
@artist.allow_rasterization
def draw(self, renderer):
# docstring inherited
super().set_linewidth(lw)
self._linewidth3d = self.get_linewidth()
self.update_scalarmappable()

@cbook._delete_parameter('3.4', 'renderer')
def do_3d_projection(self, renderer=None):
xs, ys, zs = self._offsets3d
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs,
self.axes.M)

fcs = (_zalpha(self._facecolor3d, vzs) if self._depthshade else
self._facecolor3d)
ecs = (_zalpha(self._edgecolor3d, vzs) if self._depthshade else
self._edgecolor3d)
sizes = self._sizes3d
lws = self._linewidth3d
fcs = self.get_facecolor()
ecs = self.get_edgecolor()
if self._depthshade:
fcs = _zalpha(fcs, vzs)
ecs = _zalpha(ecs, vzs)
fcs = mcolors.to_rgba_array(fcs, self._alpha)
ecs = mcolors.to_rgba_array(ecs, self._alpha)
sizes = self.get_sizes()
lws = self.get_linewidth()

# Sort the points based on z coordinates
# Performance optimization: Create a sorted index array and reorder
# points and point properties according to the index array
z_markers_idx = np.argsort(vzs)[::-1]

# Re-order items
vzs = vzs[z_markers_idx]
vxs = vxs[z_markers_idx]
vys = vys[z_markers_idx]
if len(fcs) > 1:
Expand All @@ -622,17 +607,9 @@ def do_3d_projection(self, renderer=None):
lws = lws[z_markers_idx]
vps = np.column_stack((vxs, vys))

fcs = mcolors.to_rgba_array(fcs, self._alpha)
ecs = mcolors.to_rgba_array(ecs, self._alpha)

super().set_edgecolor(ecs)
super().set_facecolor(fcs)
super().set_sizes(sizes)
super().set_linewidth(lws)

PathCollection.set_offsets(self, vps)

return np.min(vzs) if vzs.size else np.nan
with cbook._setattr_cm(self, _edgecolors=ecs, _facecolors=fcs,
_linewidths=lws, _offsets=vps, _sizes=sizes):
super().draw(renderer)


def patch_collection_2d_to_3d(col, zs=0, zdir='z', depthshade=True):
Expand Down