├── .editorconfig ├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── debug ├── .gitignore ├── .vscode │ └── extensions.json ├── README.md ├── dist │ ├── assets │ │ ├── graphCreation.worker.02f291a7.js │ │ ├── index.065c788d.css │ │ ├── index.628061df.js │ │ └── vendor.6c2250e5.js │ ├── favicon.ico │ └── index.html ├── gj.js ├── index.html ├── public │ └── favicon.ico ├── src │ ├── App.vue │ ├── graphCreation.worker.js │ ├── graphHelper.js │ ├── main.js │ └── mapHelpers.js └── vite.config.js ├── dist └── visibilityGraph.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── Contour.js ├── Edge.js ├── EdgeKey.js ├── EdgeKeys.js ├── Point.js ├── VisibilityGraph.js ├── createGraphFromGeoJson.js ├── debug.js ├── setupStructure.js └── utils.js └── test ├── Edge.spec.js ├── EdgeKey.spec.js ├── EdgeKeys.spec.js ├── Point.spec.js ├── bench.js ├── harness ├── asia.geojson ├── australia.geojson ├── bayarea2.geojson ├── bayarea3.geojson ├── continents2.geojson ├── multipolygon.geojson ├── polygon.geojson └── polygonCollection.geojson ├── setStructures.spec.js ├── sort.spec.js └── utils.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | indent_style = space 2 | indent_size = 2 -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:vue-libs/recommended"], 3 | "rules": { 4 | "padded-blocks": "off", 5 | "no-console": "off", 6 | "indent": ["error", 2] 7 | }, 8 | "globals": { 9 | "L": true, 10 | "turf": true 11 | } 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | .nyc_output/ 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | debug/ 2 | test/ 3 | .nyc_output/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rowan Winsemius 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # visibility-graph.js 2 | Visibility graph implementation to support shortest path calculations such as [dijkstra](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) or [a-star](https://en.wikipedia.org/wiki/A*_search_algorithm). 3 | 4 | ### [Demo](https://rowanwins.github.io/visibility-graph/debug/dist/index.html) 5 | 6 | ## Documentation 7 | 8 | This library exposes a `VisibilityGraph` class 9 | 10 | #### API 11 | `new VisibilityGraph(geojson, ?existingGraph)` - creates a new instance using a [Polygon](http://geojson.win/#appendix-A.3) or [MultiPolygon](http://geojson.win/#appendix-A.6) feature or geometry. Optionally, if you have an existing graph that you've previously generated using the `.saveGraphToJson()` you can pass it in as a argument. 12 | 13 | `.saveGraphToJson()` - Returns a json representation of the visibility graph which can be saved to disk and then restored by passing a second argument to the class constructor. 14 | 15 | `.addStartAndEndPointsToGraph(origin, destination)` - Takes 2 geojson point features, one for the origin, and one for the destination, and returns the newly added nodes in an object `{startNode: ngraphNode, endNode: ngraphNode}`. Each time this is called any previously added start and end points are removed from the graph. 16 | 17 | `.getNodeIdByLatLon([lat, lon])` - Returns a graph node ID that matches the lat lon. 18 | 19 | 20 | 21 | ## Example 22 | 23 | ````js 24 | import VisibilityGraph from 'visibility-graph.js' 25 | import path from 'ngraph.path' 26 | 27 | // Create the visibility graph from the geojson data 28 | const vg = new VisibilityGraph(geojson) 29 | 30 | // Use the 'ngraph.path' library to find a way 31 | //through the newly created visibility graph 32 | const pathFinder = path.nba(vg.graph, { 33 | distance (fromNode, toNode) { 34 | const dx = fromNode.data.x - toNode.data.x 35 | const dy = fromNode.data.y - toNode.data.y 36 | return Math.sqrt(dx * dx + dy * dy) 37 | } 38 | }) 39 | 40 | // Add the start and endpoints to the graph 41 | const startEndNodes = vg.addStartAndEndPointsToGraph( 42 | {type: 'Feature', geometry: {type: 'Point', coordinates: [0, 0]}}, 43 | {type: 'Feature', geometry: {type: 'Point', coordinates: [10, 10]}} 44 | ) 45 | 46 | // And finally retrive the optimal path 47 | const optimalPath = pathFinder.find( 48 | startEndNodes.startNode.nodeId, 49 | startEndNodes.endNode.nodeId 50 | ) 51 | 52 | ```` 53 | 54 | **NOTE:** If you get occassional issues with how your edges are being linked try reducing the precision of your coordinates (eg 8 decimal places). 55 | 56 | ## Using with other packages 57 | - Path finding can be achieved with the [ngraph.path](https://github.com/anvaka/ngraph.path) package. 58 | 59 | 60 | ## Performance 61 | The process of creating a visibility graph can be slow depending on the number of vertices in your input geometry. 62 | 63 | | Scenario | Nodes/Vertices | Create Graph | Time Reload Graph / Graph Size | 64 | | --------- | --------------- | ------------- | ------------------------------- | 65 | | Australia | 250 | 1 second | 300kb | 66 | | Asia | 1400 | 4 seconds | 100ms / 5.2MB | 67 | | World | 4400 | 20 seconds | | 68 | 69 | 70 | Depending on your requirements you may also be able to convert your input data if it has concave polygons, to only having convex polygons, this may reduce redundant nodes in the graph. 71 | 72 | 73 | ## References & Credits 74 | * Based on [pyvisgraph](https://github.com/TaipanRex/pyvisgraph) and associated blog posts 75 | * [Distance Tables Part 1: Defining the Problem](https://taipanrex.github.io/2016/09/17/Distance-Tables-Part-1-Defining-the-Problem.html) 76 | * [Distance Tables Part 2: Lee's Visibility Graph Algorithm](https://taipanrex.github.io/2016/10/19/Distance-Tables-Part-2-Lees-Visibility-Graph-Algorithm.html) 77 | * [Lee's o(n2 log n) Visibility Graph Algorithm](https://github.com/davetcoleman/visibility_graph/blob/master/Visibility_Graph_Algorithm.pdf) paper by Dave Coleman 78 | * [Intro to path finding](https://www.redblobgames.com/pathfinding/) 79 | * And specifically a bit about [visibility graphs](https://www.redblobgames.com/pathfinding/visibility-graphs/) 80 | -------------------------------------------------------------------------------- /debug/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | *.local 12 | 13 | # Editor directories and files 14 | .vscode/* 15 | !.vscode/extensions.json 16 | .idea 17 | .DS_Store 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /debug/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /debug/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Vite 2 | 3 | This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 ` 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 |