@@ -949,36 +949,73 @@ def unit_circle_righthalf(cls):
949
949
return cls ._unit_circle_righthalf
950
950
951
951
@classmethod
952
- def arc (cls , theta1 , theta2 , n = None , is_wedge = False ):
952
+ def arc (cls , theta1 , theta2 , n = None , is_wedge = False , wrap = True ):
953
953
"""
954
- Return a `Path` for the unit circle arc from angles *theta1* to
955
- *theta2* (in degrees).
954
+ Return a `Path` for a counter-clockwise unit circle arc from angles
955
+ *theta1* to * theta2* (in degrees).
956
956
957
- *theta2* is unwrapped to produce the shortest arc within 360 degrees.
958
- That is, if *theta2* > *theta1* + 360, the arc will be from *theta1* to
959
- *theta2* - 360 and not a full circle plus some extra overlap.
960
-
961
- If *n* is provided, it is the number of spline segments to make.
962
- If *n* is not provided, the number of spline segments is
963
- determined based on the delta between *theta1* and *theta2*.
957
+ Parameters
958
+ ----------
959
+ theta1, theta2 : float
960
+ The angles (in degrees) defining the start (*theta1*) and end
961
+ (*theta2*) of the arc. If the arc spans more than 360 degrees, it
962
+ will be wrapped to fit within the range from *theta1* to *theta1* +
963
+ 360, provided *wrap* is True. The arc is drawn counter-clockwise
964
+ from *theta1* to *theta2*. For instance, if *theta1* =90 and
965
+ *theta2* = 70, the resulting arc will span 320 degrees.
966
+
967
+ n : int, optional
968
+ The number of spline segments to make. If not provided, the number
969
+ of spline segments is determined based on the delta between
970
+ *theta1* and *theta2*.
971
+
972
+ is_wedge : bool, default: False
973
+ If True, the arc is a wedge. The first vertex is the center of the
974
+ wedge, the second vertex is the start of the arc, and the last
975
+ vertex is the end of the arc. The wedge is closed with a line
976
+ segment to the center of the wedge. If False, the arc is a
977
+ polyline. The first vertex is the start of the arc, and the last
978
+ vertex is the end of the arc. The arc is closed with a line
979
+ segment to the start of the arc. The wedge is not closed with a
980
+ line segment to the start of the arc.
981
+
982
+ wrap : bool, default: True
983
+ If True, the arc is wrapped to fit between *theta1* and *theta1* +
984
+ 360 degrees. If False, the arc is not wrapped. The arc will be
985
+ drawn from *theta1* to *theta2*.
964
986
965
- Masionobe, L. 2003. `Drawing an elliptical arc using
966
- polylines, quadratic or cubic Bezier curves
987
+ Notes
988
+ -----
989
+ The arc is approximated using cubic Bézier curves, as described in
990
+ Masionobe, L. 2003. `Drawing an elliptical arc using polylines,
991
+ quadratic or cubic Bezier curves
967
992
<https://web.archive.org/web/20190318044212/http://www.spaceroots.org/documents/ellipse/index.html>`_.
968
993
"""
969
- halfpi = np .pi * 0.5
970
994
971
995
eta1 = theta1
972
- eta2 = theta2 - 360 * np .floor ((theta2 - theta1 ) / 360 )
973
- # Ensure 2pi range is not flattened to 0 due to floating-point errors,
974
- # but don't try to expand existing 0 range.
975
- if theta2 != theta1 and eta2 <= eta1 :
976
- eta2 += 360
996
+ if wrap :
997
+ # Wrap theta2 to 0-360 degrees from theta1.
998
+ eta2 = np .mod (theta2 - theta1 , 360.0 ) + theta1
999
+ print ('Eta1, Eta20' , eta1 , eta2 )
1000
+ # Ensure 360-deg range is not flattened to 0 due to floating-point
1001
+ # errors, but don't try to expand existing 0 range.
1002
+ if theta2 != theta1 and eta2 <= eta1 :
1003
+ eta2 += 360
1004
+ print ('Eta1, Eta2' , eta1 , eta2 )
1005
+ else :
1006
+ eta2 = theta2
977
1007
eta1 , eta2 = np .deg2rad ([eta1 , eta2 ])
978
1008
979
1009
# number of curve segments to make
980
1010
if n is None :
981
- n = int (2 ** np .ceil ((eta2 - eta1 ) / halfpi ))
1011
+ if np .abs (eta2 - eta1 ) <= 2.2 * np .pi :
1012
+ # this doesn't need to grow exponentially, but we have left
1013
+ # this way for back compatibility
1014
+ n = int (2 ** np .ceil (2 * np .abs (eta2 - eta1 ) / np .pi ))
1015
+ print ('Here' )
1016
+ else :
1017
+ # this will not grow exponentially if we allow wrapping arcs:
1018
+ n = int (2 * np .ceil (2 * np .abs (eta2 - eta1 ) / np .pi ))
982
1019
if n < 1 :
983
1020
raise ValueError ("n must be >= 1 or None" )
984
1021
@@ -1028,22 +1065,32 @@ def arc(cls, theta1, theta2, n=None, is_wedge=False):
1028
1065
return cls (vertices , codes , readonly = True )
1029
1066
1030
1067
@classmethod
1031
- def wedge (cls , theta1 , theta2 , n = None ):
1068
+ def wedge (cls , theta1 , theta2 , n = None , wrap = True ):
1032
1069
"""
1033
- Return a `Path` for the unit circle wedge from angles *theta1* to
1034
- *theta2* (in degrees).
1035
-
1036
- *theta2* is unwrapped to produce the shortest wedge within 360 degrees.
1037
- That is, if *theta2* > *theta1* + 360, the wedge will be from *theta1*
1038
- to *theta2* - 360 and not a full circle plus some extra overlap.
1039
-
1040
- If *n* is provided, it is the number of spline segments to make.
1041
- If *n* is not provided, the number of spline segments is
1042
- determined based on the delta between *theta1* and *theta2*.
1070
+ Return a `Path` for a counter-clockwise unit circle wedge from angles
1071
+ *theta1* to *theta2* (in degrees).
1043
1072
1044
- See `Path.arc` for the reference on the approximation used.
1045
- """
1046
- return cls .arc (theta1 , theta2 , n , True )
1073
+ Parameters
1074
+ ----------
1075
+ theta1, theta2 : float
1076
+ The angles (in degrees) defining the start (*theta1*) and end
1077
+ (*theta2*) of the arc. If the arc spans more than 360 degrees, it
1078
+ will be wrapped to fit within the range from *theta1* to *theta1* +
1079
+ 360, provided *wrap* is True. The arc is drawn counter-clockwise
1080
+ from *theta1* to *theta2*. For instance, if *theta1* =90 and
1081
+ *theta2* = 70, the resulting arc will span 320 degrees.
1082
+
1083
+ n : int, optional
1084
+ The number of spline segments to make. If not provided, the number
1085
+ of spline segments is determined based on the delta between
1086
+ *theta1* and *theta2*.
1087
+
1088
+ wrap : bool, default: True
1089
+ If True, the arc is wrapped to fit between *theta1* and *theta1* +
1090
+ 360 degrees. If False, the arc is not wrapped. The arc will be
1091
+ drawn from *theta1* to *theta2*.
1092
+ """
1093
+ return cls .arc (theta1 , theta2 , n , wedge = True , wrap = wrap )
1047
1094
1048
1095
@staticmethod
1049
1096
@lru_cache (8 )
0 commit comments