@@ -1558,14 +1558,12 @@ def draw(self, renderer):
1558
1558
calculation much easier than doing rotated ellipse
1559
1559
intersection directly).
1560
1560
1561
- This uses the "line intersecting a circle" algorithm
1562
- from:
1561
+ This uses the "line intersecting a circle" algorithm from:
1563
1562
1564
1563
Vince, John. *Geometry for Computer Graphics: Formulae,
1565
1564
Examples & Proofs.* London: Springer-Verlag, 2005.
1566
1565
1567
- 2. The angles of each of the intersection points are
1568
- calculated.
1566
+ 2. The angles of each of the intersection points are calculated.
1569
1567
1570
1568
3. Proceeding counterclockwise starting in the positive
1571
1569
x-direction, each of the visible arc-segments between the
@@ -1598,7 +1596,7 @@ def theta_stretch(theta, scale):
1598
1596
self ._path = Path .arc (theta1 , theta2 )
1599
1597
return Patch .draw (self , renderer )
1600
1598
1601
- def iter_circle_intersect_on_line (x0 , y0 , x1 , y1 ):
1599
+ def line_circle_intersect (x0 , y0 , x1 , y1 ):
1602
1600
dx = x1 - x0
1603
1601
dy = y1 - y0
1604
1602
dr2 = dx * dx + dy * dy
@@ -1610,7 +1608,7 @@ def iter_circle_intersect_on_line(x0, y0, x1, y1):
1610
1608
if discrim == 0.0 :
1611
1609
x = (D * dy ) / dr2
1612
1610
y = (- D * dx ) / dr2
1613
- yield x , y
1611
+ return np . array ([[ x , y ]])
1614
1612
elif discrim > 0.0 :
1615
1613
# The definition of "sign" here is different from
1616
1614
# np.sign: we never want to get 0.0
@@ -1619,12 +1617,14 @@ def iter_circle_intersect_on_line(x0, y0, x1, y1):
1619
1617
else :
1620
1618
sign_dy = 1.0
1621
1619
sqrt_discrim = np .sqrt (discrim )
1622
- for sign in (1. , - 1. ):
1623
- x = (D * dy + sign * sign_dy * dx * sqrt_discrim ) / dr2
1624
- y = (- D * dx + sign * np .abs (dy ) * sqrt_discrim ) / dr2
1625
- yield x , y
1620
+ return np .row_stack (
1621
+ [[(D * dy + sign * sign_dy * dx * sqrt_discrim ) / dr2 ,
1622
+ (- D * dx + sign * np .abs (dy ) * sqrt_discrim ) / dr2 ]
1623
+ for sign in [1 , - 1 ]])
1624
+ else :
1625
+ return np .empty ((0 , 2 ))
1626
1626
1627
- def iter_circle_intersect_on_line_seg (x0 , y0 , x1 , y1 ):
1627
+ def segment_circle_intersect (x0 , y0 , x1 , y1 ):
1628
1628
epsilon = 1e-9
1629
1629
if x1 < x0 :
1630
1630
x0e , x1e = x1 , x0
@@ -1634,17 +1634,13 @@ def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
1634
1634
y0e , y1e = y1 , y0
1635
1635
else :
1636
1636
y0e , y1e = y0 , y1
1637
- x0e -= epsilon
1638
- y0e -= epsilon
1639
- x1e += epsilon
1640
- y1e += epsilon
1641
- for x , y in iter_circle_intersect_on_line (x0 , y0 , x1 , y1 ):
1642
- if x0e <= x <= x1e and y0e <= y <= y1e :
1643
- yield x , y
1637
+ xys = line_circle_intersect (x0 , y0 , x1 , y1 )
1638
+ xs , ys = xys .T
1639
+ return xys [(x0e - epsilon < xs ) & (xs < x1e + epsilon )
1640
+ & (y0e - epsilon < ys ) & (ys < y1e + epsilon )]
1644
1641
1645
1642
# Transforms the axes box_path so that it is relative to the unit
1646
- # circle in the same way that it is relative to the desired
1647
- # ellipse.
1643
+ # circle in the same way that it is relative to the desired ellipse.
1648
1644
box_path = Path .unit_rectangle ()
1649
1645
box_path_transform = transforms .BboxTransformTo (self .axes .bbox ) + \
1650
1646
self .get_transform ().inverted ()
@@ -1653,16 +1649,10 @@ def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
1653
1649
thetas = set ()
1654
1650
# For each of the point pairs, there is a line segment
1655
1651
for p0 , p1 in zip (box_path .vertices [:- 1 ], box_path .vertices [1 :]):
1656
- x0 , y0 = p0
1657
- x1 , y1 = p1
1658
- for x , y in iter_circle_intersect_on_line_seg (x0 , y0 , x1 , y1 ):
1659
- theta = np .arccos (x )
1660
- if y < 0 :
1661
- theta = 2 * np .pi - theta
1662
- # Convert radians to angles
1663
- theta = np .rad2deg (theta )
1664
- if theta1 < theta < theta2 :
1665
- thetas .add (theta )
1652
+ xy = segment_circle_intersect (* p0 , * p1 )
1653
+ x , y = xy .T
1654
+ theta = np .rad2deg (np .arctan2 (y , x ))
1655
+ thetas .update (theta [(theta1 < theta ) & (theta < theta2 )])
1666
1656
thetas = sorted (thetas ) + [theta2 ]
1667
1657
1668
1658
last_theta = theta1
0 commit comments