terra-route 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +15 -51
  2. package/assets/logo-dark-mode.png +0 -0
  3. package/assets/logo.png +0 -0
  4. package/dist/graph/graph.d.ts +31 -0
  5. package/dist/graph/methods/bounding-box.d.ts +13 -0
  6. package/dist/graph/methods/duplicates.d.ts +7 -0
  7. package/dist/graph/methods/leaf.d.ts +12 -0
  8. package/dist/graph/methods/spatial-index/geokdbush.d.ts +3 -0
  9. package/dist/graph/methods/spatial-index/kdbush.d.ts +16 -0
  10. package/dist/graph/methods/spatial-index/tinyqueue.d.ts +11 -0
  11. package/dist/graph/methods/unify.d.ts +2 -0
  12. package/dist/graph/methods/unique.d.ts +5 -0
  13. package/dist/terra-route.cjs +1 -1
  14. package/dist/terra-route.cjs.map +1 -1
  15. package/dist/terra-route.modern.js +1 -1
  16. package/dist/terra-route.modern.js.map +1 -1
  17. package/dist/terra-route.module.js +1 -1
  18. package/dist/terra-route.module.js.map +1 -1
  19. package/dist/terra-route.umd.js +1 -1
  20. package/dist/terra-route.umd.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/distance/haversine.ts +1 -0
  23. package/src/graph/graph.spec.ts +238 -0
  24. package/src/graph/graph.ts +63 -2
  25. package/src/graph/methods/bounding-box.spec.ts +199 -0
  26. package/src/graph/methods/bounding-box.ts +85 -0
  27. package/src/graph/methods/connected.spec.ts +3 -1
  28. package/src/graph/methods/duplicates.spec.ts +161 -0
  29. package/src/graph/methods/duplicates.ts +117 -0
  30. package/src/graph/methods/leaf.spec.ts +224 -0
  31. package/src/graph/methods/leaf.ts +88 -0
  32. package/src/graph/methods/spatial-index/geokdbush.spec.ts +86 -0
  33. package/src/graph/methods/spatial-index/geokdbush.ts +189 -0
  34. package/src/graph/methods/spatial-index/kdbush.spec.ts +67 -0
  35. package/src/graph/methods/spatial-index/kdbush.ts +189 -0
  36. package/src/graph/methods/spatial-index/tinyqueue.spec.ts +51 -0
  37. package/src/graph/methods/spatial-index/tinyqueue.ts +108 -0
  38. package/src/graph/methods/unify.spec.ts +475 -0
  39. package/src/graph/methods/unify.ts +132 -0
  40. package/src/graph/methods/unique.spec.ts +65 -0
  41. package/src/test-utils/utils.ts +1 -1
  42. package/src/graph/methods/unique-segments.spec.ts +0 -16
  43. /package/src/graph/methods/{unique-segments.ts → unique.ts} +0 -0
package/README.md CHANGED
@@ -1,4 +1,10 @@
1
- # Terra Route
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="./assets/logo-dark-mode.png">
3
+ <source media="(prefers-color-scheme: light)" srcset="./assets/logo.png">
4
+ <img alt="Terra Draw logo" src="./assets/logo.png" width="400px">
5
+ </picture>
6
+
7
+ <p></p>
2
8
 
3
9
  Terra Route aims to be a fast library for routing on GeoJSON LineStrings networks, where LineStrings share identical coordinates. Terra Routes main aim is currently performance - it uses A* to help achieve this.
4
10
 
@@ -20,62 +26,20 @@ Here is a short example of how to use the TerraRoute class:
20
26
  import { FeatureCollection, LineString, Point, Feature } from "geojson";
21
27
  import { TerraRoute } from "terra-route";
22
28
 
23
- // Sample GeoJSON network (a simple "L" shape)
24
- const network: FeatureCollection<LineString> = {
25
- type: "FeatureCollection",
26
- features: [
27
- {
28
- type: "Feature",
29
- geometry: {
30
- type: "LineString",
31
- coordinates: [
32
- [0, 0], // A
33
- [0, 1], // B
34
- [0, 2], // C
35
- ],
36
- },
37
- properties: {},
38
- },
39
- {
40
- type: "Feature",
41
- geometry: {
42
- type: "LineString",
43
- coordinates: [
44
- [0, 1], // B
45
- [1, 1], // D
46
- ],
47
- },
48
- properties: {},
49
- },
50
- ],
51
- };
52
-
53
- // Define start and end points (A and D)
54
- const startPoint: Feature<Point> = {
55
- type: "Feature",
56
- geometry: {
57
- type: "Point",
58
- coordinates: [0, 0], // Point A
59
- },
60
- properties: {},
61
- };
62
-
63
- const endPoint: Feature<Point> = {
64
- type: "Feature",
65
- geometry: {
66
- type: "Point",
67
- coordinates: [1, 1], // Point D
68
- },
69
- properties: {},
70
- };
29
+ // We omit the literal values here in the README for brevity
30
+ import { network, startPoint, endPoint } from './network'
71
31
 
72
32
  // Initialize TerraRoute instance
73
33
  const router = new TerraRoute();
74
34
 
75
- // We must build the route graph first before calling getRoute
35
+ // network here is a FeatureCollection<LineString> where the all
36
+ // identical coordinates are considered connected.
37
+ // We must build the route graph first before calling getRoute.
76
38
  router.buildRouteGraph(network);
77
39
 
78
- // Get shortest route
40
+ // Get shortest route where startPoint and endpoint are Feature<Point> of
41
+ // a coordinate node which is present on the network (i.e. the coordinate
42
+ // exists in one of the linestrings)
79
43
  const route = router.getRoute(startPoint, endPoint);
