@@ -408,10 +408,14 @@ def unit_circle(cls):
408408 unit_circle = classmethod (unit_circle )
409409
410410 #@classmethod
411- def arc (cls , theta1 , theta2 , is_wedge = False ):
411+ def arc (cls , theta1 , theta2 , is_wedge = False , n = None ):
412412 """
413413 Returns an arc on the unit circle from angle theta1 to angle
414414 theta2 (in degrees).
415+
416+ If n is provided, it is the number of spline segments to make.
417+ If n is not provided, the number of spline segments is determined
418+ based on the delta between theta1 and theta2.
415419 """
416420 # From Masionobe, L. 2003. "Drawing an elliptical arc using
417421 # polylines, quadratic or cubic Bezier curves".
@@ -422,7 +426,7 @@ def arc(cls, theta1, theta2, is_wedge=False):
422426 theta1 *= math .pi / 180.0
423427 theta2 *= math .pi / 180.0
424428
425- twopi = math .pi * 2.0
429+ twopi = math .pi * 2.0
426430 halfpi = math .pi * 0.5
427431
428432 eta1 = math .atan2 (math .sin (theta1 ), math .cos (theta1 ))
@@ -432,7 +436,8 @@ def arc(cls, theta1, theta2, is_wedge=False):
432436 eta2 += twopi
433437
434438 # number of curve segments to make
435- n = int (2 ** math .ceil ((eta2 - eta1 ) / halfpi ))
439+ if n is None :
440+ n = int (2 ** math .ceil ((eta2 - eta1 ) / halfpi ))
436441
437442 deta = (eta2 - eta1 ) / n
438443 etaB = eta1
@@ -450,40 +455,41 @@ def arc(cls, theta1, theta2, is_wedge=False):
450455 codes = Path .CURVE4 * npy .ones ((length , ), Path .code_type )
451456 vertices [1 ] = [xB , yB ]
452457 codes [0 :2 ] = [Path .MOVETO , Path .LINETO ]
458+ codes [- 2 :] = [Path .LINETO , Path .CLOSEPOLY ]
453459 vertex_offset = 2
460+ end = length - 2
454461 else :
455462 length = n * 3 + 1
456463 vertices = npy .zeros ((length , 2 ), npy .float_ )
457464 codes = Path .CURVE4 * npy .ones ((length , ), Path .code_type )
458465 vertices [0 ] = [xB , yB ]
459466 codes [0 ] = Path .MOVETO
460467 vertex_offset = 1
468+ end = length
461469
462470 t = math .tan (0.5 * deta )
463471 alpha = math .sin (deta ) * (math .sqrt (4.0 + 3.0 * t * t ) - 1 ) / 3.0
464472
465- for i in xrange (n ):
466- xA = xB
467- yA = yB
468- xA_dot = xB_dot
469- yA_dot = yB_dot
470-
471- etaB += deta
472- cos_etaB = math .cos (etaB )
473- sin_etaB = math .sin (etaB )
474- xB = cos_etaB
475- yB = sin_etaB
476- xB_dot = - sin_etaB
477- yB_dot = cos_etaB
478-
479- offset = i * 3 + vertex_offset
480- vertices [offset :offset + 3 ] = [
481- [xA + alpha * xA_dot , yA + alpha * yA_dot ],
482- [xB - alpha * xB_dot , yB - alpha * yB_dot ],
483- [xB , yB ]]
484-
485- if is_wedge :
486- codes [- 2 :] = [Path .LINETO , Path .CLOSEPOLY ]
473+ steps = npy .linspace (eta1 , eta2 , n + 1 , True )
474+ cos_eta = npy .cos (steps )
475+ sin_eta = npy .sin (steps )
476+
477+ xA = cos_eta [:- 1 ]
478+ yA = sin_eta [:- 1 ]
479+ xA_dot = - yA
480+ yA_dot = xA
481+
482+ xB = cos_eta [1 :]
483+ yB = sin_eta [1 :]
484+ xB_dot = - yB
485+ yB_dot = xB
486+
487+ vertices [vertex_offset :end :3 , 0 ] = xA + alpha * xA_dot
488+ vertices [vertex_offset :end :3 , 1 ] = yA + alpha * yA_dot
489+ vertices [vertex_offset + 1 :end :3 , 0 ] = xB - alpha * xB_dot
490+ vertices [vertex_offset + 1 :end :3 , 1 ] = yB - alpha * yB_dot
491+ vertices [vertex_offset + 2 :end :3 , 0 ] = xB
492+ vertices [vertex_offset + 2 :end :3 , 1 ] = yB
487493
488494 return Path (vertices , codes )
489495 arc = classmethod (arc )
0 commit comments