Title: [Bug]: numerical instability of Path.arc for 0 degree or 360 degree arc · Issue #29953 · matplotlib/matplotlib · GitHub
Open Graph Title: [Bug]: numerical instability of Path.arc for 0 degree or 360 degree arc · Issue #29953 · matplotlib/matplotlib
X Title: [Bug]: numerical instability of Path.arc for 0 degree or 360 degree arc · Issue #29953 · matplotlib/matplotlib
Description: Bug summary Trying to create an arc path of 0/360 degrees sometimes results in one of 360/0 degrees due to floating point weirdness. Code for reproduction from matplotlib import patches, path, pyplot fig, ax = pyplot.subplots(ncols=3) ax...
Open Graph Description: Bug summary Trying to create an arc path of 0/360 degrees sometimes results in one of 360/0 degrees due to floating point weirdness. Code for reproduction from matplotlib import patches, path, pypl...
X Description: Bug summary Trying to create an arc path of 0/360 degrees sometimes results in one of 360/0 degrees due to floating point weirdness. Code for reproduction from matplotlib import patches, path, pypl...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/29953
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"[Bug]: numerical instability of Path.arc for 0 degree or 360 degree arc","articleBody":"### Bug summary\n\nTrying to create an arc path of 0/360 degrees sometimes results in one of 360/0 degrees due to floating point weirdness.\n\n### Code for reproduction\n\n```Python\nfrom matplotlib import patches, path, pyplot\n\nfig, ax = pyplot.subplots(ncols=3)\nax[0].add_patch(patches.PathPatch(path.Path.arc(theta1=-90 - 1e-14, theta2=270)))\nax[0].set_title(\"arc(-90-1e-14, 270), should be a circle\")\nax[1].add_patch(patches.PathPatch(path.Path.arc(theta1=-90, theta2=270)))\nax[1].set_title(\"arc(-90, 270), is a circle\")\nax[2].add_patch(patches.PathPatch(path.Path.arc(theta1=-90, theta2=-90 - 1e-14)))\nax[2].set_title(\"arc(-90, -90-1e-14), should not be a circle\")\nfor a in ax:\n a.set_xlim(-1, 1)\n a.set_ylim(-1, 1)\n a.set_aspect(\"equal\")\npyplot.show()\n```\n\n### Actual outcome\n\n\n\n### Expected outcome\n\nI expect the first plot to be a circle, identical to the second.\nI expect the third plot to be empty\n\n### Additional information\n\nThe location of the bug is not hard to find:\nhttps://github.com/matplotlib/matplotlib/blob/6fc8169112a42e3f6f55793a6b56159cd8ff69d7/lib/matplotlib/path.py#L951-L956\n\nAt runtime the first example becomes `(-90 \u003c= -90 - 1e-14) == False`, which therefore skips the `+360` bump.\n\nWhat is much harder is to understand is what the intention is here.\nIf you can help me to understand what behaviour you'd like, I'd be happy to put together a PR for it.\n\nI think `theta2 \u003c theta1` always gives an unexpected result:\n- The docstring does not clarify what should happen, therefore my assumption is that it should return an anti-clockwise arc\n- The `np.floor` will mean it becomes the angle range [theta1, theta2+360], which gives the third plot which I believe should not be a circle\n- The special casing only treats `eta2 += 360`, not `eta2 -= 360`\n\nIt would be great if either the docstring could be clarified or a `ValueError` raised on unexpected inputs here.\n\n### Operating system\n\n_No response_\n\n### Matplotlib Version\n\n3.10.0\n\n### Matplotlib Backend\n\n_No response_\n\n### Python version\n\n_No response_\n\n### Jupyter version\n\n_No response_\n\n### Installation\n\npip","author":{"url":"https://github.com/robtovey","@type":"Person","name":"robtovey"},"datePublished":"2025-04-21T05:13:04.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":13},"url":"https://github.com/29953/matplotlib/issues/29953"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:c9db55da-f374-426b-de7e-8aa221f80717 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E9E6:369908:190FB:221DC:6A52550B |
| html-safe-nonce | 38330cd8bb4fb2ae8317723883f6c5e85a8b06add4c1a69cce921cd5dbd8c2e5 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFOUU2OjM2OTkwODoxOTBGQjoyMjFEQzo2QTUyNTUwQiIsInZpc2l0b3JfaWQiOiI4OTgzNjY2NzAxMjEzMjU5MDE5IiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | 8baaaada08d90b2b7f10dfe4199271cdbf71e161f228c37b00e994f1c4af0884 |
| hovercard-subject-tag | issue:3007579163 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/matplotlib/matplotlib/29953/issue_layout |
| twitter:image | https://opengraph.githubassets.com/bcec10ed161083265d60aeb75835bf8d22ec78641db632d73050012ed74de2c8/matplotlib/matplotlib/issues/29953 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/bcec10ed161083265d60aeb75835bf8d22ec78641db632d73050012ed74de2c8/matplotlib/matplotlib/issues/29953 |
| og:image:alt | Bug summary Trying to create an arc path of 0/360 degrees sometimes results in one of 360/0 degrees due to floating point weirdness. Code for reproduction from matplotlib import patches, path, pypl... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | robtovey |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| go-import | github.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 1385122 |
| octolytics-dimension-repository_nwo | matplotlib/matplotlib |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1385122 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/matplotlib |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width