80
44
 
81
45
  console.log("Shortest route:", JSON.stringify(route, null, 2));
Binary file
Binary file
@@ -1,4 +1,5 @@
1
1
  import { Feature, FeatureCollection, LineString, Point } from "geojson";
2
+ import { BoundingBox } from "./methods/bounding-box";
2
3
  /**
3
4
  * Represents a graph constructed from a GeoJSON FeatureCollection of LineString features.
4
5
  * This class provides methods to analyze the graph, including connected components, node and edge counts,
@@ -18,6 +19,18 @@ export declare class LineStringGraph {
18
19
  * @returns A GeoJSON FeatureCollection of LineString features representing the network.
19
20
  */
20
21
  getNetwork(): FeatureCollection<LineString>;
22
+ /**
23
+ * Gets a filtered network containing only LineStrings that are completely within the specified bounding box.
24
+ * @param boundingBox A bounding box array in the format [minLng, minLat, maxLng, maxLat]
25
+ * @returns A GeoJSON FeatureCollection of LineString features representing the network filtered by the bounding box.
26
+ */
27
+ getNetworkInBoundingBox(boundingBox: BoundingBox): FeatureCollection<LineString>;
28
+ /**
29
+ * Gets the network without duplicate or subsection lines.
30
+ * This method processes the network to remove any duplicate lines or lines that are subsections of other lines.
31
+ * @returns A FeatureCollection<LineString> representing the network without duplicate or subsection lines.
32
+ */
33
+ getNetworkWithoutDuplicatesOrSubsections(): FeatureCollection<LineString, import("geojson").GeoJsonProperties>;
21
34
  /**
22
35
  * Gets the connected components of the graph.
23
36
  * @returns An array of FeatureCollection<LineString> representing the connected components.
@@ -80,4 +93,22 @@ export declare class LineStringGraph {
80
93
  * @returns The number of unique edges in the graph.
81
94
  */
82
95
  getEdgeCount(): number;
96
+ /**
97
+ * Gets the leaf edges of the graph. A leaf edge is defined as an edge whose start or end node has a degree of 1.
98
+ * Here an edge is defined as a LineString with two coordinates, representing the start and end points.
99
+ * @returns A FeatureCollection<LineString> containing only the leaf edges of the graph.
100
+ */
101
+ getLeafEdges(): FeatureCollection<LineString>;
102
+ /**
103
+ * Returns the pruned network, which is the network without the leaf edges.
104
+ * i.e. This method removes all leaf edges from the network, leaving only the non-leaf edges
105
+ * @return A FeatureCollection<LineString> representing the pruned network without leaf edges.
106
+ */
107
+ getPrunedEdges(depth?: number): FeatureCollection<LineString>;
108
+ /**
109
+ * Returns the network where all nodes that are with n meters of each other are unified.
110
+ * The function will avoid unifying coordinates in the same linestring.
111
+ * @param toleranceMeters the tolerance for unifying nodes in meters.
112
+ */
113
+ getUnifiedNetwork(toleranceMeters: number): FeatureCollection<LineString, import("geojson").GeoJsonProperties>;
83
114
  }
