From e66cd0fb803fc4bd4238ccf2c48f21e77c217664 Mon Sep 17 00:00:00 2001 From: Tom Neep Date: Wed, 14 Jul 2021 14:26:18 +0100 Subject: [PATCH 1/4] Ensure NaN values properly handled in sorted --- lib/mpl_toolkits/mplot3d/art3d.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py index 8b0669775eaf..de62176c80e6 100644 --- a/lib/mpl_toolkits/mplot3d/art3d.py +++ b/lib/mpl_toolkits/mplot3d/art3d.py @@ -8,6 +8,7 @@ """ import math +import sys import numpy as np @@ -733,7 +734,13 @@ def set_zsort(self, zsort): The function applied on the z-coordinates of the vertices in the viewer's coordinate system, to determine the z-order. """ - self._zsortfunc = self._zsort_functions[zsort] + def nansafe(func): + def f(x): + value = func(x) + return sys.maxsize if np.isnan(value) else value + return f + + self._zsortfunc = nansafe(self._zsort_functions[zsort]) self._sort_zpos = None self.stale = True From 498bcdda09058db2fd1aca9cc2437e5f2fa26055 Mon Sep 17 00:00:00 2001 From: Tom Neep Date: Tue, 20 Jul 2021 17:35:50 +0100 Subject: [PATCH 2/4] Use np.inf instead of sys.maxsize --- lib/mpl_toolkits/mplot3d/art3d.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py index de62176c80e6..e58215df5e94 100644 --- a/lib/mpl_toolkits/mplot3d/art3d.py +++ b/lib/mpl_toolkits/mplot3d/art3d.py @@ -8,7 +8,6 @@ """ import math -import sys import numpy as np @@ -737,7 +736,7 @@ def set_zsort(self, zsort): def nansafe(func): def f(x): value = func(x) - return sys.maxsize if np.isnan(value) else value + return np.inf if np.isnan(value) else value return f self._zsortfunc = nansafe(self._zsort_functions[zsort]) From f2f407f3ea701cf81ef853c4160ca4433b988c52 Mon Sep 17 00:00:00 2001 From: Tom Neep Date: Thu, 22 Jul 2021 11:58:20 +0100 Subject: [PATCH 3/4] Ensure polygons that are not entirely nans are handled correctly --- lib/mpl_toolkits/mplot3d/art3d.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py index e58215df5e94..e39eb346bde1 100644 --- a/lib/mpl_toolkits/mplot3d/art3d.py +++ b/lib/mpl_toolkits/mplot3d/art3d.py @@ -733,16 +733,14 @@ def set_zsort(self, zsort): The function applied on the z-coordinates of the vertices in the viewer's coordinate system, to determine the z-order. """ - def nansafe(func): - def f(x): - value = func(x) - return np.inf if np.isnan(value) else value - return f - - self._zsortfunc = nansafe(self._zsort_functions[zsort]) + self._zsortfunc = self._zsort_functions[zsort] self._sort_zpos = None self.stale = True + def _zsortval(self, zs): + nans = np.isnan(zs) + return np.inf if nans.all() else self._zsortfunc(zs[~nans]) + def get_vector(self, segments3d): """Optimize points for projection.""" if len(segments3d): @@ -821,7 +819,7 @@ def do_3d_projection(self, renderer=None): if xyzlist: # sort by depth (furthest drawn first) z_segments_2d = sorted( - ((self._zsortfunc(zs), np.column_stack([xs, ys]), fc, ec, idx) + ((self._zsortval(zs), np.column_stack([xs, ys]), fc, ec, idx) for idx, ((xs, ys, zs), fc, ec) in enumerate(zip(xyzlist, cface, cedge))), key=lambda x: x[0], reverse=True) From b48fc6d79a44687a08296b689a3ea1b7e22b01e7 Mon Sep 17 00:00:00 2001 From: Tom Neep Date: Thu, 22 Jul 2021 12:34:29 +0100 Subject: [PATCH 4/4] Add docstring to _zsortval --- lib/mpl_toolkits/mplot3d/art3d.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/mpl_toolkits/mplot3d/art3d.py b/lib/mpl_toolkits/mplot3d/art3d.py index e39eb346bde1..f206213e9d65 100644 --- a/lib/mpl_toolkits/mplot3d/art3d.py +++ b/lib/mpl_toolkits/mplot3d/art3d.py @@ -738,6 +738,14 @@ def set_zsort(self, zsort): self.stale = True def _zsortval(self, zs): + """ + Compute the value to use for z-sorting given the viewer z + coordinates of an object `zs`, with larger values drawn underneath + smaller values. + + This function should never return `nan`, and returns `np.inf` if no + non-nan value is computable. + """ nans = np.isnan(zs) return np.inf if nans.all() else self._zsortfunc(zs[~nans])