{"id":19097240,"url":"https://github.com/lycantropos/clipping","last_synced_at":"2025-04-30T14:30:23.383Z","repository":{"id":62562705,"uuid":"240798656","full_name":"lycantropos/clipping","owner":"lycantropos","description":"Segments \u0026 polygons clipping","archived":false,"fork":false,"pushed_at":"2023-05-15T21:40:33.000Z","size":820,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-19T04:41:20.032Z","etag":null,"topics":["martinez-algorithm","polygon-boolean","polygon-clipping","polygon-clipping-algorithm"],"latest_commit_sha":null,"homepage":"https://clip.rtfd.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lycantropos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-02-15T22:47:05.000Z","updated_at":"2024-12-23T18:01:41.000Z","dependencies_parsed_at":"2025-04-18T16:55:16.688Z","dependency_job_id":"4d296ae7-02d9-4536-a724-428ba88c84f2","html_url":"https://github.com/lycantropos/clipping","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Fclipping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Fclipping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Fclipping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Fclipping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lycantropos","download_url":"https://codeload.github.com/lycantropos/clipping/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251721380,"owners_count":21632827,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["martinez-algorithm","polygon-boolean","polygon-clipping","polygon-clipping-algorithm"],"created_at":"2024-11-09T03:39:32.670Z","updated_at":"2025-04-30T14:30:23.336Z","avatar_url":"https://github.com/lycantropos.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"clipping\n========\n\n[![](https://github.com/lycantropos/clipping/workflows/CI/badge.svg)](https://github.com/lycantropos/clipping/actions/workflows/ci.yml \"Github Actions\")\n[![](https://readthedocs.org/projects/clip/badge/?version=latest)](https://clip.readthedocs.io/en/latest \"Documentation\")\n[![](https://codecov.io/gh/lycantropos/clipping/branch/master/graph/badge.svg)](https://codecov.io/gh/lycantropos/clipping \"Codecov\")\n[![](https://img.shields.io/github/license/lycantropos/clipping.svg)](https://github.com/lycantropos/clipping/blob/master/LICENSE \"License\")\n[![](https://badge.fury.io/py/clipping.svg)](https://badge.fury.io/py/clipping \"PyPI\")\n\nIn what follows `python` is an alias for `python3.6` or `pypy3.6`\nor any later version (`python3.7`, `pypy3.7` and so on).\n\nInstallation\n------------\n\nInstall the latest `pip` \u0026 `setuptools` packages versions\n```bash\npython -m pip install --upgrade pip setuptools\n```\n\n### User\n\nDownload and install the latest stable version from `PyPI` repository\n```bash\npython -m pip install --upgrade clipping\n```\n\n### Developer\n\nDownload the latest version from `GitHub` repository\n```bash\ngit clone https://github.com/lycantropos/clipping.git\ncd clipping\n```\n\nInstall dependencies\n```bash\npython -m pip install -r requirements.txt\n```\n\nInstall\n```bash\npython setup.py install\n```\n\nUsage\n-----\n```python\n\u003e\u003e\u003e from ground.base import get_context\n\u003e\u003e\u003e context = get_context()\n\u003e\u003e\u003e EMPTY = context.empty\n\u003e\u003e\u003e Mix = context.mix_cls\n\u003e\u003e\u003e Multipoint = context.multipoint_cls\n\u003e\u003e\u003e Multisegment = context.multisegment_cls\n\u003e\u003e\u003e Point = context.point_cls\n\u003e\u003e\u003e Segment = context.segment_cls\n\u003e\u003e\u003e left_edge = Segment(Point(0, 0), Point(0, 1))\n\u003e\u003e\u003e right_edge = Segment(Point(1, 0), Point(1, 1))\n\u003e\u003e\u003e bottom_edge = Segment(Point(0, 0), Point(1, 0))\n\u003e\u003e\u003e top_edge = Segment(Point(0, 1), Point(1, 1))\n\u003e\u003e\u003e main_diagonal = Segment(Point(0, 0), Point(1, 1))\n\u003e\u003e\u003e trident = Multisegment([left_edge, main_diagonal, bottom_edge])\n\u003e\u003e\u003e square_edges = Multisegment([bottom_edge, right_edge, top_edge, left_edge])\n\u003e\u003e\u003e from clipping.planar import intersect_multisegments\n\u003e\u003e\u003e (intersect_multisegments(trident, square_edges)\n...  == intersect_multisegments(square_edges, trident)\n...  == Multisegment([left_edge, bottom_edge]))\nTrue\n\u003e\u003e\u003e from clipping.planar import complete_intersect_multisegments\n\u003e\u003e\u003e (complete_intersect_multisegments(trident, square_edges)\n...  == complete_intersect_multisegments(square_edges, trident)\n...  == Mix(Multipoint([Point(1, 1)]), Multisegment([left_edge, bottom_edge]),\n...         EMPTY))\nTrue\n\u003e\u003e\u003e from clipping.planar import unite_multisegments\n\u003e\u003e\u003e (unite_multisegments(trident, square_edges)\n...  == unite_multisegments(square_edges, trident)\n...  == Multisegment([left_edge, bottom_edge, main_diagonal, top_edge,\n...                   right_edge]))\nTrue\n\u003e\u003e\u003e from clipping.planar import subtract_multisegments\n\u003e\u003e\u003e subtract_multisegments(trident, square_edges) == main_diagonal\nTrue\n\u003e\u003e\u003e (subtract_multisegments(square_edges, trident)\n...  == Multisegment([top_edge, right_edge]))\nTrue\n\u003e\u003e\u003e from clipping.planar import symmetric_subtract_multisegments\n\u003e\u003e\u003e (symmetric_subtract_multisegments(trident, square_edges)\n...  == symmetric_subtract_multisegments(square_edges, trident)\n...  == Multisegment([main_diagonal, top_edge, right_edge]))\nTrue\n\u003e\u003e\u003e Contour = context.contour_cls\n\u003e\u003e\u003e Multipolygon = context.multipolygon_cls\n\u003e\u003e\u003e Polygon = context.polygon_cls\n\u003e\u003e\u003e first_square = Contour([Point(0, 0), Point(1, 0), Point(1, 1),\n...                         Point(0, 1)])\n\u003e\u003e\u003e second_square = Contour([Point(1, 0), Point(2, 0), Point(2, 1),\n...                          Point(1, 1)])\n\u003e\u003e\u003e third_square = Contour([Point(1, 1), Point(2, 1), Point(2, 2),\n...                         Point(1, 2)])\n\u003e\u003e\u003e fourth_square = Contour([Point(0, 1), Point(1, 1), Point(1, 2),\n...                          Point(0, 2)])\n\u003e\u003e\u003e from clipping.planar import intersect_multipolygons\n\u003e\u003e\u003e (intersect_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                        Polygon(third_square, [])]),\n...                          Multipolygon([Polygon(second_square, []),\n...                                        Polygon(fourth_square, [])]))\n...  is EMPTY)\nTrue\n\u003e\u003e\u003e (intersect_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                        Polygon(third_square, [])]),\n...                          Multipolygon([Polygon(first_square, []),\n...                                        Polygon(third_square, [])]))\n...  == Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\nTrue\n\u003e\u003e\u003e from clipping.planar import complete_intersect_multipolygons\n\u003e\u003e\u003e (complete_intersect_multipolygons(\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]),\n...      Multipolygon([Polygon(second_square, []),\n...                    Polygon(fourth_square, [])]))\n...  == Multisegment([Segment(Point(0, 1), Point(1, 1)),\n...                   Segment(Point(1, 0), Point(1, 1)),\n...                   Segment(Point(1, 1), Point(2, 1)),\n...                   Segment(Point(1, 1), Point(1, 2))]))\nTrue\n\u003e\u003e\u003e (complete_intersect_multipolygons(\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]),\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\n...  == Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\nTrue\n\u003e\u003e\u003e from clipping.planar import unite_multipolygons\n\u003e\u003e\u003e (unite_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                    Polygon(third_square, [])]),\n...                      Multipolygon([Polygon(second_square, []),\n...                                    Polygon(fourth_square, [])]))\n...  == Polygon(Contour([Point(0, 0), Point(2, 0), Point(2, 2), Point(0, 2)]),\n...             []))\nTrue\n\u003e\u003e\u003e (unite_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                    Polygon(third_square, [])]),\n...                      Multipolygon([Polygon(first_square, []),\n...                                    Polygon(third_square, [])]))\n...  == Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\nTrue\n\u003e\u003e\u003e from clipping.planar import subtract_multipolygons\n\u003e\u003e\u003e (subtract_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                       Polygon(third_square, [])]),\n...                         Multipolygon([Polygon(first_square, []),\n...                                       Polygon(third_square, [])]))\n...  is EMPTY)\nTrue\n\u003e\u003e\u003e (subtract_multipolygons(Multipolygon([Polygon(first_square, []),\n...                                       Polygon(third_square, [])]),\n...                         Multipolygon([Polygon(second_square, []),\n...                                       Polygon(fourth_square, [])]))\n...  == Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\nTrue\n\u003e\u003e\u003e from clipping.planar import symmetric_subtract_multipolygons\n\u003e\u003e\u003e (symmetric_subtract_multipolygons(\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]),\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]))\n...  is EMPTY)\nTrue\n\u003e\u003e\u003e (symmetric_subtract_multipolygons(\n...      Multipolygon([Polygon(first_square, []), Polygon(third_square, [])]),\n...      Multipolygon([Polygon(second_square, []),\n...                    Polygon(fourth_square, [])]))\n...  == Polygon(Contour([Point(0, 0), Point(2, 0), Point(2, 2), Point(0, 2)]),\n...             []))\nTrue\n\n```\n\nDevelopment\n-----------\n\n### Bumping version\n\n#### Preparation\n\nInstall\n[bump2version](https://github.com/c4urself/bump2version#installation).\n\n#### Pre-release\n\nChoose which version number category to bump following [semver\nspecification](http://semver.org/).\n\nTest bumping version\n```bash\nbump2version --dry-run --verbose $CATEGORY\n```\n\nwhere `$CATEGORY` is the target version number category name, possible\nvalues are `patch`/`minor`/`major`.\n\nBump version\n```bash\nbump2version --verbose $CATEGORY\n```\n\nThis will set version to `major.minor.patch-alpha`. \n\n#### Release\n\nTest bumping version\n```bash\nbump2version --dry-run --verbose release\n```\n\nBump version\n```bash\nbump2version --verbose release\n```\n\nThis will set version to `major.minor.patch`.\n\n### Running tests\n\nInstall dependencies\n```bash\npython -m pip install -r requirements-tests.txt\n```\n\nPlain\n```bash\npytest\n```\n\nInside `Docker` container:\n- with `CPython`\n  ```bash\n  docker-compose --file docker-compose.cpython.yml up\n  ```\n- with `PyPy`\n  ```bash\n  docker-compose --file docker-compose.pypy.yml up\n  ```\n\n`Bash` script:\n- with `CPython`\n  ```bash\n  ./run-tests.sh\n  ```\n  or\n  ```bash\n  ./run-tests.sh cpython\n  ```\n\n- with `PyPy`\n  ```bash\n  ./run-tests.sh pypy\n  ```\n\n`PowerShell` script:\n- with `CPython`\n  ```powershell\n  .\\run-tests.ps1\n  ```\n  or\n  ```powershell\n  .\\run-tests.ps1 cpython\n  ```\n- with `PyPy`\n  ```powershell\n  .\\run-tests.ps1 pypy\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycantropos%2Fclipping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flycantropos%2Fclipping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycantropos%2Fclipping/lists"}