@@ -0,0 +1,13 @@
1
+ import { FeatureCollection, LineString } from 'geojson';
2
+ /**
3
+ * Type representing a bounding box as [minLng, minLat, maxLng, maxLat]
4
+ */
5
+ export type BoundingBox = [number, number, number, number];
6
+ /**
7
+ * Filters a FeatureCollection of LineString features to only include LineStrings
8
+ * that are completely within the specified bounding box.
9
+ * @param featureCollection - A GeoJSON FeatureCollection containing LineString features
10
+ * @param boundingBox - A bounding box array in the format [minLng, minLat, maxLng, maxLat]
11
+ * @returns A new FeatureCollection<LineString> containing only the LineStrings completely within the bounding box
12
+ */
13
+ export declare function getNetworkInBoundingBox(featureCollection: FeatureCollection<LineString>, boundingBox: BoundingBox): FeatureCollection<LineString>;
@@ -0,0 +1,7 @@
1
+ import { FeatureCollection, LineString } from 'geojson';
2
+ /**
3
+ * Remove any LineString that is either
4
+ * - an exact duplicate of an earlier one, or
5
+ * - a contiguous subsequence (in either direction) of any other.
6
+ */
7
+ export declare function removeDuplicateAndSubsectionLines(collection: FeatureCollection<LineString>): FeatureCollection<LineString>;
@@ -0,0 +1,12 @@
1
+ import { FeatureCollection, LineString } from 'geojson';
2
+ /**
3
+ * Separates a graph's edges into leaf and non-leaf edges.
4
+ * A leaf edge has a start or end node with degree 1.
5
+ *
6
+ * @param edgesFc - FeatureCollection containing LineString features representing edges of a graph
7
+ * @returns Object containing two FeatureCollections: leafEdges and nonLeafEdges
8
+ */
9
+ export declare function getLeafEdges(edgesFc: FeatureCollection<LineString>): {
10
+ leafEdges: FeatureCollection<LineString>;
11
+ nonLeafEdges: FeatureCollection<LineString>;
12
+ };
@@ -0,0 +1,3 @@
1
+ import { KDBush } from './kdbush';
2
+ export declare function around(index: KDBush, lng: number, lat: number, maxResults?: number, maxDistanceKm?: number): any[];
3
+ export declare function distance(lng1: number, lat1: number, lng2: number, lat2: number): number;
@@ -0,0 +1,16 @@
1
+ export declare class KDBush {
2
+ data: ArrayBuffer;
3
+ ids: Uint16Array | Uint32Array;
4
+ coords: InstanceType<TypedArrayConstructor>;
5
+ private _pos;
6
+ private _finished;
7
+ numItems: number;
8
+ nodeSize: number;
9
+ private ArrayType;
10
+ private IndexArrayType;
11
+ constructor(numItems: number, nodeSize?: number, ArrayType?: TypedArrayConstructor, data?: ArrayBuffer);
12
+ add(x: number, y: number): number;
13
+ finish(): this;
14
+ }
15
+ type TypedArrayConstructor = Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor;
16
+ export {};
@@ -0,0 +1,11 @@
1
+ export default class TinyQueue<T> {
2
+ private data;
3
+ length: number;
4
+ private compare;
5
+ constructor(data?: T[], compare?: (a: T, b: T) => number);
6
+ push(item: T): void;
7
+ pop(): T | undefined;
8
+ peek(): T | undefined;
9
+ private _up;
10
+ private _down;
11
+ }
@@ -0,0 +1,2 @@
1
+ import { FeatureCollection, LineString } from 'geojson';
2
+ export declare function unifyCloseCoordinates(featureCollection: FeatureCollection<LineString>, radiusMeters: number): FeatureCollection<LineString>;
@@ -0,0 +1,5 @@
1
+ import { FeatureCollection, LineString } from 'geojson';
2
+ /**
3
+ * Breaks LineStrings in a FeatureCollection into unique single line segments
4
+ */
5
+ export declare function graphGetUniqueSegments(input: FeatureCollection<LineString>): FeatureCollection<LineString>;
@@ -1,2 +1,2 @@
1
- function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function t(t,r){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=function(t,r){if(t){if("string"==typeof t)return e(t,r);var n={}.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?e(t,r):void 0}}(t))||r&&t&&"number"==typeof t.length){n&&(t=n);var o=0;return function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var r=function(e,t){var r=function(e){return e*Math.PI/180},n=r(e[1]),o=r(e[0]),a=r(t[1]),i=a-n,s=r(t[0])-o,u=Math.sin(i/2)*Math.sin(i/2)+Math.cos(n)*Math.cos(a)*Math.sin(s/2)*Math.sin(s/2);return 2*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))*6371e3/1e3},n=/*#__PURE__*/function(){function e(){this.heap=[],this.insertCounter=0}var t=e.prototype;return t.insert=function(e,t){var r={key:e,value:t,index:this.insertCounter++},n=this.heap.length;for(this.heap.push(r);n>0;){var o=n-1>>>1,a=this.heap[o];if(e>a.key||e===a.key&&r.index>a.index)break;this.heap[n]=a,n=o}this.heap[n]=r},t.extractMin=function(){var e=this.heap,t=e.length;if(0===t)return null;var r=e[0],n=e.pop();return t>1&&(e[0]=n,this.bubbleDown(0)),r.value},t.size=function(){return this.heap.length},t.bubbleDown=function(e){for(var t=this.heap,r=t.length,n=t[e],o=n.key,a=n.index;;){var i=1+(e<<1);if(i>=r)break;var s=i,u=t[i],h=i+1;if(h<r){var d=t[h];(d.key<u.key||d.key===u.key&&d.index<u.index)&&(s=h,u=d)}if(!(u.key<o||u.key===o&&u.index<a))break;t[e]=u,e=s}t[e]=n},e}();function o(e,r,n){n[e]=!0;for(var a,i=t(r[e]);!(a=i()).done;){var s=a.value;n[s]||o(s,r,n)}}function a(e,t){var r=function(e,t){var r=e[0],n=t[0];return r<n||r===n&&e[1]<=t[1]?[e,t]:[t,e]}(e,t);return JSON.stringify([r[0],r[1]])}function i(e){for(var t=e.geometry.coordinates,n=0,o=0;o<t.length-1;o++)n+=r(t[o],t[o+1]);return n}var s=/*#__PURE__*/function(){function e(e){this.network=void 0,this.network=e}var r=e.prototype;return r.setNetwork=function(e){this.network=e},r.getNetwork=function(){return this.network},r.getConnectedComponents=function(){return function(e){var r=e.features,n=new Map,o=new Map;function a(e){return e[0]+","+e[1]}for(var i=0;i<r.length;i++)for(var s,u=t(r[i].geometry.coordinates);!(s=u()).done;){var h=a(s.value);o.has(h)||o.set(h,new Set),o.get(h).add(i)}for(var d=0;d<r.length;d++){n.set(d,new Set);for(var f,c=t(r[d].geometry.coordinates);!(f=c()).done;){var v=a(f.value),g=o.get(v);if(g)for(var l,p=t(g);!(l=p()).done;){var y=l.value;y!==d&&n.get(d).add(y)}}}var w=new Set,M=[];function m(e,o){for(var a=[e];a.length>0;){var i=a.pop();if(!w.has(i)){w.add(i),o.push(r[i]);var s=n.get(i);if(s)for(var u,h=t(s);!(u=h()).done;){var d=u.value;w.has(d)||a.push(d)}}}}for(var k=0;k<r.length;k++)if(!w.has(k)){var C=[];m(k,C),M.push({type:"FeatureCollection",features:C})}return M.sort(function(e,t){return e.features.length-t.features.length}),M}(this.network)},r.getConnectedComponentCount=function(){return function(e){for(var r,n=e.features,a=n.length,i=new Map,s=0;s<a;s++)for(var u,h=t(n[s].geometry.coordinates);!(u=h()).done;){var d=(r=u.value)[0]+","+r[1];i.has(d)||i.set(d,[]),i.get(d).push(s)}for(var f,c=Array.from({length:a},function(){return[]}),v=t(i.values());!(f=v()).done;)for(var g=f.value,l=0;l<g.length;l++)for(var p=l+1;p<g.length;p++){var y=g[l],w=g[p];c[y].push(w),c[w].push(y)}for(var M=new Array(a).fill(!1),m=0,k=0;k<a;k++)M[k]||(o(k,c,M),m++);return m}(this.network)},r.getNodeAndEdgeCount=function(){return function(e){for(var r,n=new Set,o=new Set,a=t(e.features);!(r=a()).done;){for(var i,s=r.value.geometry.coordinates,u=t(s);!(i=u()).done;)n.add(JSON.stringify(i.value));for(var h=0;h<s.length-1;h++){var d=(f=s[h+1],void 0,void 0,(c=JSON.stringify(s[h]))<(v=JSON.stringify(f))?c+"|"+v:v+"|"+c);o.add(d)}}var f,c,v;return{nodeCount:n.size,edgeCount:o.size}}(this.network)},r.getNodes=function(){return{type:"FeatureCollection",features:function(e){for(var r,n=new Set,o=[],a=t(e.features);!(r=a()).done;)for(var i,s=t(r.value.geometry.coordinates);!(i=s()).done;){var u=i.value,h=u.join(",");n.has(h)||(n.add(h),o.push({type:"Feature",geometry:{type:"Point",coordinates:u},properties:{}}))}return o}(this.network)}},r.getNodeCount=function(){return this.getNodeAndEdgeCount().nodeCount},r.getEdges=function(){return function(e){for(var r,n=new Map,o=t(e.features);!(r=o()).done;)for(var i=r.value.geometry.coordinates,s=0;s<i.length-1;s++){var u=i[s],h=i[s+1],d=a(u,h);n.has(d)||n.set(d,{type:"Feature",geometry:{type:"LineString",coordinates:[u,h]},properties:{}})}return{type:"FeatureCollection",features:Array.from(n.values())}}(this.network)},r.getLongestEdgeLength=function(){var e=this.getLongestEdge();return e?i(e):-1},r.getShortestEdgeLength=function(){var e=this.getShortestEdge();return e?i(e):-1},r.getLongestEdge=function(){var e=this.getEdges().features;if(0===e.length)return null;var t=e.sort(function(e,t){return i(e)-i(t)});return t[t.length-1]},r.getShortestEdge=function(){var e=this.getEdges().features;return 0===e.length?null:e.sort(function(e,t){return i(e)-i(t)})[0]},r.getEdgeCount=function(){return this.getNodeAndEdgeCount().edgeCount},e}(),u=/*#__PURE__*/function(){function e(e){var t,o;this.network=null,this.distanceMeasurement=void 0,this.heapConstructor=void 0,this.coordinateIndexMap=new Map,this.coordinates=[],this.adjacencyList=[],this.distanceMeasurement=null!=(t=null==e?void 0:e.distanceMeasurement)?t:r,this.heapConstructor=null!=(o=null==e?void 0:e.heap)?o:n}var o=e.prototype;return o.buildRouteGraph=function(e){this.network=e,this.coordinateIndexMap=new Map,this.coordinates=[],this.adjacencyList=[];for(var r,n=this.coordinateIndexMap,o=this.coordinates,a=this.adjacencyList,i=this.distanceMeasurement,s=t(e.features);!(r=s()).done;)for(var u=r.value.geometry.coordinates,h=0;h<u.length-1;h++){var d=u[h],f=d[0],c=d[1],v=u[h+1],g=v[0],l=v[1],p=n.get(f);p||(p=new Map,n.set(f,p));var y=p.get(c);void 0===y&&(y=o.length,o.push(u[h]),p.set(c,y),a[y]=[]);var w=n.get(g);w||(w=new Map,n.set(g,w));var M=w.get(l);void 0===M&&(M=o.length,o.push(u[h+1]),w.set(l,M),a[M]=[]);var m=i(u[h],u[h+1]);a[y].push({node:M,distance:m}),a[M].push({node:y,distance:m})}},o.getRoute=function(e,r){if(!this.network)throw new Error("Network not built. Please call buildRouteGraph(network) first.");var n=this.getOrCreateIndex(e.geometry.coordinates),o=this.getOrCreateIndex(r.geometry.coordinates);if(n===o)return null;var a=new this.heapConstructor;a.insert(0,n);var i=this.coordinates.length,s=new Array(i).fill(Infinity),u=new Array(i).fill(-1),h=new Array(i).fill(!1);for(s[n]=0;a.size()>0;){var d=a.extractMin();if(!h[d]){if(d===o)break;h[d]=!0;for(var f,c=t(this.adjacencyList[d]||[]);!(f=c()).done;){var v=f.value,g=s[d]+v.distance;if(g<s[v.node]){s[v.node]=g,u[v.node]=d;var l=this.distanceMeasurement(this.coordinates[v.node],this.coordinates[o]);a.insert(g+l,v.node)}}}}if(u[o]<0)return null;for(var p=[],y=o;y!==n;)p.unshift(this.coordinates[y]),y=u[y];return p.unshift(this.coordinates[n]),{type:"Feature",geometry:{type:"LineString",coordinates:p},properties:{}}},o.getOrCreateIndex=function(e){var t=e[0],r=e[1],n=this.coordinateIndexMap.get(t);n||(n=new Map,this.coordinateIndexMap.set(t,n));var o=n.get(r);return void 0===o&&(o=this.coordinates.length,this.coordinates.push(e),n.set(r,o),this.adjacencyList[o]=[]),o},e}();exports.LineStringGraph=s,exports.TerraRoute=u,exports.createCheapRuler=function(e){var t=1/298.257223563,r=t*(2-t),n=Math.PI/180,o=Math.cos(e*n),a=1/(1-r*(1-o*o)),i=Math.sqrt(a),s=6378.137*n,u=s*i*o,h=s*i*a*(1-r);return function(e,t){for(var r=e[0]-t[0];r<-180;)r+=360;for(;r>180;)r-=360;var n=r*u,o=(e[1]-t[1])*h;return Math.sqrt(n*n+o*o)}},exports.haversineDistance=r;
1
+ function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=Array(e);r<e;r++)n[r]=t[r];return n}function e(e,r){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(n)return(n=n.call(e)).next.bind(n);if(Array.isArray(e)||(n=function(e,r){if(e){if("string"==typeof e)return t(e,r);var n={}.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?t(e,r):void 0}}(e))||r&&e&&"number"==typeof e.length){n&&(e=n);var a=0;return function(){return a>=e.length?{done:!0}:{done:!1,value:e[a++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function r(){return r=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var n in r)({}).hasOwnProperty.call(r,n)&&(t[n]=r[n])}return t},r.apply(null,arguments)}var n=function(t,e){var r=function(t){return t*Math.PI/180},n=r(t[1]),a=r(t[0]),i=r(e[1]),o=i-n,s=r(e[0])-a,u=Math.sin(o/2)*Math.sin(o/2)+Math.cos(n)*Math.cos(i)*Math.sin(s/2)*Math.sin(s/2);return 2*Math.atan2(Math.sqrt(u),Math.sqrt(1-u))*6371e3/1e3},a=/*#__PURE__*/function(){function t(){this.heap=[],this.insertCounter=0}var e=t.prototype;return e.insert=function(t,e){var r={key:t,value:e,index:this.insertCounter++},n=this.heap.length;for(this.heap.push(r);n>0;){var a=n-1>>>1,i=this.heap[a];if(t>i.key||t===i.key&&r.index>i.index)break;this.heap[n]=i,n=a}this.heap[n]=r},e.extractMin=function(){var t=this.heap,e=t.length;if(0===e)return null;var r=t[0],n=t.pop();return e>1&&(t[0]=n,this.bubbleDown(0)),r.value},e.size=function(){return this.heap.length},e.bubbleDown=function(t){for(var e=this.heap,r=e.length,n=e[t],a=n.key,i=n.index;;){var o=1+(t<<1);if(o>=r)break;var s=o,u=e[o],h=o+1;if(h<r){var f=e[h];(f.key<u.key||f.key===u.key&&f.index<u.index)&&(s=h,u=f)}if(!(u.key<a||u.key===a&&u.index<i))break;e[t]=u,t=s}e[t]=n},t}();function i(t,r,n){n[t]=!0;for(var a,o=e(r[t]);!(a=o()).done;){var s=a.value;n[s]||i(s,r,n)}}function o(t,e){var r=function(t,e){var r=t[0],n=e[0];return r<n||r===n&&t[1]<=e[1]?[t,e]:[e,t]}(t,e);return JSON.stringify([r[0],r[1]])}function s(t){for(var r,n=new Map,a=e(t.features);!(r=a()).done;)for(var i=r.value.geometry.coordinates,s=0;s<i.length-1;s++){var u=i[s],h=i[s+1],f=o(u,h);n.has(f)||n.set(f,{type:"Feature",geometry:{type:"LineString",coordinates:[u,h]},properties:{}})}return{type:"FeatureCollection",features:Array.from(n.values())}}function u(t){for(var e=t.geometry.coordinates,r=0,a=0;a<e.length-1;a++)r+=n(e[a],e[a+1]);return r}function h(t,e){var r=t.length,n=e.length;if(r>n)return!1;for(var a=0;a<=n-r;a++){for(var i=!0,o=0;o<r;o++)if(e[a+o][0]!==t[o][0]||e[a+o][1]!==t[o][1]){i=!1;break}if(i)return!0}for(var s=[].concat(t).reverse(),u=0;u<=n-r;u++){for(var h=!0,f=0;f<r;f++)if(e[u+f][0]!==s[f][0]||e[u+f][1]!==s[f][1]){h=!1;break}if(h)return!0}return!1}function f(t){var e=s(t),r=new Map;function n(t){return t.join(",")}for(var a=0;a<e.features.length;a++){var i=e.features[a].geometry.coordinates;if(!(i.length<2)){var o=n(i[0]),u=n(i[i.length-1]);r.set(o,(r.get(o)||0)+1),r.set(u,(r.get(u)||0)+1)}}for(var h=new Map,f=new Map,d=0;d<e.features.length;d++){var v=e.features[d],c=v.geometry.coordinates;if(!(c.length<2)){var l=n(c[0]),g=n(c[c.length-1]),p=r.get(l)||0,y=r.get(g)||0,m=c.map(n).join(";");1===p||1===y?h.has(m)||h.set(m,v):f.has(m)||f.set(m,v)}}return{leafEdges:{type:"FeatureCollection",features:Array.from(h.values())},nonLeafEdges:{type:"FeatureCollection",features:Array.from(f.values())}}}function d(t,r,n,a,i){for(var o,s=e(t.geometry.coordinates);!(o=s()).done;)if(!v(o.value,r,n,a,i))return!1;return!0}function v(t,e,r,n,a){var i=t[0],o=t[1];return i>=e&&i<=n&&o>=r&&o<=a}var c=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],l=/*#__PURE__*/function(){function t(t,e,r,n){if(void 0===e&&(e=64),void 0===r&&(r=Float64Array),this.data=void 0,this.ids=void 0,this.coords=void 0,this._pos=void 0,this._finished=void 0,this.numItems=void 0,this.nodeSize=void 0,this.ArrayType=void 0,this.IndexArrayType=void 0,isNaN(t)||t<0)throw new Error("Unexpected numItems value: "+t+".");this.numItems=t,this.nodeSize=Math.min(Math.max(e,2),65535),this.ArrayType=r,this.IndexArrayType=t<65536?Uint16Array:Uint32Array;var a=c.indexOf(this.ArrayType),i=2*t*this.ArrayType.BYTES_PER_ELEMENT,o=t*this.IndexArrayType.BYTES_PER_ELEMENT,s=(8-o%8)%8;if(a<0)throw new Error("Unexpected typed array class: "+r+".");n?(this.data=n,this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+o+s,2*t),this._pos=2*t,this._finished=!0):(this.data=new ArrayBuffer(8+i+o+s),this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+o+s,2*t),this._pos=0,this._finished=!1,new Uint8Array(this.data,0,2).set([219,16+a]),new Uint16Array(this.data,2,1)[0]=this.nodeSize,new Uint32Array(this.data,4,1)[0]=this.numItems)}var e=t.prototype;return e.add=function(t,e){var r=this._pos>>1;return this.ids[r]=r,this.coords[this._pos++]=t,this.coords[this._pos++]=e,r},e.finish=function(){var t=this._pos>>1;if(t!==this.numItems)throw new Error("Added "+t+" items when expected "+this.numItems+".");return g(this.ids,this.coords,this.nodeSize,0,this.numItems-1,0),this._finished=!0,this},t}();function g(t,e,r,n,a,i){if(!(a-n<=r)){var o=n+a>>1;p(t,e,o,n,a,i),g(t,e,r,n,o-1,1-i),g(t,e,r,o+1,a,1-i)}}function p(t,e,r,n,a,i){for(;a>n;){if(a-n>600){var o=a-n+1,s=r-n+1,u=Math.log(o),h=.5*Math.exp(2*u/3),f=.5*Math.sqrt(u*h*(o-h)/o)*(s-o/2<0?-1:1);p(t,e,r,Math.max(n,Math.floor(r-s*h/o+f)),Math.min(a,Math.floor(r+(o-s)*h/o+f)),i)}var d=e[2*r+i],v=n,c=a;for(y(t,e,n,r),e[2*a+i]>d&&y(t,e,n,a);v<c;){for(y(t,e,v,c),v++,c--;e[2*v+i]<d;)v++;for(;e[2*c+i]>d;)c--}e[2*n+i]===d?y(t,e,n,c):y(t,e,++c,a),c<=r&&(n=c+1),r<=c&&(a=c-1)}}function y(t,e,r,n){m(t,r,n),m(e,2*r,2*n),m(e,2*r+1,2*n+1)}function m(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}var w=/*#__PURE__*/function(){function t(t,e){if(void 0===t&&(t=[]),void 0===e&&(e=function(t,e){return t<e?-1:t>e?1:0}),this.data=void 0,this.length=void 0,this.compare=void 0,this.data=t,this.length=this.data.length,this.compare=e,this.length>0)for(var r=(this.length>>1)-1;r>=0;r--)this._down(r)}var e=t.prototype;return e.push=function(t){this.data.push(t),this._up(this.length++)},e.pop=function(){if(0!==this.length){var t=this.data[0],e=this.data.pop();return this.length--,this.length>0&&(this.data[0]=e,this._down(0)),t}},e.peek=function(){return this.data[0]},e._up=function(t){for(var e=this.data,r=this.compare,n=e[t];t>0;){var a=t-1>>1,i=e[a];if(r(n,i)>=0)break;e[t]=i,t=a}e[t]=n},e._down=function(t){for(var e=this.data,r=this.compare,n=this.length>>1,a=e[t];t<n;){var i=1+(t<<1),o=i+1;if(o<this.length&&r(e[o],e[i])<0&&(i=o),r(e[i],a)>=0)break;e[t]=e[i],t=i}e[t]=a},t}(),M=Math.PI/180;function x(t,e,r,n){var a=n.minLng,i=n.maxLng,o=n.minLat,s=n.maxLat;if(t>=a&&t<=i)return e<o?A((e-o)*M):e>s?A((e-s)*M):0;var u=Math.min(A((t-a)*M),A((t-i)*M)),h=function(t,e){var r=1-2*e;return r<=0?t>0?90:-90:Math.atan(Math.tan(t*M)/r)/M}(e,u);return h>o&&h<s?L(u,r,e,h):Math.min(L(u,r,e,o),L(u,r,e,s))}function k(t,e){return t.dist-e.dist}function A(t){var e=Math.sin(t/2);return e*e}function L(t,e,r,n){return e*Math.cos(n*M)*t+A((r-n)*M)}function I(t,e,r,n,a){return L(A((t-r)*M),a,e,n)}var E=/*#__PURE__*/function(){function t(t){this.network=void 0,this.network=t}var a=t.prototype;return a.setNetwork=function(t){this.network=t},a.getNetwork=function(){return this.network},a.getNetworkInBoundingBox=function(t){return function(t,r){var n=r[0],a=r[1],i=r[2],o=r[3];if(n>=i||a>=o)throw new Error("Invalid bounding box: min values must be less than max values");for(var s,u=[],h=e(t.features);!(s=h()).done;){var f=s.value;d(f,n,a,i,o)&&u.push(f)}return{type:"FeatureCollection",features:u}}(this.network,t)},a.getNetworkWithoutDuplicatesOrSubsections=function(){return function(t){for(var e=t.features,r=new Set,n=0;n<e.length;n++)for(var a=e[n].geometry.coordinates,i=0;i<e.length;i++)if(n!==i){var o=e[i].geometry.coordinates;if(h(a,o)&&(a.length<o.length||a.length===o.length&&n>i)){r.add(n);break}}return{type:"FeatureCollection",features:e.filter(function(t,e){return!r.has(e)})}}(this.network)},a.getConnectedComponents=function(){return function(t){var r=t.features,n=new Map,a=new Map;function i(t){return t[0]+","+t[1]}for(var o=0;o<r.length;o++)for(var s,u=e(r[o].geometry.coordinates);!(s=u()).done;){var h=i(s.value);a.has(h)||a.set(h,new Set),a.get(h).add(o)}for(var f=0;f<r.length;f++){n.set(f,new Set);for(var d,v=e(r[f].geometry.coordinates);!(d=v()).done;){var c=i(d.value),l=a.get(c);if(l)for(var g,p=e(l);!(g=p()).done;){var y=g.value;y!==f&&n.get(f).add(y)}}}var m=new Set,w=[];function M(t,a){for(var i=[t];i.length>0;){var o=i.pop();if(!m.has(o)){m.add(o),a.push(r[o]);var s=n.get(o);if(s)for(var u,h=e(s);!(u=h()).done;){var f=u.value;m.has(f)||i.push(f)}}}}for(var x=0;x<r.length;x++)if(!m.has(x)){var k=[];M(x,k),w.push({type:"FeatureCollection",features:k})}return w.sort(function(t,e){return t.features.length-e.features.length}),w}(this.network)},a.getConnectedComponentCount=function(){return function(t){for(var r,n=t.features,a=n.length,o=new Map,s=0;s<a;s++)for(var u,h=e(n[s].geometry.coordinates);!(u=h()).done;){var f=(r=u.value)[0]+","+r[1];o.has(f)||o.set(f,[]),o.get(f).push(s)}for(var d,v=Array.from({length:a},function(){return[]}),c=e(o.values());!(d=c()).done;)for(var l=d.value,g=0;g<l.length;g++)for(var p=g+1;p<l.length;p++){var y=l[g],m=l[p];v[y].push(m),v[m].push(y)}for(var w=new Array(a).fill(!1),M=0,x=0;x<a;x++)w[x]||(i(x,v,w),M++);return M}(this.network)},a.getNodeAndEdgeCount=function(){return function(t){for(var r,n=new Set,a=new Set,i=e(t.features);!(r=i()).done;){for(var o,s=r.value.geometry.coordinates,u=e(s);!(o=u()).done;)n.add(JSON.stringify(o.value));for(var h=0;h<s.length-1;h++){var f=(d=s[h+1],(v=JSON.stringify(s[h]))<(c=JSON.stringify(d))?v+"|"+c:c+"|"+v);a.add(f)}}var d,v,c;return{nodeCount:n.size,edgeCount:a.size}}(this.network)},a.getNodes=function(){return{type:"FeatureCollection",features:function(t){for(var r,n=new Set,a=[],i=e(t.features);!(r=i()).done;)for(var o,s=e(r.value.geometry.coordinates);!(o=s()).done;){var u=o.value,h=u.join(",");n.has(h)||(n.add(h),a.push({type:"Feature",geometry:{type:"Point",coordinates:u},properties:{}}))}return a}(this.network)}},a.getNodeCount=function(){return this.getNodeAndEdgeCount().nodeCount},a.getEdges=function(){return s(this.network)},a.getLongestEdgeLength=function(){var t=this.getLongestEdge();return t?u(t):-1},a.getShortestEdgeLength=function(){var t=this.getShortestEdge();return t?u(t):-1},a.getLongestEdge=function(){var t=this.getEdges().features;if(0===t.length)return null;var e=t.sort(function(t,e){return u(t)-u(e)});return e[e.length-1]},a.getShortestEdge=function(){var t=this.getEdges().features;return 0===t.length?null:t.sort(function(t,e){return u(t)-u(e)})[0]},a.getEdgeCount=function(){return this.getNodeAndEdgeCount().edgeCount},a.getLeafEdges=function(){return f(this.network).leafEdges},a.getPrunedEdges=function(t){if(t&&t>0){for(var e=this.network,r=0;r<t;r++)e=f(e).nonLeafEdges;return e}return f(this.network).nonLeafEdges},a.getUnifiedNetwork=function(t){return function(t,a){if(t.features.length<2)return t;for(var i,o=new Set,s=new Map,u=[],h=new Map,f=e(t.features);!(i=f()).done;)for(var d,v=e(i.value.geometry.coordinates);!(d=v()).done;){var c=d.value,g=c[0]+","+c[1];h.has(g)||(h.set(g,u.length),u.push(c))}for(var p=new l(u.length),y=0,m=u;y<m.length;y++){var L=m[y];p.add(L[0],L[1])}function E(t,r,i){for(var s,h=null,f=Infinity,d=e(function(t,e,r,n,a){void 0===n&&(n=Infinity),void 0===a&&(a=Infinity);var i=1,o=[];void 0===n&&(n=Infinity),void 0!==a&&(i=A(a/6371));for(var s=new w([],k),u={left:0,right:t.ids.length-1,axis:0,dist:0,minLng:-180,minLat:-90,maxLng:180,maxLat:90},h=Math.cos(r*M);u;){var f=u.right,d=u.left;if(f-d<=t.nodeSize)for(var v=d;v<=f;v++){var c=t.ids[v],l=I(e,r,t.coords[2*v],t.coords[2*v+1],h);s.push({id:c,dist:l})}else{var g=d+f>>1,p=t.coords[2*g],y=t.coords[2*g+1],m=t.ids[g],L=I(e,r,p,y,h);s.push({id:m,dist:L});var E=(u.axis+1)%2,b={left:d,right:g-1,axis:E,minLng:u.minLng,minLat:u.minLat,maxLng:0===u.axis?p:u.maxLng,maxLat:1===u.axis?y:u.maxLat,dist:0},C={left:g+1,right:f,axis:E,minLng:0===u.axis?p:u.minLng,minLat:1===u.axis?y:u.minLat,maxLng:u.maxLng,maxLat:u.maxLat,dist:0};b.dist=x(e,r,h,b),C.dist=x(e,r,h,C),s.push(b),s.push(C)}for(;s.length&&null!=s.peek().id;){var S=s.pop();if(S.dist>i)return o;if(o.push(S.id),o.length===n)return o}u=s.pop()}return o}(p,t[0],t[1],Infinity,a/1e3));!(s=d()).done;){var v=u[s.value],c=v[0]+","+v[1];if(o.has(c)&&!r.includes(v)&&!i.has(c)){var l=1e3*n(v,t);l<=a&&l<f&&(h=v,f=l)}}return null!==h?h:(o.add(t[0]+","+t[1]),t)}p.finish();var b=t.features.map(function(t){for(var n,a=[],i=[],o=new Set,u=e(t.geometry.coordinates);!(n=u()).done;){var h=n.value,f=h[0]+","+h[1];if(!s.has(f)){var d=E(h,a,o);o.has(d[0]+","+d[1])?s.set(f,h):s.set(f,d)}var v=s.get(f),c=v[0]+","+v[1];o.has(c)||(i.push(v),o.add(c)),a.push(h)}return r({},t,{geometry:r({},t.geometry,{coordinates:i})})});return r({},t,{features:b})}(this.network,t)},t}(),b=/*#__PURE__*/function(){function t(t){var e,r;this.network=null,this.distanceMeasurement=void 0,this.heapConstructor=void 0,this.coordinateIndexMap=new Map,this.coordinates=[],this.adjacencyList=[],this.distanceMeasurement=null!=(e=null==t?void 0:t.distanceMeasurement)?e:n,this.heapConstructor=null!=(r=null==t?void 0:t.heap)?r:a}var r=t.prototype;return r.buildRouteGraph=function(t){this.network=t,this.coordinateIndexMap=new Map,this.coordinates=[],this.adjacencyList=[];for(var r,n=this.coordinateIndexMap,a=this.coordinates,i=this.adjacencyList,o=this.distanceMeasurement,s=e(t.features);!(r=s()).done;)for(var u=r.value.geometry.coordinates,h=0;h<u.length-1;h++){var f=u[h],d=f[0],v=f[1],c=u[h+1],l=c[0],g=c[1],p=n.get(d);p||(p=new Map,n.set(d,p));var y=p.get(v);void 0===y&&(y=a.length,a.push(u[h]),p.set(v,y),i[y]=[]);var m=n.get(l);m||(m=new Map,n.set(l,m));var w=m.get(g);void 0===w&&(w=a.length,a.push(u[h+1]),m.set(g,w),i[w]=[]);var M=o(u[h],u[h+1]);i[y].push({node:w,distance:M}),i[w].push({node:y,distance:M})}},r.getRoute=function(t,r){if(!this.network)throw new Error("Network not built. Please call buildRouteGraph(network) first.");var n=this.getOrCreateIndex(t.geometry.coordinates),a=this.getOrCreateIndex(r.geometry.coordinates);if(n===a)return null;var i=new this.heapConstructor;i.insert(0,n);var o=this.coordinates.length,s=new Array(o).fill(Infinity),u=new Array(o).fill(-1),h=new Array(o).fill(!1);for(s[n]=0;i.size()>0;){var f=i.extractMin();if(!h[f]){if(f===a)break;h[f]=!0;for(var d,v=e(this.adjacencyList[f]||[]);!(d=v()).done;){var c=d.value,l=s[f]+c.distance;if(l<s[c.node]){s[c.node]=l,u[c.node]=f;var g=this.distanceMeasurement(this.coordinates[c.node],this.coordinates[a]);i.insert(l+g,c.node)}}}}if(u[a]<0)return null;for(var p=[],y=a;y!==n;)p.unshift(this.coordinates[y]),y=u[y];return p.unshift(this.coordinates[n]),{type:"Feature",geometry:{type:"LineString",coordinates:p},properties:{}}},r.getOrCreateIndex=function(t){var e=t[0],r=t[1],n=this.coordinateIndexMap.get(e);n||(n=new Map,this.coordinateIndexMap.set(e,n));var a=n.get(r);return void 0===a&&(a=this.coordinates.length,this.coordinates.push(t),n.set(r,a),this.adjacencyList[a]=[]),a},t}();exports.LineStringGraph=E,exports.TerraRoute=b,exports.createCheapRuler=function(t){var e=1/298.257223563,r=e*(2-e),n=Math.PI/180,a=Math.cos(t*n),i=1/(1-r*(1-a*a)),o=Math.sqrt(i),s=6378.137*n,u=s*o*a,h=s*o*i*(1-r);return function(t,e){for(var r=t[0]-e[0];r<-180;)r+=360;for(;r>180;)r-=360;var n=r*u,a=(t[1]-e[1])*h;return Math.sqrt(n*n+a*a)}},exports.haversineDistance=n;
2
2
  //# sourceMappingURL=terra-route.cjs.map