@@ -1558,14 +1558,12 @@ def draw(self, renderer):
15581558 calculation much easier than doing rotated ellipse
15591559 intersection directly).
15601560
1561- This uses the "line intersecting a circle" algorithm
1562- from:
1561+ This uses the "line intersecting a circle" algorithm from:
15631562
15641563 Vince, John. *Geometry for Computer Graphics: Formulae,
15651564 Examples & Proofs.* London: Springer-Verlag, 2005.
15661565
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.
15691567
15701568 3. Proceeding counterclockwise starting in the positive
15711569 x-direction, each of the visible arc-segments between the
@@ -1598,7 +1596,7 @@ def theta_stretch(theta, scale):
15981596 self ._path = Path .arc (theta1 , theta2 )
15991597 return Patch .draw (self , renderer )
16001598
1601- def iter_circle_intersect_on_line (x0 , y0 , x1 , y1 ):
1599+ def line_circle_intersect (x0 , y0 , x1 , y1 ):
16021600 dx = x1 - x0
16031601 dy = y1 - y0
16041602 dr2 = dx * dx + dy * dy
@@ -1610,7 +1608,7 @@ def iter_circle_intersect_on_line(x0, y0, x1, y1):
16101608 if discrim == 0.0 :
16111609 x = (D * dy ) / dr2
16121610 y = (- D * dx ) / dr2
1613- yield x , y
1611+ return np . array ([[ x , y ]])
16141612 elif discrim > 0.0 :
16151613 # The definition of "sign" here is different from
16161614 # np.sign: we never want to get 0.0
@@ -1619,12 +1617,15 @@ def iter_circle_intersect_on_line(x0, y0, x1, y1):
16191617 else :
16201618 sign_dy = 1.0
16211619 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 .array (
1621+ [[D * dy + sign_dy * dx * sqrt_discrim / dr2 ,
1622+ - D * dx + abs (dy ) * sqrt_discrim / dr2 ],
1623+ [D * dy - sign_dy * dx * sqrt_discrim / dr2 ,
1624+ - D * dx - abs (dy ) * sqrt_discrim / dr2 ]])
1625+ else :
1626+ return np .empty ((0 , 2 ))
16261627
1627- def iter_circle_intersect_on_line_seg (x0 , y0 , x1 , y1 ):
1628+ def segment_circle_intersect (x0 , y0 , x1 , y1 ):
16281629 epsilon = 1e-9
16291630 if x1 < x0 :
16301631 x0e , x1e = x1 , x0
@@ -1634,17 +1635,13 @@ def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
16341635 y0e , y1e = y1 , y0
16351636 else :
16361637 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
1638+ xys = line_circle_intersect (x0 , y0 , x1 , y1 )
1639+ xs , ys = xys .T
1640+ return xys [(x0e - epsilon < xs ) & (xs < x1e + epsilon )
1641+ & (y0e - epsilon < ys ) & (ys < y1e + epsilon )]
16441642
16451643 # 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.
1644+ # circle in the same way that it is relative to the desired ellipse.
16481645 box_path = Path .unit_rectangle ()
16491646 box_path_transform = transforms .BboxTransformTo (self .axes .bbox ) + \
16501647 self .get_transform ().inverted ()
@@ -1653,16 +1650,10 @@ def iter_circle_intersect_on_line_seg(x0, y0, x1, y1):
16531650 thetas = set ()
16541651 # For each of the point pairs, there is a line segment
16551652 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 )
1653+ xy = segment_circle_intersect (* p0 , * p1 )
1654+ x , y = xy .T
1655+ theta = np .rad2deg (np .arctan2 (y , x ))
1656+ thetas .update (theta [(theta1 < theta ) & (theta < theta2 )])
16661657 thetas = sorted (thetas ) + [theta2 ]
16671658
16681659 last_theta = theta1
0 commit comments