diff --git a/lib/matplotlib/path.py b/lib/matplotlib/path.py index 4216f3a9e1b7..fcaf191dc04b 100644 --- a/lib/matplotlib/path.py +++ b/lib/matplotlib/path.py @@ -856,6 +856,10 @@ def arc(cls, theta1, theta2, n=None, is_wedge=False): Return an arc on the unit circle from angle *theta1* to angle *theta2* (in degrees). + *theta2* is unwrapped to produce the shortest arc within 360 degrees. + That is, if *theta2* > *theta1* + 360, the arc will be from *theta1* to + *theta2* - 360 and not a full circle plus some extra overlap. + If *n* is provided, it is the number of spline segments to make. If *n* is not provided, the number of spline segments is determined based on the delta between *theta1* and *theta2*. @@ -864,14 +868,15 @@ def arc(cls, theta1, theta2, n=None, is_wedge=False): polylines, quadratic or cubic Bezier curves `_. """ - theta1, theta2 = np.deg2rad([theta1, theta2]) - - twopi = np.pi * 2.0 halfpi = np.pi * 0.5 - eta1 = np.arctan2(np.sin(theta1), np.cos(theta1)) - eta2 = np.arctan2(np.sin(theta2), np.cos(theta2)) - eta2 -= twopi * np.floor((eta2 - eta1) / twopi) + eta1 = theta1 + eta2 = theta2 - 360 * np.floor((theta2 - theta1) / 360) + # Ensure 2pi range is not flattened to 0 due to floating-point errors, + # but don't try to expand existing 0 range. + if theta2 != theta1 and eta2 <= eta1: + eta2 += 360 + eta1, eta2 = np.deg2rad([eta1, eta2]) # number of curve segments to make if n is None: @@ -930,6 +935,10 @@ def wedge(cls, theta1, theta2, n=None): Return a wedge of the unit circle from angle *theta1* to angle *theta2* (in degrees). + *theta2* is unwrapped to produce the shortest wedge within 360 degrees. + That is, if *theta2* > *theta1* + 360, the wedge will be from *theta1* + to *theta2* - 360 and not a full circle plus some extra overlap. + If *n* is provided, it is the number of spline segments to make. If *n* is not provided, the number of spline segments is determined based on the delta between *theta1* and *theta2*. diff --git a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.pdf b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.pdf index bfb079b97af2..7f85a4fb0c90 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.pdf and b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.pdf differ diff --git a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.png b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.png index 6035d0604b3e..1c1d4c4f96fb 100644 Binary files a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.png and b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.svg b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.svg index c1fa833228ea..23a18eeee8a7 100644 --- a/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.svg +++ b/lib/matplotlib/tests/baseline_images/test_patches/wedge_range.svg @@ -27,43 +27,44 @@ z " style="fill:#ffffff;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> - +" style="fill:none;stroke:#000000;stroke-linejoin:miter;stroke-width:3;"/> +" id="m368fc901b1" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="mc63e59a608" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + @@ -288,80 +283,80 @@ L 0 4 +" id="m556f96d829" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="m27e32ca04a" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + @@ -369,8 +364,8 @@ L -4 0 - - + + diff --git a/lib/matplotlib/tests/test_path.py b/lib/matplotlib/tests/test_path.py index 31b97830375f..25635b2d8ac3 100644 --- a/lib/matplotlib/tests/test_path.py +++ b/lib/matplotlib/tests/test_path.py @@ -205,3 +205,15 @@ def test_path_deepcopy(): path2 = Path(verts, codes) copy.deepcopy(path1) copy.deepcopy(path2) + + +@pytest.mark.parametrize('offset', range(-720, 361, 45)) +def test_full_arc(offset): + low = offset + high = 360 + offset + + path = Path.arc(low, high) + mins = np.min(path.vertices, axis=0) + maxs = np.max(path.vertices, axis=0) + np.testing.assert_allclose(mins, -1) + assert np.allclose(maxs, 1)