{"id":16386510,"url":"https://github.com/rowanwins/sweepline-intersections","last_synced_at":"2025-04-12T16:36:26.136Z","repository":{"id":37659143,"uuid":"208019170","full_name":"rowanwins/sweepline-intersections","owner":"rowanwins","description":"A small module using a sweepline algorithm to detect intersections (\u0026 self-intersections) in polygons or polylines.","archived":false,"fork":false,"pushed_at":"2024-11-24T08:34:18.000Z","size":1354,"stargazers_count":69,"open_issues_count":2,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-05T23:26:14.892Z","etag":null,"topics":["computational-geometry","polygon","sweep-line","sweep-line-algorithm"],"latest_commit_sha":null,"homepage":"https://rowanwins.github.io/sweepline-intersections/debug/index.html","language":"JavaScript","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/rowanwins.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":"FUNDING.yml","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},"funding":{"github":["rowanwins"],"custom":["https://paypal.me/rowanwinsemius"]}},"created_at":"2019-09-12T09:56:49.000Z","updated_at":"2025-02-25T01:26:00.000Z","dependencies_parsed_at":"2024-06-18T21:23:12.005Z","dependency_job_id":"b74a9016-37e1-429c-abcf-0323e51ac926","html_url":"https://github.com/rowanwins/sweepline-intersections","commit_stats":{"total_commits":17,"total_committers":3,"mean_commits":5.666666666666667,"dds":"0.11764705882352944","last_synced_commit":"b193aa1c12549d4be17cb8dc59481941fc2c37c9"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rowanwins%2Fsweepline-intersections","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rowanwins%2Fsweepline-intersections/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rowanwins%2Fsweepline-intersections/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rowanwins%2Fsweepline-intersections/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rowanwins","download_url":"https://codeload.github.com/rowanwins/sweepline-intersections/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248597364,"owners_count":21130863,"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":["computational-geometry","polygon","sweep-line","sweep-line-algorithm"],"created_at":"2024-10-11T04:17:28.294Z","updated_at":"2025-04-12T16:36:26.110Z","avatar_url":"https://github.com/rowanwins.png","language":"JavaScript","funding_links":["https://github.com/sponsors/rowanwins","https://paypal.me/rowanwinsemius"],"categories":[],"sub_categories":[],"readme":"# sweepline-intersections\nA small and fast module using a sweepline algorithm to detect intersections between polygons and/or polylines.\n\n## Documentation\n\n### Install\n````\nnpm install sweepline-intersections\n````\n\n### Basic Use\nValid inputs: Geojson `Feature` or `Geometry` including `Polygon`, `LineString`, `MultiPolygon`, `MultiLineString`, as well as `FeatureCollection`.\n\nReturns an array of intersection points eg, [[x1, y1], [x2, y2]] \n\n````js\n    const findIntersections = require('sweepline-intersections')\n\n    const box = {type: 'Polygon', coordinates: [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]}\n    const intersections = findIntersections(box)\n    // returns an array of self-intersection points\n````\n\nAlso accepts an optional boolean argument second which when set to true means the module won't detect self-intersections and will only report intersections between different features. This defaults to false.\neg \n````js\n    const findIntersections = require('sweepline-intersections')\n    const intersectionsBetweenFeature = findIntersections(featureCollection, true)\n    // returns an array of intersection points between features\n````\n\n### Complex Use\nThis library also provide a class-based approach which is helpful if you want to check multiple geometries against a single geometry. This allows you to save the state of the initial event queue with the primary geometry.\n\n````js\n    import SweeplineIntersectionsClass from 'sweepline-intersections/dist/SweeplineIntersectionsClass'\n\n    // create the base instance\n    const sl = new SweeplineIntersectionsClass()\n    // populate the event queue with your primary geometry\n    sl.addData(largeGeoJson)\n    // clone the event queue in the original state so you can reuse it\n    const origQueue = sl.cloneEventQueue()\n\n    // now you can iterate through some other set of features saving\n    // the overhead of having to populate the complete queue multiple times\n    someOtherFeatureCollection.features.forEach(feature =\u003e {\n        // add another feature to test against your original data\n        sl.addData(feature, origQueue)\n        // check if those two features intersect\n        // add an optional boolean argument to ignore self-intersections \n        const intersectionPoints = sl.getIntersections(true)\n    })\n````\n\n#### API\n`new SweeplineIntersectionsClass()` - creates a new instance\n\n`.addData(geojson, existingQueue)` - add geojson to the event queue. The second argument for an `existingQueue` is optional, and takes a queue generated from `.cloneEventQueue()`\n\n`.cloneEventQueue()` - clones the state of the existing event queue that's been populated with geojson. Returns a queue that you can pass to the `addData` method\n\n`.getIntersections(ignoreSelfIntersections)` - Checks for segment intersections. Accepts an optional boolean argument to ignore self intersections are only report intersections between features.\n\n\n## Benchmarks\nTested against \n- bentley-ottmann-intersections - https://www.npmjs.com/package/bentley-ottmann-intersections\n- gpsi - https://www.npmjs.com/package/geojson-polygon-self-intersections\n- isects - https://www.npmjs.com/package/2d-polygon-self-intersections\n````\n// Switzerland (~700 vertices)\n// gpsi x 37.05 ops/sec ±1.77% (49 runs sampled)\n// bentleyOttmann x 2,010 ops/sec ±1.52% (89 runs sampled)\n// sweepline x 2,621 ops/sec ±0.29% (95 runs sampled)\n// isects x 14.29 ops/sec ±2.16% (40 runs sampled)\n// - Fastest is sweepline (this library)\n\n// Simple Case (6 vertices)\n// gpsi x 246,512 ops/sec ±1.23% (90 runs sampled)\n// bentleyOttmann x 546,326 ops/sec ±0.66% (92 runs sampled)\n// sweepline x 1,157,425 ops/sec ±1.04% (94 runs sampled)\n// - Fastest is sweepline (this library)\n\n// Chile - Vertical geometry (17,000 vertices)\n// sweepline x 35.64 ops/sec ±1.20% (62 runs sampled)\n````\n\n## Contributing\n- For a live dev server run `npm run debug`. \n  - The geometry being tested can be modified in `debug/src/App.vue`\n- There are a couple of test suites\n  - `npm run test` runs all tests\n  - `npm run test:e2e` does a general test that the correct number of self-intersections are found in the `test/fixtures` folder\n  - `npm run test:unit` is unit style tests to make sure functions \u0026 methods do the right thing\n    - these need some love\n\n\n## Algorithm notes\nThe basic concept of this algorithm is based on a sweepline. Where this algorithm differs from the [bentley-ottmann algorithm](https://en.wikipedia.org/wiki/Bentley%E2%80%93Ottmann_algorithm) is that there is no use of a tree data structure to store the segments. The reason for the modification is because if you are dealing with polygons or polylines (rather than a random group of line segments) there is a reasonable assumption that there are going to be very few segments that lie on the same x plane.\n\nRemoving the tree structure greatly simplifies the code. The tree structure is replaced with a priority queue of segments which is sorted by the x vertex of the right endpoint of the segments. A priority queue is already used to sort the vertices which means only 1 data structure is required.\n\nThe package size of this module is 3kb compared to my implementation of the bentley-ottmann algorithm which is 16kb while performance is typically faster than bentley-ottmann. \n\nBentley-ottman only outperforms this library when there are several thousands vertices, however I'm also less confident in the results of my bentley-ottman lib as it occassionally misses intersections and is much harder to write tests for due to the more complex logic.\n\n\n### Algorithm Steps\n- Vertices are entered into a priority queue sorted from left to right\n- An empty priority queue is created to store segments encountered\n- An item is removed from the priority queue\n    - If the vertex is the left endpoint of a segment, we test it against every other segment in the segment queue for intersections with any intersection recorded. We then add the vertex (and it's associated right endpoint) to the segment queue.\n    - When we encounter a right endpoint we remove the first item from the segment queue.\n\nEach pair of segments are only tested once. And only segments that overlap on the x plane are tested against each other.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frowanwins%2Fsweepline-intersections","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frowanwins%2Fsweepline-intersections","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frowanwins%2Fsweepline-intersections/lists"}