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

Skip to content

Commit 31e26cc

Browse files
authored
Merge pull request #17564 from tacaswell/fix_big_arc
FIX: big arc code path
2 parents d479a91 + 0dfdfd6 commit 31e26cc

5 files changed

Lines changed: 631 additions & 31 deletions

File tree

lib/matplotlib/patches.py

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,8 @@ def draw(self, renderer):
16471647
"""
16481648
if not hasattr(self, 'axes'):
16491649
raise RuntimeError('Arcs can only be used in Axes instances')
1650+
if not self.get_visible():
1651+
return
16501652

16511653
self._recompute_transform()
16521654

@@ -1659,14 +1661,40 @@ def theta_stretch(theta, scale):
16591661
theta = np.deg2rad(theta)
16601662
x = np.cos(theta)
16611663
y = np.sin(theta)
1662-
return np.rad2deg(np.arctan2(scale * y, x))
1663-
theta1 = theta_stretch(self.theta1, width / height)
1664-
theta2 = theta_stretch(self.theta2, width / height)
1665-
1666-
# Get width and height in pixels
1667-
width, height = self.get_transform().transform((width, height))
1664+
stheta = np.rad2deg(np.arctan2(scale * y, x))
1665+
# arctan2 has the range [-pi, pi], we expect [0, 2*pi]
1666+
return (stheta + 360) % 360
1667+
1668+
theta1 = self.theta1
1669+
theta2 = self.theta2
1670+
1671+
if (
1672+
# if we need to stretch the angles because we are distorted
1673+
width != height
1674+
# and we are not doing a full circle.
1675+
#
1676+
# 0 and 360 do not exactly round-trip through the angle
1677+
# stretching (due to both float precision limitations and
1678+
# the difference between the range of arctan2 [-pi, pi] and
1679+
# this method [0, 360]) so avoid doing it if we don't have to.
1680+
and not (theta1 != theta2 and theta1 % 360 == theta2 % 360)
1681+
):
1682+
theta1 = theta_stretch(self.theta1, width / height)
1683+
theta2 = theta_stretch(self.theta2, width / height)
1684+
1685+
# Get width and height in pixels we need to use
1686+
# `self.get_data_transform` rather than `self.get_transform`
1687+
# because we want the transform from dataspace to the
1688+
# screen space to estimate how big the arc will be in physical
1689+
# units when rendered (the transform that we get via
1690+
# `self.get_transform()` goes from an idealized unit-radius
1691+
# space to screen space).
1692+
data_to_screen_trans = self.get_data_transform()
1693+
pwidth, pheight = (data_to_screen_trans.transform((width, height)) -
1694+
data_to_screen_trans.transform((0, 0)))
16681695
inv_error = (1.0 / 1.89818e-6) * 0.5
1669-
if width < inv_error and height < inv_error:
1696+
1697+
if pwidth < inv_error and pheight < inv_error:
16701698
self._path = Path.arc(theta1, theta2)
16711699
return Patch.draw(self, renderer)
16721700

@@ -1700,29 +1728,32 @@ def segment_circle_intersect(x0, y0, x1, y1):
17001728
y0e, y1e = y0, y1
17011729
xys = line_circle_intersect(x0, y0, x1, y1)
17021730
xs, ys = xys.T
1703-
return xys[(x0e - epsilon < xs) & (xs < x1e + epsilon)
1704-
& (y0e - epsilon < ys) & (ys < y1e + epsilon)]
1731+
return xys[
1732+
(x0e - epsilon < xs) & (xs < x1e + epsilon)
1733+
& (y0e - epsilon < ys) & (ys < y1e + epsilon)
1734+
]
17051735

17061736
# Transforms the axes box_path so that it is relative to the unit
17071737
# circle in the same way that it is relative to the desired ellipse.
1708-
box_path = Path.unit_rectangle()
17091738
box_path_transform = (transforms.BboxTransformTo(self.axes.bbox)
17101739
+ self.get_transform().inverted())
1711-
box_path = box_path.transformed(box_path_transform)
1740+
box_path = Path.unit_rectangle().transformed(box_path_transform)
17121741

17131742
thetas = set()
17141743
# For each of the point pairs, there is a line segment
17151744
for p0, p1 in zip(box_path.vertices[:-1], box_path.vertices[1:]):
17161745
xy = segment_circle_intersect(*p0, *p1)
17171746
x, y = xy.T
1718-
theta = np.rad2deg(np.arctan2(y, x))
1747+
# arctan2 return [-pi, pi), the rest of our angles are in
1748+
# [0, 360], adjust as needed.
1749+
theta = (np.rad2deg(np.arctan2(y, x)) + 360) % 360
17191750
thetas.update(theta[(theta1 < theta) & (theta < theta2)])
17201751
thetas = sorted(thetas) + [theta2]
1721-
17221752
last_theta = theta1
17231753
theta1_rad = np.deg2rad(theta1)
1724-
inside = box_path.contains_point((np.cos(theta1_rad),
1725-
np.sin(theta1_rad)))
1754+
inside = box_path.contains_point(
1755+
(np.cos(theta1_rad), np.sin(theta1_rad))
1756+
)
17261757

17271758
# save original path
17281759
path_original = self._path
-152 Bytes
Loading

0 commit comments

Comments
 (0)