Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd67550c

Browse files
committed
Backport PR#17564: FIX: correctly handle large arcs
Merge pull request#17564 from tacaswell/fix_big_arcFIX: big arc code path Conflicts:lib/matplotlib/patches.py - implicitly backport a change from#15356 (from `- trans ` -> `+ trans.inverted()`)
1 parentd885c0f commitd67550c

File tree

5 files changed

+632
-32
lines changed

5 files changed

+632
-32
lines changed

‎lib/matplotlib/patches.py

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,8 @@ def draw(self, renderer):
16071607
"""
16081608
ifnothasattr(self,'axes'):
16091609
raiseRuntimeError('Arcs can only be used in Axes instances')
1610+
ifnotself.get_visible():
1611+
return
16101612

16111613
self._recompute_transform()
16121614

@@ -1619,14 +1621,40 @@ def theta_stretch(theta, scale):
16191621
theta=np.deg2rad(theta)
16201622
x=np.cos(theta)
16211623
y=np.sin(theta)
1622-
returnnp.rad2deg(np.arctan2(scale*y,x))
1623-
theta1=theta_stretch(self.theta1,width/height)
1624-
theta2=theta_stretch(self.theta2,width/height)
1625-
1626-
# Get width and height in pixels
1627-
width,height=self.get_transform().transform((width,height))
1624+
stheta=np.rad2deg(np.arctan2(scale*y,x))
1625+
# arctan2 has the range [-pi, pi], we expect [0, 2*pi]
1626+
return (stheta+360)%360
1627+
1628+
theta1=self.theta1
1629+
theta2=self.theta2
1630+
1631+
if (
1632+
# if we need to stretch the angles because we are distorted
1633+
width!=height
1634+
# and we are not doing a full circle.
1635+
#
1636+
# 0 and 360 do not exactly round-trip through the angle
1637+
# stretching (due to both float precision limitations and
1638+
# the difference between the range of arctan2 [-pi, pi] and
1639+
# this method [0, 360]) so avoid doing it if we don't have to.
1640+
andnot (theta1!=theta2andtheta1%360==theta2%360)
1641+
):
1642+
theta1=theta_stretch(self.theta1,width/height)
1643+
theta2=theta_stretch(self.theta2,width/height)
1644+
1645+
# Get width and height in pixels we need to use
1646+
# `self.get_data_transform` rather than `self.get_transform`
1647+
# because we want the transform from dataspace to the
1648+
# screen space to estimate how big the arc will be in physical
1649+
# units when rendered (the transform that we get via
1650+
# `self.get_transform()` goes from an idealized unit-radius
1651+
# space to screen space).
1652+
data_to_screen_trans=self.get_data_transform()
1653+
pwidth,pheight= (data_to_screen_trans.transform((width,height))-
1654+
data_to_screen_trans.transform((0,0)))
16281655
inv_error= (1.0/1.89818e-6)*0.5
1629-
ifwidth<inv_errorandheight<inv_error:
1656+
1657+
ifpwidth<inv_errorandpheight<inv_error:
16301658
self._path=Path.arc(theta1,theta2)
16311659
returnPatch.draw(self,renderer)
16321660

@@ -1660,29 +1688,32 @@ def segment_circle_intersect(x0, y0, x1, y1):
16601688
y0e,y1e=y0,y1
16611689
xys=line_circle_intersect(x0,y0,x1,y1)
16621690
xs,ys=xys.T
1663-
returnxys[(x0e-epsilon<xs)& (xs<x1e+epsilon)
1664-
& (y0e-epsilon<ys)& (ys<y1e+epsilon)]
1691+
returnxys[
1692+
(x0e-epsilon<xs)& (xs<x1e+epsilon)
1693+
& (y0e-epsilon<ys)& (ys<y1e+epsilon)
1694+
]
16651695

16661696
# Transforms the axes box_path so that it is relative to the unit
16671697
# circle in the same way that it is relative to the desired ellipse.
1668-
box_path=Path.unit_rectangle()
16691698
box_path_transform= (transforms.BboxTransformTo(self.axes.bbox)
1670-
-self.get_transform())
1671-
box_path=box_path.transformed(box_path_transform)
1699+
+self.get_transform().inverted())
1700+
box_path=Path.unit_rectangle().transformed(box_path_transform)
16721701

16731702
thetas=set()
16741703
# For each of the point pairs, there is a line segment
16751704
forp0,p1inzip(box_path.vertices[:-1],box_path.vertices[1:]):
16761705
xy=segment_circle_intersect(*p0,*p1)
16771706
x,y=xy.T
1678-
theta=np.rad2deg(np.arctan2(y,x))
1707+
# arctan2 return [-pi, pi), the rest of our angles are in
1708+
# [0, 360], adjust as needed.
1709+
theta= (np.rad2deg(np.arctan2(y,x))+360)%360
16791710
thetas.update(theta[(theta1<theta)& (theta<theta2)])
16801711
thetas=sorted(thetas)+ [theta2]
1681-
16821712
last_theta=theta1
16831713
theta1_rad=np.deg2rad(theta1)
1684-
inside=box_path.contains_point((np.cos(theta1_rad),
1685-
np.sin(theta1_rad)))
1714+
inside=box_path.contains_point(
1715+
(np.cos(theta1_rad),np.sin(theta1_rad))
1716+
)
16861717

16871718
# save original path
16881719
path_original=self._path
Loading

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp