@maplibre/geojson-vt 6.0.2 → 6.0.4

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.
@@ -42,6 +42,16 @@ export type GeoJSONVTFeatureDiff = {
42
42
  value: unknown;
43
43
  }[];
44
44
  };
45
+ export type ApplySourceDiffResult = {
46
+ /**
47
+ * The features affected by this update, which should be used to invalidate tiles
48
+ */
49
+ affected: GeoJSONVTInternalFeature[];
50
+ /**
51
+ * The updated source data, which should replace the existing source data in the index
52
+ */
53
+ source: GeoJSONVTInternalFeature[];
54
+ };
45
55
  type HashedGeoJSONVTSourceDiff = {
46
56
  removeAll?: boolean | undefined;
47
57
  remove: Set<string | number>;
@@ -55,10 +65,7 @@ type HashedGeoJSONVTSourceDiff = {
55
65
  * @param options
56
66
  * @returns
57
67
  */
58
- export declare function applySourceDiff(source: GeoJSONVTInternalFeature[], dataDiff: GeoJSONVTSourceDiff, options: GeoJSONVTOptions): {
59
- affected: GeoJSONVTInternalFeature[];
60
- source: GeoJSONVTInternalFeature[];
61
- };
68
+ export declare function applySourceDiff(source: GeoJSONVTInternalFeature[], dataDiff: GeoJSONVTSourceDiff, options: GeoJSONVTOptions): ApplySourceDiffResult;
62
69
  /**
63
70
  * Convert a GeoJSON Source Diff to an idempotent hashed representation using Sets and Maps
64
71
  */
@@ -1 +1 @@
1
- {"version":3,"file":"difference.d.ts","sourceRoot":"","sources":["../src/difference.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7B;;OAEG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;OAEG;IACH,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;IAC/B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;OAEG;IACH,qBAAqB,CAAC,EAAE;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,OAAO,CAAC;KAClB,EAAE,CAAC;CACP,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC7B,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC7B,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACtD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,wBAAwB,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB;;;EAwE3H;AAgED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,yBAAyB,CAejF"}
1
+ {"version":3,"file":"difference.d.ts","sourceRoot":"","sources":["../src/difference.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhF,MAAM,MAAM,mBAAmB,GAAG;IAC9B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC7B;;OAEG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IAC/B;;OAEG;IACH,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC;IAC/B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;OAEG;IACH,qBAAqB,CAAC,EAAE;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,OAAO,CAAC;KAClB,EAAE,CAAC;CACP,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC;;OAEG;IACH,QAAQ,EAAE,wBAAwB,EAAE,CAAC;IACrC;;OAEG;IACH,MAAM,EAAE,wBAAwB,EAAE,CAAC;CACtC,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC7B,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAC7B,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACtD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,wBAAwB,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,OAAO,EAAE,gBAAgB,GAAG,qBAAqB,CA6DnJ;AAqED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,yBAAyB,CAejF"}
@@ -680,89 +680,92 @@ function shiftCoords(points, offset) {
680
680
  function applySourceDiff(source, dataDiff, options) {
681
681
  // convert diff to sets/maps for o(1) lookups
682
682
  const diff = diffToHashed(dataDiff);
683
- // collection for features that will be affected by this update
683
+ // collection for features that will be affected by this update and used to invalidate tiles
684
684
  let affected = [];
685
- // full removal - clear everything before applying diff
686
685
  if (diff.removeAll) {
687
686
  affected = source;
688
687
  source = [];
689
688
  }
690
- // remove/add features and collect affected ones
691
689
  if (diff.remove.size || diff.add.size) {
692
690
  const removeFeatures = [];
693
- // collect source features to be removed
691
+ // Collect features to remove (explicit removals + replacements via add)
694
692
  for (const feature of source) {
695
- const { id } = feature;
696
- // explicit feature removal
697
- if (diff.remove.has(id)) {
698
- removeFeatures.push(feature);
699
- // feature with duplicate id being added
700
- }
701
- else if (diff.add.has(id)) {
693
+ if (diff.remove.has(feature.id) || diff.add.has(feature.id)) {
702
694
  removeFeatures.push(feature);
703
695
  }
704
696
  }
705
- // collect affected and remove from source
706
697
  if (removeFeatures.length) {
707
698
  affected.push(...removeFeatures);
708
699
  const removeIds = new Set(removeFeatures.map(f => f.id));
709
700
  source = source.filter(f => !removeIds.has(f.id));
710
701
  }
711
- // convert and add new features
712
702
  if (diff.add.size) {
713
- // projects and adds simplification info
714
703
  let addFeatures = convertToInternal({ type: 'FeatureCollection', features: Array.from(diff.add.values()) }, options);
715
- // wraps features (ie extreme west and extreme east)
716
704
  addFeatures = wrap(addFeatures, options);
717
705
  affected.push(...addFeatures);
718
706
  source.push(...addFeatures);
719
707
  }
720
708
  }
721
709
  if (diff.update.size) {
710
+ // Features can be duplicated across the antimeridian (wrap) in a single tile, so must update all instances with the same id
722
711
  for (const [id, update] of diff.update) {
723
- const featureIndex = source.findIndex(f => f.id === id);
724
- if (featureIndex === -1)
712
+ const oldFeatures = [];
713
+ const keepFeatures = [];
714
+ for (const feature of source) {
715
+ if (feature.id === id) {
716
+ oldFeatures.push(feature);
717
+ }
718
+ else {
719
+ keepFeatures.push(feature);
720
+ }
721
+ }
722
+ if (!oldFeatures.length)
725
723
  continue;
726
- const feature = source[featureIndex];
727
- // get updated geojsonvt simplified feature
728
- const updatedFeature = getUpdatedFeature(feature, update, options);
729
- if (!updatedFeature)
724
+ const updatedFeatures = getUpdatedFeatures(oldFeatures, update, options);
725
+ if (!updatedFeatures.length)
730
726
  continue;
731
- // track both features for invalidation
732
- affected.push(feature, updatedFeature);
733
- // replace old feature with updated feature
734
- source[featureIndex] = updatedFeature;
727
+ affected.push(...oldFeatures, ...updatedFeatures);
728
+ keepFeatures.push(...updatedFeatures);
729
+ source = keepFeatures;
735
730
  }
736
731
  }
737
732
  return { affected, source };
738
733
  }
739
- // return an updated geojsonvt simplified feature
740
- function getUpdatedFeature(vtFeature, update, options) {
734
+ /**
735
+ * Gets updated simplified feature(s) based on a diff update object.
736
+ * @param vtFeatures - the original features
737
+ * @param update - the update object to apply
738
+ * @param options - the options to use for the wrap method
739
+ * @returns Updated features. If geometry is updated, returns new feature(s) converted from geojson and wrapped. If only properties are updated, returns feature(s) with tags updated.
740
+ */
741
+ function getUpdatedFeatures(vtFeatures, update, options) {
741
742
  const changeGeometry = !!update.newGeometry;
742
743
  const changeProps = update.removeAllProperties ||
743
744
  update.removeProperties?.length > 0 ||
744
745
  update.addOrUpdateProperties?.length > 0;
745
- // if geometry changed, need to create new geojson feature and convert to simplified format
746
+ // if geometry changed, need to create a new geojson feature and convert to internal format
746
747
  if (changeGeometry) {
748
+ const vtFeature = vtFeatures[0];
747
749
  const geojsonFeature = {
748
750
  type: 'Feature',
749
751
  id: vtFeature.id,
750
752
  geometry: update.newGeometry,
751
753
  properties: changeProps ? applyPropertyUpdates(vtFeature.tags, update) : vtFeature.tags
752
754
  };
753
- // projects and adds simplification info
754
755
  let features = convertToInternal({ type: 'FeatureCollection', features: [geojsonFeature] }, options);
755
- // wraps features (ie extreme west and extreme east)
756
756
  features = wrap(features, options);
757
- return features[0];
757
+ return features;
758
758
  }
759
- // only properties changed - update tags directly
760
759
  if (changeProps) {
761
- const feature = { ...vtFeature };
762
- feature.tags = applyPropertyUpdates(feature.tags, update);
763
- return feature;
760
+ const updated = [];
761
+ for (const vtFeature of vtFeatures) {
762
+ const feature = { ...vtFeature };
763
+ feature.tags = applyPropertyUpdates(feature.tags, update);
764
+ updated.push(feature);
765
+ }
766
+ return updated;
764
767
  }
765
- return null;
768
+ return [];
766
769
  }
767
770
  /**
768
771
  * helper to apply property updates from a diff update object to a properties object
@@ -1151,11 +1154,6 @@ const OFFSET_PROP = 6;
1151
1154
  * This class allow clustering of geojson points.
1152
1155
  */
1153
1156
  class ClusterTileIndex {
1154
- options;
1155
- trees;
1156
- stride;
1157
- clusterProps;
1158
- points;
1159
1157
  constructor(options) {
1160
1158
  this.options = Object.assign(Object.create(defaultClusterOptions), options);
1161
1159
  this.trees = new Array(this.options.maxZoom + 1);
@@ -1802,16 +1800,12 @@ function transformPoint(x, y, extent, z2, tx, ty) {
1802
1800
  }
1803
1801
 
1804
1802
  class TileIndex {
1805
- options;
1806
- tileCoords;
1807
- /** @internal */
1808
- tiles;
1809
- /** @internal */
1810
- stats = {};
1811
- /** @internal */
1812
- total = 0;
1813
1803
  constructor(options) {
1814
1804
  this.options = options;
1805
+ /** @internal */
1806
+ this.stats = {};
1807
+ /** @internal */
1808
+ this.total = 0;
1815
1809
  this.tiles = {};
1816
1810
  this.tileCoords = [];
1817
1811
  this.stats = {};
@@ -2110,9 +2104,6 @@ class GeoJSONVT {
2110
2104
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2111
2105
  return this.tileIndex.total;
2112
2106
  }
2113
- options;
2114
- source;
2115
- tileIndex;
2116
2107
  constructor(data, options) {
2117
2108
  options = this.options = Object.assign({}, defaultOptions, options);
2118
2109
  const debug = options.debug;
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).geojsonvt={})}(this,(function(t){"use strict";function e(t,o,i,s){let r=s;const a=o+(i-o>>1);let u,l=i-o;const c=t[o],h=t[o+1],d=t[i],p=t[i+1];for(let e=o+3;e<i;e+=3){const o=n(t[e],t[e+1],c,h,d,p);if(o>r)u=e,r=o;else if(o===r){const t=Math.abs(e-a);t<l&&(u=e,l=t)}}r>s&&(u-o>3&&e(t,o,u,s),t[u+2]=r,i-u>3&&e(t,u,i,s))}function n(t,e,n,o,i,s){let r=i-n,a=s-o;if(0!==r||0!==a){const u=((t-n)*r+(e-o)*a)/(r*r+a*a);u>1?(n=i,o=s):u>0&&(n+=r*u,o+=a*u)}return r=t-n,a=e-o,r*r+a*a}function o(t,e,n,o){const s={type:e,geom:n},r={id:null==t?null:t,type:s.type,geometry:s.geom,tags:o,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};switch(s.type){case"Point":case"MultiPoint":case"LineString":i(r,s.geom);break;case"Polygon":i(r,s.geom[0]);break;case"MultiLineString":for(const t of s.geom)i(r,t);break;case"MultiPolygon":for(const t of s.geom)i(r,t[0])}return r}function i(t,e){for(let n=0;n<e.length;n+=3)t.minX=Math.min(t.minX,e[n]),t.minY=Math.min(t.minY,e[n+1]),t.maxX=Math.max(t.maxX,e[n]),t.maxY=Math.max(t.maxY,e[n+1])}function s(t,e){const n=[];switch(t.type){case"FeatureCollection":for(let o=0;o<t.features.length;o++)r(n,t.features[o],e,o);break;case"Feature":r(n,t,e);break;default:r(n,{geometry:t,properties:void 0},e)}return n}function r(t,e,n,i){if(!e.geometry)return;if("GeometryCollection"===e.geometry.type)return void function(t,e,n,o,i){for(const s of n.geometries)r(t,{id:e.id,geometry:s,properties:e.properties},o,i)}(t,e,e.geometry,n,i);const s=e.geometry.coordinates;if(!s?.length)return;const h=function(t,e,n){if(e.promoteId)return t.properties?.[e.promoteId];if(e.generateId)return n||0;return t.id}(e,n,i),d=Math.pow(n.tolerance/((1<<n.maxZoom)*n.extent),2);switch(e.geometry.type){case"Point":return void function(t,e,n,i){const s=[];s.push(l(n.coordinates[0]),c(n.coordinates[1]),0),t.push(o(e,"Point",s,i))}(t,h,e.geometry,e.properties);case"MultiPoint":return void function(t,e,n,i){const s=[];for(const t of n.coordinates)s.push(l(t[0]),c(t[1]),0);t.push(o(e,"MultiPoint",s,i))}(t,h,e.geometry,e.properties);case"LineString":return void function(t,e,n,i,s){const r=[];a(n.coordinates,r,i,!1),t.push(o(e,"LineString",r,s))}(t,h,e.geometry,d,e.properties);case"MultiLineString":return void function(t,e,n,i,s,r){if(s.lineMetrics)for(const s of n.coordinates){const n=[];a(s,n,i,!1),t.push(o(e,"LineString",n,r))}else{const s=[];u(n.coordinates,s,i,!1),t.push(o(e,"MultiLineString",s,r))}}(t,h,e.geometry,d,n,e.properties);case"Polygon":return void function(t,e,n,i,s){const r=[];u(n.coordinates,r,i,!0),t.push(o(e,"Polygon",r,s))}(t,h,e.geometry,d,e.properties);case"MultiPolygon":return void function(t,e,n,i,s){const r=[];for(const t of n.coordinates){const e=[];u(t,e,i,!0),r.push(e)}t.push(o(e,"MultiPolygon",r,s))}(t,h,e.geometry,d,e.properties);default:throw new Error("Input data is not a valid GeoJSON object.")}}function a(t,n,o,i){let s,r,a=0;for(let e=0;e<t.length;e++){const o=l(t[e][0]),u=c(t[e][1]);n.push(o,u,0),e>0&&(a+=i?(s*u-o*r)/2:Math.sqrt(Math.pow(o-s,2)+Math.pow(u-r,2))),s=o,r=u}const u=n.length-3;n[2]=1,o>0&&e(n,0,u,o),n[u+2]=1,n.size=Math.abs(a),n.start=0,n.end=n.size}function u(t,e,n,o){for(let i=0;i<t.length;i++){const s=[];a(t[i],s,n,o),e.push(s)}}function l(t){return t/360+.5}function c(t){const e=Math.sin(t*Math.PI/180),n=.5-.25*Math.log((1+e)/(1-e))/Math.PI;return n<0?0:n>1?1:n}function h(t){const e={type:"Feature",geometry:d(t),properties:t.tags};return null!=t.id&&(e.id=t.id),e}function d(t){const{type:e,geometry:n}=t;switch(e){case"Point":return{type:e,coordinates:f(n[0],n[1])};case"MultiPoint":case"LineString":return{type:e,coordinates:p(n)};case"MultiLineString":case"Polygon":return{type:e,coordinates:n.map((t=>p(t)))};case"MultiPolygon":return{type:e,coordinates:n.map((t=>t.map((t=>p(t)))))}}}function p(t){const e=[];for(let n=0;n<t.length;n+=3)e.push(f(t[n],t[n+1]));return e}function f(t,e){return[g(t),m(e)]}function g(t){return 360*(t-.5)}function m(t){const e=(180-360*t)*Math.PI/180;return 360*Math.atan(Math.exp(e))/Math.PI-90}var y;function x(t,e,n,o,i,s,r,a){if(o/=e,s>=(n/=e)&&r<o)return t;if(r<n||s>=o)return null;const u=[];for(const e of t){const t=i===y.X?e.minX:e.minY,s=i===y.X?e.maxX:e.maxY;if(t>=n&&s<o)u.push(e);else if(!(s<n||t>=o))switch(e.type){case"Point":case"MultiPoint":M(e,u,n,o,i);continue;case"LineString":w(e,u,n,o,i,a);continue;case"MultiLineString":P(e,u,n,o,i);continue;case"Polygon":I(e,u,n,o,i);continue;case"MultiPolygon":v(e,u,n,o,i);continue}}return u.length?u:null}function M(t,e,n,i,s){const r=[];if(function(t,e,n,o,i){for(let s=0;s<t.length;s+=3){const r=t[s+i];r>=n&&r<=o&&A(e,t[s],t[s+1],t[s+2])}}(t.geometry,r,n,i,s),!r.length)return;const a=3===r.length?"Point":"MultiPoint";e.push(o(t.id,a,r,t.tags))}function w(t,e,n,i,s,r){const a=[];if(b(t.geometry,a,n,i,s,!1,r.lineMetrics),a.length)if(r.lineMetrics)for(const n of a)e.push(o(t.id,"LineString",n,t.tags));else a.length>1?e.push(o(t.id,"MultiLineString",a,t.tags)):e.push(o(t.id,"LineString",a[0],t.tags))}function P(t,e,n,i,s){const r=[];z(t.geometry,r,n,i,s,!1),r.length&&(1!==r.length?e.push(o(t.id,"MultiLineString",r,t.tags)):e.push(o(t.id,"LineString",r[0],t.tags)))}function I(t,e,n,i,s){const r=[];z(t.geometry,r,n,i,s,!0),r.length&&e.push(o(t.id,"Polygon",r,t.tags))}function v(t,e,n,i,s){const r=[];for(const e of t.geometry){const t=[];z(e,t,n,i,s,!0),t.length&&r.push(t)}r.length&&e.push(o(t.id,"MultiPolygon",r,t.tags))}function b(t,e,n,o,i,s,r){let a=S(t);const u=i===y.X?E:T;let l,c,h=t.start;for(let d=0;d<t.length-3;d+=3){const p=t[d],f=t[d+1],g=t[d+2],m=t[d+3],x=t[d+4],M=i===y.X?p:f,w=i===y.X?m:x;let P=!1;r&&(l=Math.sqrt(Math.pow(p-m,2)+Math.pow(f-x,2))),M<n?w>n&&(c=u(a,p,f,m,x,n),r&&(a.start=h+l*c)):M>o?w<o&&(c=u(a,p,f,m,x,o),r&&(a.start=h+l*c)):A(a,p,f,g),w<n&&M>=n&&(c=u(a,p,f,m,x,n),P=!0),w>o&&M<=o&&(c=u(a,p,f,m,x,o),P=!0),!s&&P&&(r&&(a.end=h+l*c),e.push(a),a=S(t)),r&&(h+=l)}let d=t.length-3;const p=t[d],f=t[d+1],g=t[d+2],m=i===y.X?p:f;m>=n&&m<=o&&A(a,p,f,g),d=a.length-3,s&&d>=3&&(a[d]!==a[0]||a[d+1]!==a[1])&&A(a,a[0],a[1],a[2]),a.length&&e.push(a)}function S(t){const e=[];return e.size=t.size,e.start=t.start,e.end=t.end,e}function z(t,e,n,o,i,s){for(const r of t)b(r,e,n,o,i,s,!1)}function A(t,e,n,o){t.push(e,n,o)}function E(t,e,n,o,i,s){const r=(s-e)/(o-e);return A(t,s,n+(i-n)*r,1),r}function T(t,e,n,o,i,s){const r=(s-n)/(i-n);return A(t,e+(o-e)*r,s,1),r}function X(t,e){const n=e.buffer/e.extent;let o=t;const i=x(t,1,-1-n,n,y.X,-1,2,e),s=x(t,1,1-n,2+n,y.X,-1,2,e);return i||s?(o=x(t,1,-n,1+n,y.X,-1,2,e)||[],i&&(o=Y(i,1).concat(o)),s&&(o=o.concat(Y(s,-1))),o):o}function Y(t,e){const n=[];for(const i of t)switch(i.type){case"Point":case"MultiPoint":case"LineString":{const t=C(i.geometry,e);n.push(o(i.id,i.type,t,i.tags));continue}case"MultiLineString":case"Polygon":{const t=[];for(const n of i.geometry)t.push(C(n,e));n.push(o(i.id,i.type,t,i.tags));continue}case"MultiPolygon":{const t=[];for(const n of i.geometry){const o=[];for(const t of n)o.push(C(t,e));t.push(o)}n.push(o(i.id,i.type,t,i.tags));continue}}return n}function C(t,e){const n=[];n.size=t.size,void 0!==t.start&&(n.start=t.start,n.end=t.end);for(let o=0;o<t.length;o+=3)n.push(t[o]+e,t[o+1],t[o+2]);return n}function L(t,e,n){const o=function(t){if(!t)return{remove:new Set,add:new Map,update:new Map};const e={removeAll:t.removeAll,remove:new Set(t.remove||[]),add:new Map(t.add?.map((t=>[t.id,t]))),update:new Map(t.update?.map((t=>[t.id,t])))};return e}(e);let i=[];if(o.removeAll&&(i=t,t=[]),o.remove.size||o.add.size){const e=[];for(const n of t){const{id:t}=n;(o.remove.has(t)||o.add.has(t))&&e.push(n)}if(e.length){i.push(...e);const n=new Set(e.map((t=>t.id)));t=t.filter((t=>!n.has(t.id)))}if(o.add.size){let e=s({type:"FeatureCollection",features:Array.from(o.add.values())},n);e=X(e,n),i.push(...e),t.push(...e)}}if(o.update.size)for(const[e,s]of o.update){const o=t.findIndex((t=>t.id===e));if(-1===o)continue;const r=t[o],a=O(r,s,n);a&&(i.push(r,a),t[o]=a)}return{affected:i,source:t}}function O(t,e,n){const o=!!e.newGeometry,i=e.removeAllProperties||e.removeProperties?.length>0||e.addOrUpdateProperties?.length>0;if(o){let o=s({type:"FeatureCollection",features:[{type:"Feature",id:t.id,geometry:e.newGeometry,properties:i?_(t.tags,e):t.tags}]},n);return o=X(o,n),o[0]}if(i){const n={...t};return n.tags=_(n.tags,e),n}return null}function _(t,e){if(e.removeAllProperties)return{};const n={...t||{}};if(e.removeProperties)for(const t of e.removeProperties)delete n[t];if(e.addOrUpdateProperties)for(const{key:t,value:o}of e.addOrUpdateProperties)n[t]=o;return n}!function(t){t[t.X=0]="X",t[t.Y=1]="Y"}(y||(y={}));const Z=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];class F{static from(t){if(!(t instanceof ArrayBuffer))throw new Error("Data must be an instance of ArrayBuffer.");const[e,n]=new Uint8Array(t,0,2);if(219!==e)throw new Error("Data does not appear to be in a KDBush format.");const o=n>>4;if(1!==o)throw new Error(`Got v${o} data when expected v1.`);const i=Z[15&n];if(!i)throw new Error("Unrecognized array type.");const[s]=new Uint16Array(t,2,1),[r]=new Uint32Array(t,4,1);return new F(r,s,i,t)}constructor(t,e=64,n=Float64Array,o){if(isNaN(t)||t<0)throw new Error(`Unpexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.ArrayType=n,this.IndexArrayType=t<65536?Uint16Array:Uint32Array;const i=Z.indexOf(this.ArrayType),s=2*t*this.ArrayType.BYTES_PER_ELEMENT,r=t*this.IndexArrayType.BYTES_PER_ELEMENT,a=(8-r%8)%8;if(i<0)throw new Error(`Unexpected typed array class: ${n}.`);o&&o instanceof ArrayBuffer?(this.data=o,this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+r+a,2*t),this._pos=2*t,this._finished=!0):(this.data=new ArrayBuffer(8+s+r+a),this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+r+a,2*t),this._pos=0,this._finished=!1,new Uint8Array(this.data,0,2).set([219,16+i]),new Uint16Array(this.data,2,1)[0]=e,new Uint32Array(this.data,4,1)[0]=t)}add(t,e){const n=this._pos>>1;return this.ids[n]=n,this.coords[this._pos++]=t,this.coords[this._pos++]=e,n}finish(){const t=this._pos>>1;if(t!==this.numItems)throw new Error(`Added ${t} items when expected ${this.numItems}.`);return U(this.ids,this.coords,this.nodeSize,0,this.numItems-1,0),this._finished=!0,this}range(t,e,n,o){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:i,coords:s,nodeSize:r}=this,a=[0,i.length-1,0],u=[];for(;a.length;){const l=a.pop()||0,c=a.pop()||0,h=a.pop()||0;if(c-h<=r){for(let r=h;r<=c;r++){const a=s[2*r],l=s[2*r+1];a>=t&&a<=n&&l>=e&&l<=o&&u.push(i[r])}continue}const d=h+c>>1,p=s[2*d],f=s[2*d+1];p>=t&&p<=n&&f>=e&&f<=o&&u.push(i[d]),(0===l?t<=p:e<=f)&&(a.push(h),a.push(d-1),a.push(1-l)),(0===l?n>=p:o>=f)&&(a.push(d+1),a.push(c),a.push(1-l))}return u}within(t,e,n){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:o,coords:i,nodeSize:s}=this,r=[0,o.length-1,0],a=[],u=n*n;for(;r.length;){const l=r.pop()||0,c=r.pop()||0,h=r.pop()||0;if(c-h<=s){for(let n=h;n<=c;n++)k(i[2*n],i[2*n+1],t,e)<=u&&a.push(o[n]);continue}const d=h+c>>1,p=i[2*d],f=i[2*d+1];k(p,f,t,e)<=u&&a.push(o[d]),(0===l?t-n<=p:e-n<=f)&&(r.push(h),r.push(d-1),r.push(1-l)),(0===l?t+n>=p:e+n>=f)&&(r.push(d+1),r.push(c),r.push(1-l))}return a}}function U(t,e,n,o,i,s){if(i-o<=n)return;const r=o+i>>1;D(t,e,r,o,i,s),U(t,e,n,o,r-1,1-s),U(t,e,n,r+1,i,1-s)}function D(t,e,n,o,i,s){for(;i>o;){if(i-o>600){const r=i-o+1,a=n-o+1,u=Math.log(r),l=.5*Math.exp(2*u/3),c=.5*Math.sqrt(u*l*(r-l)/r)*(a-r/2<0?-1:1);D(t,e,n,Math.max(o,Math.floor(n-a*l/r+c)),Math.min(i,Math.floor(n+(r-a)*l/r+c)),s)}const r=e[2*n+s];let a=o,u=i;for(j(t,e,o,n),e[2*i+s]>r&&j(t,e,o,i);a<u;){for(j(t,e,a,u),a++,u--;e[2*a+s]<r;)a++;for(;e[2*u+s]>r;)u--}e[2*o+s]===r?j(t,e,o,u):(u++,j(t,e,u,i)),u<=n&&(o=u+1),n<=u&&(i=u-1)}}function j(t,e,n,o){N(t,n,o),N(e,2*n,2*o),N(e,2*n+1,2*o+1)}function N(t,e,n){const o=t[e];t[e]=t[n],t[n]=o}function k(t,e,n,o){const i=t-n,s=e-o;return i*i+s*s}const $={minZoom:0,maxZoom:16,minPoints:2,radius:40,extent:512,nodeSize:64,log:!1,generateId:!1,reduce:null,map:t=>t},G=3,B=5,J=6;class q{options;trees;stride;clusterProps;points;constructor(t){this.options=Object.assign(Object.create($),t),this.trees=new Array(this.options.maxZoom+1),this.stride=this.options.reduce?7:6,this.clusterProps=[],this.points=[]}load(t){const e=[];for(const n of t){if(!n.geometry)continue;const[t,o]=n.geometry.coordinates,[i,s]=[l(t),c(o)],r={id:n.id,type:"Point",geometry:[i,s],tags:n.properties};e.push(r)}this.createIndex(e)}initialize(t){const e=[];for(const n of t)"Point"===n.type&&e.push(n);this.createIndex(e)}updateIndex(t,e,n){this.options=Object.assign(Object.create($),n.clusterOptions),this.initialize(t)}createIndex(t){const{log:e,minZoom:n,maxZoom:o}=this.options;e&&console.time("total time");const i=`prepare ${t.length} points`;e&&console.time(i),this.points=t;const s=[];for(let e=0;e<t.length;e++){const n=t[e];if(!n?.geometry)continue;let[o,i]=n.geometry;o=Math.fround(o),i=Math.fround(i),s.push(o,i,1/0,e,-1,1),this.options.reduce&&s.push(0)}let r=this.trees[o+1]=this.createTree(s);e&&console.timeEnd(i);for(let t=o;t>=n;t--){const n=Date.now();r=this.trees[t]=this.createTree(this.cluster(r,t)),e&&console.log("z%d: %d clusters in %dms",t,r.numItems,Date.now()-n)}e&&console.timeEnd("total time")}getClusters(t,e){return this.getClustersInternal(t,e).map((t=>h(t)))}getClustersInternal(t,e){let n=((t[0]+180)%360+360)%360-180;const o=Math.max(-90,Math.min(90,t[1]));let i=180===t[2]?180:((t[2]+180)%360+360)%360-180;const s=Math.max(-90,Math.min(90,t[3]));if(t[2]-t[0]>=360)n=-180,i=180;else if(n>i){const t=this.getClustersInternal([n,o,180,s],e),r=this.getClustersInternal([-180,o,i,s],e);return t.concat(r)}const r=this.trees[this.limitZoom(e)],a=r.range(l(n),c(s),l(i),c(o)),u=r.flatData,h=[];for(const t of a){const e=this.stride*t;h.push(u[e+B]>1?R(u,e,this.clusterProps):this.points[u[e+G]])}return h}getChildren(t){const e=this.getOriginId(t),n=this.getOriginZoom(t),o=new Error("No cluster with the specified id: "+t),i=this.trees[n];if(!i)throw o;const s=i.flatData;if(e*this.stride>=s.length)throw o;const r=this.options.radius/(this.options.extent*Math.pow(2,n-1)),a=s[e*this.stride],u=s[e*this.stride+1],l=i.within(a,u,r),c=[];for(const e of l){const n=e*this.stride;s[n+4]===t&&c.push(s[n+B]>1?V(s,n,this.clusterProps):h(this.points[s[n+G]]))}if(0===c.length)throw o;return c}getLeaves(t,e,n){e=e||10,n=n||0;const o=[];return this.appendLeaves(o,t,e,n,0),o}getTile(t,e,n){const o=this.trees[this.limitZoom(t)];if(!o)return null;const i=Math.pow(2,t),{extent:s,radius:r}=this.options,a=r/s,u=(n-a)/i,l=(n+1+a)/i,c={transformed:!0,features:[],source:null,x:e,y:n,z:t};return this.addTileFeatures(o.range((e-a)/i,u,(e+1+a)/i,l),o.flatData,e,n,i,c),0===e&&this.addTileFeatures(o.range(1-a/i,u,1,l),o.flatData,i,n,i,c),e===i-1&&this.addTileFeatures(o.range(0,u,a/i,l),o.flatData,-1,n,i,c),c}getClusterExpansionZoom(t){return this.getOriginZoom(t)}appendLeaves(t,e,n,o,i){const s=this.getChildren(e);for(const e of s){const s=e.properties;if(s?.cluster?i+s.point_count<=o?i+=s.point_count:i=this.appendLeaves(t,s.cluster_id,n,o,i):i<o?i++:t.push(e),t.length===n)break}return i}createTree(t){const e=new F(t.length/this.stride|0,this.options.nodeSize,Float32Array);for(let n=0;n<t.length;n+=this.stride)e.add(t[n],t[n+1]);return e.finish(),e.flatData=t,e.data=null,e}addTileFeatures(t,e,n,o,i,s){for(const r of t){const t=r*this.stride,a=e[t+B]>1;let u,l,c;if(a)u=K(e,t,this.clusterProps),l=e[t],c=e[t+1];else{const n=this.points[e[t+G]];u=n.tags,[l,c]=n.geometry}const h={type:1,geometry:[[Math.round(this.options.extent*(l*i-n)),Math.round(this.options.extent*(c*i-o))]],tags:u};let d;d=a||this.options.generateId?e[t+G]:this.points[e[t+G]].id,void 0!==d&&(h.id=d),s.features.push(h)}}limitZoom(t){return Math.max(this.options.minZoom,Math.min(Math.floor(+t),this.options.maxZoom+1))}cluster(t,e){const{radius:n,extent:o,reduce:i,minPoints:s}=this.options,r=n/(o*Math.pow(2,e)),a=t.flatData,u=[],l=this.stride;for(let n=0;n<a.length;n+=l){if(a[n+2]<=e)continue;a[n+2]=e;const o=a[n],c=a[n+1],h=t.within(a[n],a[n+1],r),d=a[n+B];let p=d;for(const t of h){const n=t*l;a[n+2]>e&&(p+=a[n+B])}if(p>d&&p>=s){let t,s=o*d,r=c*d,f=-1;const g=(n/l<<5)+(e+1)+this.points.length;for(const o of h){const u=o*l;if(a[u+2]<=e)continue;a[u+2]=e;const c=a[u+B];s+=a[u]*c,r+=a[u+1]*c,a[u+4]=g,i&&(t||(t=this.map(a,n,!0),f=this.clusterProps.length,this.clusterProps.push(t)),i(t,this.map(a,u)))}a[n+4]=g,u.push(s/p,r/p,1/0,g,-1,p),i&&u.push(f)}else{for(let t=0;t<l;t++)u.push(a[n+t]);if(p>1)for(const t of h){const n=t*l;if(!(a[n+2]<=e)){a[n+2]=e;for(let t=0;t<l;t++)u.push(a[n+t])}}}}return u}getOriginId(t){return t-this.points.length>>5}getOriginZoom(t){return(t-this.points.length)%32}map(t,e,n){if(t[e+B]>1){const o=this.clusterProps[t[e+J]];return n?Object.assign({},o):o}const o=this.points[t[e+G]].tags,i=this.options.map(o);return n&&i===o?Object.assign({},i):i}}function R(t,e,n){return{id:t[e+G],type:"Point",tags:K(t,e,n),geometry:[t[e],t[e+1]]}}function V(t,e,n){return{type:"Feature",id:t[e+G],properties:K(t,e,n),geometry:{type:"Point",coordinates:[g(t[e]),m(t[e+1])]}}}function K(t,e,n){const o=t[e+B],i=o>=1e4?`${Math.round(o/1e3)}k`:o>=1e3?Math.round(o/100)/10+"k":o,s=t[e+J],r=-1===s?{}:Object.assign({},n[s]);return Object.assign(r,{cluster:!0,cluster_id:t[e+G],point_count:o,point_count_abbreviated:i})}const H="geojsonvt_clip_start",Q="geojsonvt_clip_end";function W(t,e,n,o,i){const s=e===i.maxZoom?0:i.tolerance/((1<<e)*i.extent),r={transformed:!1,features:[],source:null,x:n,y:o,z:e,minX:2,minY:1,maxX:-1,maxY:0,numPoints:0,numSimplified:0,numFeatures:t.length};for(const e of t)tt(r,e,s,i);return r}function tt(t,e,n,o){switch(t.minX=Math.min(t.minX,e.minX),t.minY=Math.min(t.minY,e.minY),t.maxX=Math.max(t.maxX,e.maxX),t.maxY=Math.max(t.maxY,e.maxY),e.type){case"Point":case"MultiPoint":return void function(t,e){const n=[];for(let o=0;o<e.geometry.length;o+=3)n.push(e.geometry[o],e.geometry[o+1]),t.numPoints++,t.numSimplified++;if(!n.length)return;const o={type:1,tags:e.tags||null,geometry:n};null!==e.id&&(o.id=e.id);t.features.push(o)}(t,e);case"LineString":return void function(t,e,n,o){const i=[];if(et(i,e.geometry,t,n,!1,!1),!i.length)return;let s=e.tags||null;if(o.lineMetrics){s={};for(const t in e.tags)s[t]=e.tags[t];s[H]=e.geometry.start/e.geometry.size,s[Q]=e.geometry.end/e.geometry.size}const r={type:2,tags:s,geometry:i};null!==e.id&&(r.id=e.id);t.features.push(r)}(t,e,n,o);case"MultiLineString":case"Polygon":return void function(t,e,n){const o=[];for(let i=0;i<e.geometry.length;i++)et(o,e.geometry[i],t,n,"Polygon"===e.type,0===i);if(!o.length)return;const i={type:"Polygon"===e.type?3:2,tags:e.tags||null,geometry:o};null!==e.id&&(i.id=e.id);t.features.push(i)}(t,e,n);case"MultiPolygon":return void function(t,e,n){const o=[];for(let i=0;i<e.geometry.length;i++){const s=e.geometry[i];for(let e=0;e<s.length;e++)et(o,s[e],t,n,!0,0===e)}if(!o.length)return;const i={type:3,tags:e.tags||null,geometry:o};null!==e.id&&(i.id=e.id);t.features.push(i)}(t,e,n)}}function et(t,e,n,o,i,s){const r=o*o;if(o>0&&e.size<(i?r:o))return void(n.numPoints+=e.length/3);const a=[];for(let t=0;t<e.length;t+=3)(0===o||e[t+2]>r)&&(n.numSimplified++,a.push(e[t],e[t+1])),n.numPoints++;i&&function(t,e){let n=0;for(let e=0,o=t.length,i=o-2;e<o;i=e,e+=2)n+=(t[e]-t[i])*(t[e+1]+t[i+1]);if(n>0!==e)return;for(let e=0,n=t.length;e<n/2;e+=2){const o=t[e],i=t[e+1];t[e]=t[n-2-e],t[e+1]=t[n-1-e],t[n-2-e]=o,t[n-1-e]=i}}(a,s),t.push(a)}function nt(t,e){if(t.transformed)return t;const n=1<<t.z,o=t.x,i=t.y;for(const s of t.features)1===s.type?ot(s,e,n,o,i):it(s,e,n,o,i);return t.transformed=!0,t}function ot(t,e,n,o,i){const s=t,r=t.geometry,a=[];for(let t=0;t<r.length;t+=2)a.push(st(r[t],r[t+1],e,n,o,i));return s.geometry=a,s}function it(t,e,n,o,i){const s=t,r=t.geometry,a=[];for(const t of r){const s=[];for(let r=0;r<t.length;r+=2)s.push(st(t[r],t[r+1],e,n,o,i));a.push(s)}return s.geometry=a,s}function st(t,e,n,o,i,s){return[Math.round(n*(t*o-i)),Math.round(n*(e*o-s))]}class rt{options;tileCoords;tiles;stats={};total=0;constructor(t){this.options=t,this.tiles={},this.tileCoords=[],this.stats={},this.total=0}initialize(t){this.splitTile(t,0,0,0),this.options.debug&&(t.length&&console.log("features: %d, points: %d",this.tiles[0].numFeatures,this.tiles[0].numPoints),console.timeEnd("generate tiles"),console.log("tiles generated:",this.total,JSON.stringify(this.stats)))}updateIndex(t,e,n){n.debug>1&&(console.log("invalidating tiles"),console.time("invalidating")),this.invalidateTiles(e),n.debug>1&&console.timeEnd("invalidating");const[o,i,s]=[0,0,0],r=W(t,o,i,s,n);r.source=t;const a=at(o,i,s);if(this.tiles[a]=r,this.tileCoords.push({z:o,x:i,y:s,id:a}),n.debug){const t=`z${o}`;this.stats[t]=(this.stats[t]||0)+1,this.total++}}getClusterExpansionZoom(t){return null}getChildren(t){return null}getLeaves(t,e,n){return null}getTile(t,e,n){const{extent:o,debug:i}=this.options,s=1<<t,r=at(t,e=e+s&s-1,n);if(this.tiles[r])return nt(this.tiles[r],o);i>1&&console.log("drilling down to z%d-%d-%d",t,e,n);let a,u=t,l=e,c=n;for(;!a&&u>0;)u--,l>>=1,c>>=1,a=this.tiles[at(u,l,c)];return a?.source?(i>1&&(console.log("found parent tile z%d-%d-%d",u,l,c),console.time("drilling down")),this.splitTile(a.source,u,l,c,t,e,n),i>1&&console.timeEnd("drilling down"),this.tiles[r]?nt(this.tiles[r],o):null):null}splitTile(t,e,n,o,i,s,r){const a=[t,e,n,o],u=this.options,l=u.debug;for(;a.length;){o=a.pop(),n=a.pop(),e=a.pop(),t=a.pop();const c=1<<e,h=at(e,n,o);let d=this.tiles[h];if(!d&&(l>1&&console.time("creation"),d=this.tiles[h]=W(t,e,n,o,u),this.tileCoords.push({z:e,x:n,y:o,id:h}),l)){l>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",e,n,o,d.numFeatures,d.numPoints,d.numSimplified),console.timeEnd("creation"));const t=`z${e}`;this.stats[t]=(this.stats[t]||0)+1,this.total++}if(d.source=t,null==i){if(e===u.indexMaxZoom||d.numPoints<=u.indexMaxPoints)continue}else{if(e===u.maxZoom||e===i)continue;if(null!=i){const t=i-e;if(n!==s>>t||o!==r>>t)continue}}if(d.source=null,!t.length)continue;l>1&&console.time("clipping");const p=.5*u.buffer/u.extent,f=.5-p,g=.5+p,m=1+p;let M=null,w=null,P=null,I=null;const v=x(t,c,n-p,n+g,y.X,d.minX,d.maxX,u),b=x(t,c,n+f,n+m,y.X,d.minX,d.maxX,u);v&&(M=x(v,c,o-p,o+g,y.Y,d.minY,d.maxY,u),w=x(v,c,o+f,o+m,y.Y,d.minY,d.maxY,u)),b&&(P=x(b,c,o-p,o+g,y.Y,d.minY,d.maxY,u),I=x(b,c,o+f,o+m,y.Y,d.minY,d.maxY,u)),l>1&&console.timeEnd("clipping"),a.push(M||[],e+1,2*n,2*o),a.push(w||[],e+1,2*n,2*o+1),a.push(P||[],e+1,2*n+1,2*o),a.push(I||[],e+1,2*n+1,2*o+1)}}invalidateTiles(t){if(!t.length)return;const e=this.options,{debug:n}=e;let o=1/0,i=-1/0,s=1/0,r=-1/0;for(const e of t)o=Math.min(o,e.minX),i=Math.max(i,e.maxX),s=Math.min(s,e.minY),r=Math.max(r,e.maxY);const a=e.buffer/e.extent,u=new Set;for(const e in this.tiles){const l=this.tiles[e],c=1<<l.z,h=(l.x-a)/c,d=(l.x+1+a)/c,p=(l.y-a)/c,f=(l.y+1+a)/c;if(i<h||o>=d||r<p||s>=f)continue;let g=!1;for(const e of t)if(e.maxX>=h&&e.minX<d&&e.maxY>=p&&e.minY<f){g=!0;break}if(g){if(n){n>1&&console.log("invalidate tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",l.z,l.x,l.y,l.numFeatures,l.numPoints,l.numSimplified);const t=`z${l.z}`;this.stats[t]=(this.stats[t]||0)-1,this.total--}delete this.tiles[e],u.add(e)}}u.size&&(this.tileCoords=this.tileCoords.filter((t=>!u.has(t.id))))}}function at(t,e,n){return 32*((1<<t)*n+e)+t}const ut={maxZoom:14,indexMaxZoom:5,indexMaxPoints:1e5,tolerance:3,extent:4096,buffer:64,lineMetrics:!1,promoteId:null,generateId:!1,updateable:!1,cluster:!1,clusterOptions:$,debug:0};t.GEOJSONVT_CLIP_END=Q,t.GEOJSONVT_CLIP_START=H,t.GeoJSONVT=class{get tiles(){return this.tileIndex?.tiles??{}}get stats(){return this.tileIndex.stats}get total(){return this.tileIndex.total}options;source;tileIndex;constructor(t,e){const n=(e=this.options=Object.assign({},ut,e)).debug;if(n&&console.time("preprocess data"),e.maxZoom<0||e.maxZoom>24)throw new Error("maxZoom should be in the 0-24 range");if(e.promoteId&&e.generateId)throw new Error("promoteId and generateId cannot be used together.");let o=s(t,e);n&&(console.timeEnd("preprocess data"),console.log("index: maxZoom: %d, maxPoints: %d",e.indexMaxZoom,e.indexMaxPoints),console.time("generate tiles")),o=X(o,e),e.updateable&&(this.source=o),this.initializeIndex(o,e)}initializeIndex(t,e){this.tileIndex=e.cluster?new q(e.clusterOptions):new rt(e),t.length&&this.tileIndex.initialize(t)}getTile(t,e,n){return e=+e,n=+n,(t=+t)<0||t>24?null:this.tileIndex.getTile(t,e,n)}updateData(t,e){const n=this.options;if(!n.updateable)throw new Error("to update tile geojson `updateable` option must be set to true");let{affected:o,source:i}=L(this.source,t,n);e&&({affected:o,source:i}=this.filterUpdate(i,o,e)),o.length&&(this.source=i,this.tileIndex.updateIndex(i,o,n))}filterUpdate(t,e,n){const o=new Set;for(const i of t)null!=i.id&&(n(h(i))||(e.push(i),o.add(i.id)));return{affected:e,source:t=t.filter((t=>!o.has(t.id)))}}getData(){if(!this.options.updateable)throw new Error("to retrieve data the `updateable` option must be set to true");return{type:"FeatureCollection",features:this.source.map((t=>h(t)))}}updateClusterOptions(t,e){const n=this.options.cluster;this.options.cluster=t,this.options.clusterOptions=e,n!=t?this.initializeIndex(this.source,this.options):this.tileIndex.updateIndex(this.source,[],this.options)}getClusterExpansionZoom(t){return this.tileIndex.getClusterExpansionZoom(t)}getClusterChildren(t){return this.tileIndex.getChildren(t)}getClusterLeaves(t,e,n){return this.tileIndex.getLeaves(t,e,n)}},t.Supercluster=q,t.geoJSONToTile=function(t,e,n,o,i={}){i={...ut,...i};const{wrap:r=!1,clip:a=!1}=i;let u=s(t,i);if(r&&(u=X(u,i)),a||i.lineMetrics){const t=1<<e,s=i.buffer/i.extent,r=x(u,t,n-s,n+1+s,y.X,-1,2,i);u=x(r||[],t,o-s,o+1+s,y.Y,-1,2,i)}return nt(W(u??[],e,n,o,i),i.extent)}}));
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).geojsonvt={})}(this,(function(t){"use strict";function e(t,o,s,i){let r=i;const a=o+(s-o>>1);let u,c=s-o;const l=t[o],h=t[o+1],d=t[s],p=t[s+1];for(let e=o+3;e<s;e+=3){const o=n(t[e],t[e+1],l,h,d,p);if(o>r)u=e,r=o;else if(o===r){const t=Math.abs(e-a);t<c&&(u=e,c=t)}}r>i&&(u-o>3&&e(t,o,u,i),t[u+2]=r,s-u>3&&e(t,u,s,i))}function n(t,e,n,o,s,i){let r=s-n,a=i-o;if(0!==r||0!==a){const u=((t-n)*r+(e-o)*a)/(r*r+a*a);u>1?(n=s,o=i):u>0&&(n+=r*u,o+=a*u)}return r=t-n,a=e-o,r*r+a*a}function o(t,e,n,o){const i={type:e,geom:n},r={id:null==t?null:t,type:i.type,geometry:i.geom,tags:o,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0};switch(i.type){case"Point":case"MultiPoint":case"LineString":s(r,i.geom);break;case"Polygon":s(r,i.geom[0]);break;case"MultiLineString":for(const t of i.geom)s(r,t);break;case"MultiPolygon":for(const t of i.geom)s(r,t[0])}return r}function s(t,e){for(let n=0;n<e.length;n+=3)t.minX=Math.min(t.minX,e[n]),t.minY=Math.min(t.minY,e[n+1]),t.maxX=Math.max(t.maxX,e[n]),t.maxY=Math.max(t.maxY,e[n+1])}function i(t,e){const n=[];switch(t.type){case"FeatureCollection":for(let o=0;o<t.features.length;o++)r(n,t.features[o],e,o);break;case"Feature":r(n,t,e);break;default:r(n,{geometry:t,properties:void 0},e)}return n}function r(t,e,n,s){if(!e.geometry)return;if("GeometryCollection"===e.geometry.type)return void function(t,e,n,o,s){for(const i of n.geometries)r(t,{id:e.id,geometry:i,properties:e.properties},o,s)}(t,e,e.geometry,n,s);const i=e.geometry.coordinates;if(!i?.length)return;const h=function(t,e,n){if(e.promoteId)return t.properties?.[e.promoteId];if(e.generateId)return n||0;return t.id}(e,n,s),d=Math.pow(n.tolerance/((1<<n.maxZoom)*n.extent),2);switch(e.geometry.type){case"Point":return void function(t,e,n,s){const i=[];i.push(c(n.coordinates[0]),l(n.coordinates[1]),0),t.push(o(e,"Point",i,s))}(t,h,e.geometry,e.properties);case"MultiPoint":return void function(t,e,n,s){const i=[];for(const t of n.coordinates)i.push(c(t[0]),l(t[1]),0);t.push(o(e,"MultiPoint",i,s))}(t,h,e.geometry,e.properties);case"LineString":return void function(t,e,n,s,i){const r=[];a(n.coordinates,r,s,!1),t.push(o(e,"LineString",r,i))}(t,h,e.geometry,d,e.properties);case"MultiLineString":return void function(t,e,n,s,i,r){if(i.lineMetrics)for(const i of n.coordinates){const n=[];a(i,n,s,!1),t.push(o(e,"LineString",n,r))}else{const i=[];u(n.coordinates,i,s,!1),t.push(o(e,"MultiLineString",i,r))}}(t,h,e.geometry,d,n,e.properties);case"Polygon":return void function(t,e,n,s,i){const r=[];u(n.coordinates,r,s,!0),t.push(o(e,"Polygon",r,i))}(t,h,e.geometry,d,e.properties);case"MultiPolygon":return void function(t,e,n,s,i){const r=[];for(const t of n.coordinates){const e=[];u(t,e,s,!0),r.push(e)}t.push(o(e,"MultiPolygon",r,i))}(t,h,e.geometry,d,e.properties);default:throw new Error("Input data is not a valid GeoJSON object.")}}function a(t,n,o,s){let i,r,a=0;for(let e=0;e<t.length;e++){const o=c(t[e][0]),u=l(t[e][1]);n.push(o,u,0),e>0&&(a+=s?(i*u-o*r)/2:Math.sqrt(Math.pow(o-i,2)+Math.pow(u-r,2))),i=o,r=u}const u=n.length-3;n[2]=1,o>0&&e(n,0,u,o),n[u+2]=1,n.size=Math.abs(a),n.start=0,n.end=n.size}function u(t,e,n,o){for(let s=0;s<t.length;s++){const i=[];a(t[s],i,n,o),e.push(i)}}function c(t){return t/360+.5}function l(t){const e=Math.sin(t*Math.PI/180),n=.5-.25*Math.log((1+e)/(1-e))/Math.PI;return n<0?0:n>1?1:n}function h(t){const e={type:"Feature",geometry:d(t),properties:t.tags};return null!=t.id&&(e.id=t.id),e}function d(t){const{type:e,geometry:n}=t;switch(e){case"Point":return{type:e,coordinates:f(n[0],n[1])};case"MultiPoint":case"LineString":return{type:e,coordinates:p(n)};case"MultiLineString":case"Polygon":return{type:e,coordinates:n.map((t=>p(t)))};case"MultiPolygon":return{type:e,coordinates:n.map((t=>t.map((t=>p(t)))))}}}function p(t){const e=[];for(let n=0;n<t.length;n+=3)e.push(f(t[n],t[n+1]));return e}function f(t,e){return[g(t),m(e)]}function g(t){return 360*(t-.5)}function m(t){const e=(180-360*t)*Math.PI/180;return 360*Math.atan(Math.exp(e))/Math.PI-90}var y;function x(t,e,n,o,s,i,r,a){if(o/=e,i>=(n/=e)&&r<o)return t;if(r<n||i>=o)return null;const u=[];for(const e of t){const t=s===y.X?e.minX:e.minY,i=s===y.X?e.maxX:e.maxY;if(t>=n&&i<o)u.push(e);else if(!(i<n||t>=o))switch(e.type){case"Point":case"MultiPoint":M(e,u,n,o,s);continue;case"LineString":w(e,u,n,o,s,a);continue;case"MultiLineString":P(e,u,n,o,s);continue;case"Polygon":I(e,u,n,o,s);continue;case"MultiPolygon":v(e,u,n,o,s);continue}}return u.length?u:null}function M(t,e,n,s,i){const r=[];if(function(t,e,n,o,s){for(let i=0;i<t.length;i+=3){const r=t[i+s];r>=n&&r<=o&&A(e,t[i],t[i+1],t[i+2])}}(t.geometry,r,n,s,i),!r.length)return;const a=3===r.length?"Point":"MultiPoint";e.push(o(t.id,a,r,t.tags))}function w(t,e,n,s,i,r){const a=[];if(b(t.geometry,a,n,s,i,!1,r.lineMetrics),a.length)if(r.lineMetrics)for(const n of a)e.push(o(t.id,"LineString",n,t.tags));else a.length>1?e.push(o(t.id,"MultiLineString",a,t.tags)):e.push(o(t.id,"LineString",a[0],t.tags))}function P(t,e,n,s,i){const r=[];z(t.geometry,r,n,s,i,!1),r.length&&(1!==r.length?e.push(o(t.id,"MultiLineString",r,t.tags)):e.push(o(t.id,"LineString",r[0],t.tags)))}function I(t,e,n,s,i){const r=[];z(t.geometry,r,n,s,i,!0),r.length&&e.push(o(t.id,"Polygon",r,t.tags))}function v(t,e,n,s,i){const r=[];for(const e of t.geometry){const t=[];z(e,t,n,s,i,!0),t.length&&r.push(t)}r.length&&e.push(o(t.id,"MultiPolygon",r,t.tags))}function b(t,e,n,o,s,i,r){let a=S(t);const u=s===y.X?E:T;let c,l,h=t.start;for(let d=0;d<t.length-3;d+=3){const p=t[d],f=t[d+1],g=t[d+2],m=t[d+3],x=t[d+4],M=s===y.X?p:f,w=s===y.X?m:x;let P=!1;r&&(c=Math.sqrt(Math.pow(p-m,2)+Math.pow(f-x,2))),M<n?w>n&&(l=u(a,p,f,m,x,n),r&&(a.start=h+c*l)):M>o?w<o&&(l=u(a,p,f,m,x,o),r&&(a.start=h+c*l)):A(a,p,f,g),w<n&&M>=n&&(l=u(a,p,f,m,x,n),P=!0),w>o&&M<=o&&(l=u(a,p,f,m,x,o),P=!0),!i&&P&&(r&&(a.end=h+c*l),e.push(a),a=S(t)),r&&(h+=c)}let d=t.length-3;const p=t[d],f=t[d+1],g=t[d+2],m=s===y.X?p:f;m>=n&&m<=o&&A(a,p,f,g),d=a.length-3,i&&d>=3&&(a[d]!==a[0]||a[d+1]!==a[1])&&A(a,a[0],a[1],a[2]),a.length&&e.push(a)}function S(t){const e=[];return e.size=t.size,e.start=t.start,e.end=t.end,e}function z(t,e,n,o,s,i){for(const r of t)b(r,e,n,o,s,i,!1)}function A(t,e,n,o){t.push(e,n,o)}function E(t,e,n,o,s,i){const r=(i-e)/(o-e);return A(t,i,n+(s-n)*r,1),r}function T(t,e,n,o,s,i){const r=(i-n)/(s-n);return A(t,e+(o-e)*r,i,1),r}function X(t,e){const n=e.buffer/e.extent;let o=t;const s=x(t,1,-1-n,n,y.X,-1,2,e),i=x(t,1,1-n,2+n,y.X,-1,2,e);return s||i?(o=x(t,1,-n,1+n,y.X,-1,2,e)||[],s&&(o=Y(s,1).concat(o)),i&&(o=o.concat(Y(i,-1))),o):o}function Y(t,e){const n=[];for(const s of t)switch(s.type){case"Point":case"MultiPoint":case"LineString":{const t=L(s.geometry,e);n.push(o(s.id,s.type,t,s.tags));continue}case"MultiLineString":case"Polygon":{const t=[];for(const n of s.geometry)t.push(L(n,e));n.push(o(s.id,s.type,t,s.tags));continue}case"MultiPolygon":{const t=[];for(const n of s.geometry){const o=[];for(const t of n)o.push(L(t,e));t.push(o)}n.push(o(s.id,s.type,t,s.tags));continue}}return n}function L(t,e){const n=[];n.size=t.size,void 0!==t.start&&(n.start=t.start,n.end=t.end);for(let o=0;o<t.length;o+=3)n.push(t[o]+e,t[o+1],t[o+2]);return n}function O(t,e,n){const o=function(t){if(!t)return{remove:new Set,add:new Map,update:new Map};const e={removeAll:t.removeAll,remove:new Set(t.remove||[]),add:new Map(t.add?.map((t=>[t.id,t]))),update:new Map(t.update?.map((t=>[t.id,t])))};return e}(e);let s=[];if(o.removeAll&&(s=t,t=[]),o.remove.size||o.add.size){const e=[];for(const n of t)(o.remove.has(n.id)||o.add.has(n.id))&&e.push(n);if(e.length){s.push(...e);const n=new Set(e.map((t=>t.id)));t=t.filter((t=>!n.has(t.id)))}if(o.add.size){let e=i({type:"FeatureCollection",features:Array.from(o.add.values())},n);e=X(e,n),s.push(...e),t.push(...e)}}if(o.update.size)for(const[e,i]of o.update){const o=[],r=[];for(const n of t)n.id===e?o.push(n):r.push(n);if(!o.length)continue;const a=C(o,i,n);a.length&&(s.push(...o,...a),r.push(...a),t=r)}return{affected:s,source:t}}function C(t,e,n){const o=!!e.newGeometry,s=e.removeAllProperties||e.removeProperties?.length>0||e.addOrUpdateProperties?.length>0;if(o){const o=t[0];let r=i({type:"FeatureCollection",features:[{type:"Feature",id:o.id,geometry:e.newGeometry,properties:s?_(o.tags,e):o.tags}]},n);return r=X(r,n),r}if(s){const n=[];for(const o of t){const t={...o};t.tags=_(t.tags,e),n.push(t)}return n}return[]}function _(t,e){if(e.removeAllProperties)return{};const n={...t||{}};if(e.removeProperties)for(const t of e.removeProperties)delete n[t];if(e.addOrUpdateProperties)for(const{key:t,value:o}of e.addOrUpdateProperties)n[t]=o;return n}!function(t){t[t.X=0]="X",t[t.Y=1]="Y"}(y||(y={}));const Z=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];class F{static from(t){if(!(t instanceof ArrayBuffer))throw new Error("Data must be an instance of ArrayBuffer.");const[e,n]=new Uint8Array(t,0,2);if(219!==e)throw new Error("Data does not appear to be in a KDBush format.");const o=n>>4;if(1!==o)throw new Error(`Got v${o} data when expected v1.`);const s=Z[15&n];if(!s)throw new Error("Unrecognized array type.");const[i]=new Uint16Array(t,2,1),[r]=new Uint32Array(t,4,1);return new F(r,i,s,t)}constructor(t,e=64,n=Float64Array,o){if(isNaN(t)||t<0)throw new Error(`Unpexpected numItems value: ${t}.`);this.numItems=+t,this.nodeSize=Math.min(Math.max(+e,2),65535),this.ArrayType=n,this.IndexArrayType=t<65536?Uint16Array:Uint32Array;const s=Z.indexOf(this.ArrayType),i=2*t*this.ArrayType.BYTES_PER_ELEMENT,r=t*this.IndexArrayType.BYTES_PER_ELEMENT,a=(8-r%8)%8;if(s<0)throw new Error(`Unexpected typed array class: ${n}.`);o&&o instanceof ArrayBuffer?(this.data=o,this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+r+a,2*t),this._pos=2*t,this._finished=!0):(this.data=new ArrayBuffer(8+i+r+a),this.ids=new this.IndexArrayType(this.data,8,t),this.coords=new this.ArrayType(this.data,8+r+a,2*t),this._pos=0,this._finished=!1,new Uint8Array(this.data,0,2).set([219,16+s]),new Uint16Array(this.data,2,1)[0]=e,new Uint32Array(this.data,4,1)[0]=t)}add(t,e){const n=this._pos>>1;return this.ids[n]=n,this.coords[this._pos++]=t,this.coords[this._pos++]=e,n}finish(){const t=this._pos>>1;if(t!==this.numItems)throw new Error(`Added ${t} items when expected ${this.numItems}.`);return U(this.ids,this.coords,this.nodeSize,0,this.numItems-1,0),this._finished=!0,this}range(t,e,n,o){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:s,coords:i,nodeSize:r}=this,a=[0,s.length-1,0],u=[];for(;a.length;){const c=a.pop()||0,l=a.pop()||0,h=a.pop()||0;if(l-h<=r){for(let r=h;r<=l;r++){const a=i[2*r],c=i[2*r+1];a>=t&&a<=n&&c>=e&&c<=o&&u.push(s[r])}continue}const d=h+l>>1,p=i[2*d],f=i[2*d+1];p>=t&&p<=n&&f>=e&&f<=o&&u.push(s[d]),(0===c?t<=p:e<=f)&&(a.push(h),a.push(d-1),a.push(1-c)),(0===c?n>=p:o>=f)&&(a.push(d+1),a.push(l),a.push(1-c))}return u}within(t,e,n){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:o,coords:s,nodeSize:i}=this,r=[0,o.length-1,0],a=[],u=n*n;for(;r.length;){const c=r.pop()||0,l=r.pop()||0,h=r.pop()||0;if(l-h<=i){for(let n=h;n<=l;n++)k(s[2*n],s[2*n+1],t,e)<=u&&a.push(o[n]);continue}const d=h+l>>1,p=s[2*d],f=s[2*d+1];k(p,f,t,e)<=u&&a.push(o[d]),(0===c?t-n<=p:e-n<=f)&&(r.push(h),r.push(d-1),r.push(1-c)),(0===c?t+n>=p:e+n>=f)&&(r.push(d+1),r.push(l),r.push(1-c))}return a}}function U(t,e,n,o,s,i){if(s-o<=n)return;const r=o+s>>1;D(t,e,r,o,s,i),U(t,e,n,o,r-1,1-i),U(t,e,n,r+1,s,1-i)}function D(t,e,n,o,s,i){for(;s>o;){if(s-o>600){const r=s-o+1,a=n-o+1,u=Math.log(r),c=.5*Math.exp(2*u/3),l=.5*Math.sqrt(u*c*(r-c)/r)*(a-r/2<0?-1:1);D(t,e,n,Math.max(o,Math.floor(n-a*c/r+l)),Math.min(s,Math.floor(n+(r-a)*c/r+l)),i)}const r=e[2*n+i];let a=o,u=s;for(j(t,e,o,n),e[2*s+i]>r&&j(t,e,o,s);a<u;){for(j(t,e,a,u),a++,u--;e[2*a+i]<r;)a++;for(;e[2*u+i]>r;)u--}e[2*o+i]===r?j(t,e,o,u):(u++,j(t,e,u,s)),u<=n&&(o=u+1),n<=u&&(s=u-1)}}function j(t,e,n,o){N(t,n,o),N(e,2*n,2*o),N(e,2*n+1,2*o+1)}function N(t,e,n){const o=t[e];t[e]=t[n],t[n]=o}function k(t,e,n,o){const s=t-n,i=e-o;return s*s+i*i}const $={minZoom:0,maxZoom:16,minPoints:2,radius:40,extent:512,nodeSize:64,log:!1,generateId:!1,reduce:null,map:t=>t},G=3,B=5,J=6;class q{constructor(t){this.options=Object.assign(Object.create($),t),this.trees=new Array(this.options.maxZoom+1),this.stride=this.options.reduce?7:6,this.clusterProps=[],this.points=[]}load(t){const e=[];for(const n of t){if(!n.geometry)continue;const[t,o]=n.geometry.coordinates,[s,i]=[c(t),l(o)],r={id:n.id,type:"Point",geometry:[s,i],tags:n.properties};e.push(r)}this.createIndex(e)}initialize(t){const e=[];for(const n of t)"Point"===n.type&&e.push(n);this.createIndex(e)}updateIndex(t,e,n){this.options=Object.assign(Object.create($),n.clusterOptions),this.initialize(t)}createIndex(t){const{log:e,minZoom:n,maxZoom:o}=this.options;e&&console.time("total time");const s=`prepare ${t.length} points`;e&&console.time(s),this.points=t;const i=[];for(let e=0;e<t.length;e++){const n=t[e];if(!n?.geometry)continue;let[o,s]=n.geometry;o=Math.fround(o),s=Math.fround(s),i.push(o,s,1/0,e,-1,1),this.options.reduce&&i.push(0)}let r=this.trees[o+1]=this.createTree(i);e&&console.timeEnd(s);for(let t=o;t>=n;t--){const n=Date.now();r=this.trees[t]=this.createTree(this.cluster(r,t)),e&&console.log("z%d: %d clusters in %dms",t,r.numItems,Date.now()-n)}e&&console.timeEnd("total time")}getClusters(t,e){return this.getClustersInternal(t,e).map((t=>h(t)))}getClustersInternal(t,e){let n=((t[0]+180)%360+360)%360-180;const o=Math.max(-90,Math.min(90,t[1]));let s=180===t[2]?180:((t[2]+180)%360+360)%360-180;const i=Math.max(-90,Math.min(90,t[3]));if(t[2]-t[0]>=360)n=-180,s=180;else if(n>s){const t=this.getClustersInternal([n,o,180,i],e),r=this.getClustersInternal([-180,o,s,i],e);return t.concat(r)}const r=this.trees[this.limitZoom(e)],a=r.range(c(n),l(i),c(s),l(o)),u=r.flatData,h=[];for(const t of a){const e=this.stride*t;h.push(u[e+B]>1?R(u,e,this.clusterProps):this.points[u[e+G]])}return h}getChildren(t){const e=this.getOriginId(t),n=this.getOriginZoom(t),o=new Error("No cluster with the specified id: "+t),s=this.trees[n];if(!s)throw o;const i=s.flatData;if(e*this.stride>=i.length)throw o;const r=this.options.radius/(this.options.extent*Math.pow(2,n-1)),a=i[e*this.stride],u=i[e*this.stride+1],c=s.within(a,u,r),l=[];for(const e of c){const n=e*this.stride;i[n+4]===t&&l.push(i[n+B]>1?V(i,n,this.clusterProps):h(this.points[i[n+G]]))}if(0===l.length)throw o;return l}getLeaves(t,e,n){e=e||10,n=n||0;const o=[];return this.appendLeaves(o,t,e,n,0),o}getTile(t,e,n){const o=this.trees[this.limitZoom(t)];if(!o)return null;const s=Math.pow(2,t),{extent:i,radius:r}=this.options,a=r/i,u=(n-a)/s,c=(n+1+a)/s,l={transformed:!0,features:[],source:null,x:e,y:n,z:t};return this.addTileFeatures(o.range((e-a)/s,u,(e+1+a)/s,c),o.flatData,e,n,s,l),0===e&&this.addTileFeatures(o.range(1-a/s,u,1,c),o.flatData,s,n,s,l),e===s-1&&this.addTileFeatures(o.range(0,u,a/s,c),o.flatData,-1,n,s,l),l}getClusterExpansionZoom(t){return this.getOriginZoom(t)}appendLeaves(t,e,n,o,s){const i=this.getChildren(e);for(const e of i){const i=e.properties;if(i?.cluster?s+i.point_count<=o?s+=i.point_count:s=this.appendLeaves(t,i.cluster_id,n,o,s):s<o?s++:t.push(e),t.length===n)break}return s}createTree(t){const e=new F(t.length/this.stride|0,this.options.nodeSize,Float32Array);for(let n=0;n<t.length;n+=this.stride)e.add(t[n],t[n+1]);return e.finish(),e.flatData=t,e.data=null,e}addTileFeatures(t,e,n,o,s,i){for(const r of t){const t=r*this.stride,a=e[t+B]>1;let u,c,l;if(a)u=K(e,t,this.clusterProps),c=e[t],l=e[t+1];else{const n=this.points[e[t+G]];u=n.tags,[c,l]=n.geometry}const h={type:1,geometry:[[Math.round(this.options.extent*(c*s-n)),Math.round(this.options.extent*(l*s-o))]],tags:u};let d;d=a||this.options.generateId?e[t+G]:this.points[e[t+G]].id,void 0!==d&&(h.id=d),i.features.push(h)}}limitZoom(t){return Math.max(this.options.minZoom,Math.min(Math.floor(+t),this.options.maxZoom+1))}cluster(t,e){const{radius:n,extent:o,reduce:s,minPoints:i}=this.options,r=n/(o*Math.pow(2,e)),a=t.flatData,u=[],c=this.stride;for(let n=0;n<a.length;n+=c){if(a[n+2]<=e)continue;a[n+2]=e;const o=a[n],l=a[n+1],h=t.within(a[n],a[n+1],r),d=a[n+B];let p=d;for(const t of h){const n=t*c;a[n+2]>e&&(p+=a[n+B])}if(p>d&&p>=i){let t,i=o*d,r=l*d,f=-1;const g=(n/c<<5)+(e+1)+this.points.length;for(const o of h){const u=o*c;if(a[u+2]<=e)continue;a[u+2]=e;const l=a[u+B];i+=a[u]*l,r+=a[u+1]*l,a[u+4]=g,s&&(t||(t=this.map(a,n,!0),f=this.clusterProps.length,this.clusterProps.push(t)),s(t,this.map(a,u)))}a[n+4]=g,u.push(i/p,r/p,1/0,g,-1,p),s&&u.push(f)}else{for(let t=0;t<c;t++)u.push(a[n+t]);if(p>1)for(const t of h){const n=t*c;if(!(a[n+2]<=e)){a[n+2]=e;for(let t=0;t<c;t++)u.push(a[n+t])}}}}return u}getOriginId(t){return t-this.points.length>>5}getOriginZoom(t){return(t-this.points.length)%32}map(t,e,n){if(t[e+B]>1){const o=this.clusterProps[t[e+J]];return n?Object.assign({},o):o}const o=this.points[t[e+G]].tags,s=this.options.map(o);return n&&s===o?Object.assign({},s):s}}function R(t,e,n){return{id:t[e+G],type:"Point",tags:K(t,e,n),geometry:[t[e],t[e+1]]}}function V(t,e,n){return{type:"Feature",id:t[e+G],properties:K(t,e,n),geometry:{type:"Point",coordinates:[g(t[e]),m(t[e+1])]}}}function K(t,e,n){const o=t[e+B],s=o>=1e4?`${Math.round(o/1e3)}k`:o>=1e3?Math.round(o/100)/10+"k":o,i=t[e+J],r=-1===i?{}:Object.assign({},n[i]);return Object.assign(r,{cluster:!0,cluster_id:t[e+G],point_count:o,point_count_abbreviated:s})}const H="geojsonvt_clip_start",Q="geojsonvt_clip_end";function W(t,e,n,o,s){const i=e===s.maxZoom?0:s.tolerance/((1<<e)*s.extent),r={transformed:!1,features:[],source:null,x:n,y:o,z:e,minX:2,minY:1,maxX:-1,maxY:0,numPoints:0,numSimplified:0,numFeatures:t.length};for(const e of t)tt(r,e,i,s);return r}function tt(t,e,n,o){switch(t.minX=Math.min(t.minX,e.minX),t.minY=Math.min(t.minY,e.minY),t.maxX=Math.max(t.maxX,e.maxX),t.maxY=Math.max(t.maxY,e.maxY),e.type){case"Point":case"MultiPoint":return void function(t,e){const n=[];for(let o=0;o<e.geometry.length;o+=3)n.push(e.geometry[o],e.geometry[o+1]),t.numPoints++,t.numSimplified++;if(!n.length)return;const o={type:1,tags:e.tags||null,geometry:n};null!==e.id&&(o.id=e.id);t.features.push(o)}(t,e);case"LineString":return void function(t,e,n,o){const s=[];if(et(s,e.geometry,t,n,!1,!1),!s.length)return;let i=e.tags||null;if(o.lineMetrics){i={};for(const t in e.tags)i[t]=e.tags[t];i[H]=e.geometry.start/e.geometry.size,i[Q]=e.geometry.end/e.geometry.size}const r={type:2,tags:i,geometry:s};null!==e.id&&(r.id=e.id);t.features.push(r)}(t,e,n,o);case"MultiLineString":case"Polygon":return void function(t,e,n){const o=[];for(let s=0;s<e.geometry.length;s++)et(o,e.geometry[s],t,n,"Polygon"===e.type,0===s);if(!o.length)return;const s={type:"Polygon"===e.type?3:2,tags:e.tags||null,geometry:o};null!==e.id&&(s.id=e.id);t.features.push(s)}(t,e,n);case"MultiPolygon":return void function(t,e,n){const o=[];for(let s=0;s<e.geometry.length;s++){const i=e.geometry[s];for(let e=0;e<i.length;e++)et(o,i[e],t,n,!0,0===e)}if(!o.length)return;const s={type:3,tags:e.tags||null,geometry:o};null!==e.id&&(s.id=e.id);t.features.push(s)}(t,e,n)}}function et(t,e,n,o,s,i){const r=o*o;if(o>0&&e.size<(s?r:o))return void(n.numPoints+=e.length/3);const a=[];for(let t=0;t<e.length;t+=3)(0===o||e[t+2]>r)&&(n.numSimplified++,a.push(e[t],e[t+1])),n.numPoints++;s&&function(t,e){let n=0;for(let e=0,o=t.length,s=o-2;e<o;s=e,e+=2)n+=(t[e]-t[s])*(t[e+1]+t[s+1]);if(n>0!==e)return;for(let e=0,n=t.length;e<n/2;e+=2){const o=t[e],s=t[e+1];t[e]=t[n-2-e],t[e+1]=t[n-1-e],t[n-2-e]=o,t[n-1-e]=s}}(a,i),t.push(a)}function nt(t,e){if(t.transformed)return t;const n=1<<t.z,o=t.x,s=t.y;for(const i of t.features)1===i.type?ot(i,e,n,o,s):st(i,e,n,o,s);return t.transformed=!0,t}function ot(t,e,n,o,s){const i=t,r=t.geometry,a=[];for(let t=0;t<r.length;t+=2)a.push(it(r[t],r[t+1],e,n,o,s));return i.geometry=a,i}function st(t,e,n,o,s){const i=t,r=t.geometry,a=[];for(const t of r){const i=[];for(let r=0;r<t.length;r+=2)i.push(it(t[r],t[r+1],e,n,o,s));a.push(i)}return i.geometry=a,i}function it(t,e,n,o,s,i){return[Math.round(n*(t*o-s)),Math.round(n*(e*o-i))]}class rt{constructor(t){this.options=t,this.stats={},this.total=0,this.tiles={},this.tileCoords=[],this.stats={},this.total=0}initialize(t){this.splitTile(t,0,0,0),this.options.debug&&(t.length&&console.log("features: %d, points: %d",this.tiles[0].numFeatures,this.tiles[0].numPoints),console.timeEnd("generate tiles"),console.log("tiles generated:",this.total,JSON.stringify(this.stats)))}updateIndex(t,e,n){n.debug>1&&(console.log("invalidating tiles"),console.time("invalidating")),this.invalidateTiles(e),n.debug>1&&console.timeEnd("invalidating");const[o,s,i]=[0,0,0],r=W(t,o,s,i,n);r.source=t;const a=at(o,s,i);if(this.tiles[a]=r,this.tileCoords.push({z:o,x:s,y:i,id:a}),n.debug){const t=`z${o}`;this.stats[t]=(this.stats[t]||0)+1,this.total++}}getClusterExpansionZoom(t){return null}getChildren(t){return null}getLeaves(t,e,n){return null}getTile(t,e,n){const{extent:o,debug:s}=this.options,i=1<<t,r=at(t,e=e+i&i-1,n);if(this.tiles[r])return nt(this.tiles[r],o);s>1&&console.log("drilling down to z%d-%d-%d",t,e,n);let a,u=t,c=e,l=n;for(;!a&&u>0;)u--,c>>=1,l>>=1,a=this.tiles[at(u,c,l)];return a?.source?(s>1&&(console.log("found parent tile z%d-%d-%d",u,c,l),console.time("drilling down")),this.splitTile(a.source,u,c,l,t,e,n),s>1&&console.timeEnd("drilling down"),this.tiles[r]?nt(this.tiles[r],o):null):null}splitTile(t,e,n,o,s,i,r){const a=[t,e,n,o],u=this.options,c=u.debug;for(;a.length;){o=a.pop(),n=a.pop(),e=a.pop(),t=a.pop();const l=1<<e,h=at(e,n,o);let d=this.tiles[h];if(!d&&(c>1&&console.time("creation"),d=this.tiles[h]=W(t,e,n,o,u),this.tileCoords.push({z:e,x:n,y:o,id:h}),c)){c>1&&(console.log("tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",e,n,o,d.numFeatures,d.numPoints,d.numSimplified),console.timeEnd("creation"));const t=`z${e}`;this.stats[t]=(this.stats[t]||0)+1,this.total++}if(d.source=t,null==s){if(e===u.indexMaxZoom||d.numPoints<=u.indexMaxPoints)continue}else{if(e===u.maxZoom||e===s)continue;if(null!=s){const t=s-e;if(n!==i>>t||o!==r>>t)continue}}if(d.source=null,!t.length)continue;c>1&&console.time("clipping");const p=.5*u.buffer/u.extent,f=.5-p,g=.5+p,m=1+p;let M=null,w=null,P=null,I=null;const v=x(t,l,n-p,n+g,y.X,d.minX,d.maxX,u),b=x(t,l,n+f,n+m,y.X,d.minX,d.maxX,u);v&&(M=x(v,l,o-p,o+g,y.Y,d.minY,d.maxY,u),w=x(v,l,o+f,o+m,y.Y,d.minY,d.maxY,u)),b&&(P=x(b,l,o-p,o+g,y.Y,d.minY,d.maxY,u),I=x(b,l,o+f,o+m,y.Y,d.minY,d.maxY,u)),c>1&&console.timeEnd("clipping"),a.push(M||[],e+1,2*n,2*o),a.push(w||[],e+1,2*n,2*o+1),a.push(P||[],e+1,2*n+1,2*o),a.push(I||[],e+1,2*n+1,2*o+1)}}invalidateTiles(t){if(!t.length)return;const e=this.options,{debug:n}=e;let o=1/0,s=-1/0,i=1/0,r=-1/0;for(const e of t)o=Math.min(o,e.minX),s=Math.max(s,e.maxX),i=Math.min(i,e.minY),r=Math.max(r,e.maxY);const a=e.buffer/e.extent,u=new Set;for(const e in this.tiles){const c=this.tiles[e],l=1<<c.z,h=(c.x-a)/l,d=(c.x+1+a)/l,p=(c.y-a)/l,f=(c.y+1+a)/l;if(s<h||o>=d||r<p||i>=f)continue;let g=!1;for(const e of t)if(e.maxX>=h&&e.minX<d&&e.maxY>=p&&e.minY<f){g=!0;break}if(g){if(n){n>1&&console.log("invalidate tile z%d-%d-%d (features: %d, points: %d, simplified: %d)",c.z,c.x,c.y,c.numFeatures,c.numPoints,c.numSimplified);const t=`z${c.z}`;this.stats[t]=(this.stats[t]||0)-1,this.total--}delete this.tiles[e],u.add(e)}}u.size&&(this.tileCoords=this.tileCoords.filter((t=>!u.has(t.id))))}}function at(t,e,n){return 32*((1<<t)*n+e)+t}const ut={maxZoom:14,indexMaxZoom:5,indexMaxPoints:1e5,tolerance:3,extent:4096,buffer:64,lineMetrics:!1,promoteId:null,generateId:!1,updateable:!1,cluster:!1,clusterOptions:$,debug:0};t.GEOJSONVT_CLIP_END=Q,t.GEOJSONVT_CLIP_START=H,t.GeoJSONVT=class{get tiles(){return this.tileIndex?.tiles??{}}get stats(){return this.tileIndex.stats}get total(){return this.tileIndex.total}constructor(t,e){const n=(e=this.options=Object.assign({},ut,e)).debug;if(n&&console.time("preprocess data"),e.maxZoom<0||e.maxZoom>24)throw new Error("maxZoom should be in the 0-24 range");if(e.promoteId&&e.generateId)throw new Error("promoteId and generateId cannot be used together.");let o=i(t,e);n&&(console.timeEnd("preprocess data"),console.log("index: maxZoom: %d, maxPoints: %d",e.indexMaxZoom,e.indexMaxPoints),console.time("generate tiles")),o=X(o,e),e.updateable&&(this.source=o),this.initializeIndex(o,e)}initializeIndex(t,e){this.tileIndex=e.cluster?new q(e.clusterOptions):new rt(e),t.length&&this.tileIndex.initialize(t)}getTile(t,e,n){return e=+e,n=+n,(t=+t)<0||t>24?null:this.tileIndex.getTile(t,e,n)}updateData(t,e){const n=this.options;if(!n.updateable)throw new Error("to update tile geojson `updateable` option must be set to true");let{affected:o,source:s}=O(this.source,t,n);e&&({affected:o,source:s}=this.filterUpdate(s,o,e)),o.length&&(this.source=s,this.tileIndex.updateIndex(s,o,n))}filterUpdate(t,e,n){const o=new Set;for(const s of t)null!=s.id&&(n(h(s))||(e.push(s),o.add(s.id)));return{affected:e,source:t=t.filter((t=>!o.has(t.id)))}}getData(){if(!this.options.updateable)throw new Error("to retrieve data the `updateable` option must be set to true");return{type:"FeatureCollection",features:this.source.map((t=>h(t)))}}updateClusterOptions(t,e){const n=this.options.cluster;this.options.cluster=t,this.options.clusterOptions=e,n!=t?this.initializeIndex(this.source,this.options):this.tileIndex.updateIndex(this.source,[],this.options)}getClusterExpansionZoom(t){return this.tileIndex.getClusterExpansionZoom(t)}getClusterChildren(t){return this.tileIndex.getChildren(t)}getClusterLeaves(t,e,n){return this.tileIndex.getLeaves(t,e,n)}},t.Supercluster=q,t.geoJSONToTile=function(t,e,n,o,s={}){s={...ut,...s};const{wrap:r=!1,clip:a=!1}=s;let u=i(t,s);if(r&&(u=X(u,s)),a||s.lineMetrics){const t=1<<e,i=s.buffer/s.extent,r=x(u,t,n-i,n+1+i,y.X,-1,2,s);u=x(r||[],t,o-i,o+1+i,y.Y,-1,2,s)}return nt(W(u??[],e,n,o,s),s.extent)}}));
@@ -676,89 +676,92 @@ function shiftCoords(points, offset) {
676
676
  function applySourceDiff(source, dataDiff, options) {
677
677
  // convert diff to sets/maps for o(1) lookups
678
678
  const diff = diffToHashed(dataDiff);
679
- // collection for features that will be affected by this update
679
+ // collection for features that will be affected by this update and used to invalidate tiles
680
680
  let affected = [];
681
- // full removal - clear everything before applying diff
682
681
  if (diff.removeAll) {
683
682
  affected = source;
684
683
  source = [];
685
684
  }
686
- // remove/add features and collect affected ones
687
685
  if (diff.remove.size || diff.add.size) {
688
686
  const removeFeatures = [];
689
- // collect source features to be removed
687
+ // Collect features to remove (explicit removals + replacements via add)
690
688
  for (const feature of source) {
691
- const { id } = feature;
692
- // explicit feature removal
693
- if (diff.remove.has(id)) {
694
- removeFeatures.push(feature);
695
- // feature with duplicate id being added
696
- }
697
- else if (diff.add.has(id)) {
689
+ if (diff.remove.has(feature.id) || diff.add.has(feature.id)) {
698
690
  removeFeatures.push(feature);
699
691
  }
700
692
  }
701
- // collect affected and remove from source
702
693
  if (removeFeatures.length) {
703
694
  affected.push(...removeFeatures);
704
695
  const removeIds = new Set(removeFeatures.map(f => f.id));
705
696
  source = source.filter(f => !removeIds.has(f.id));
706
697
  }
707
- // convert and add new features
708
698
  if (diff.add.size) {
709
- // projects and adds simplification info
710
699
  let addFeatures = convertToInternal({ type: 'FeatureCollection', features: Array.from(diff.add.values()) }, options);
711
- // wraps features (ie extreme west and extreme east)
712
700
  addFeatures = wrap(addFeatures, options);
713
701
  affected.push(...addFeatures);
714
702
  source.push(...addFeatures);
715
703
  }
716
704
  }
717
705
  if (diff.update.size) {
706
+ // Features can be duplicated across the antimeridian (wrap) in a single tile, so must update all instances with the same id
718
707
  for (const [id, update] of diff.update) {
719
- const featureIndex = source.findIndex(f => f.id === id);
720
- if (featureIndex === -1)
708
+ const oldFeatures = [];
709
+ const keepFeatures = [];
710
+ for (const feature of source) {
711
+ if (feature.id === id) {
712
+ oldFeatures.push(feature);
713
+ }
714
+ else {
715
+ keepFeatures.push(feature);
716
+ }
717
+ }
718
+ if (!oldFeatures.length)
721
719
  continue;
722
- const feature = source[featureIndex];
723
- // get updated geojsonvt simplified feature
724
- const updatedFeature = getUpdatedFeature(feature, update, options);
725
- if (!updatedFeature)
720
+ const updatedFeatures = getUpdatedFeatures(oldFeatures, update, options);
721
+ if (!updatedFeatures.length)
726
722
  continue;
727
- // track both features for invalidation
728
- affected.push(feature, updatedFeature);
729
- // replace old feature with updated feature
730
- source[featureIndex] = updatedFeature;
723
+ affected.push(...oldFeatures, ...updatedFeatures);
724
+ keepFeatures.push(...updatedFeatures);
725
+ source = keepFeatures;
731
726
  }
732
727
  }
733
728
  return { affected, source };
734
729
  }
735
- // return an updated geojsonvt simplified feature
736
- function getUpdatedFeature(vtFeature, update, options) {
730
+ /**
731
+ * Gets updated simplified feature(s) based on a diff update object.
732
+ * @param vtFeatures - the original features
733
+ * @param update - the update object to apply
734
+ * @param options - the options to use for the wrap method
735
+ * @returns Updated features. If geometry is updated, returns new feature(s) converted from geojson and wrapped. If only properties are updated, returns feature(s) with tags updated.
736
+ */
737
+ function getUpdatedFeatures(vtFeatures, update, options) {
737
738
  const changeGeometry = !!update.newGeometry;
738
739
  const changeProps = update.removeAllProperties ||
739
740
  update.removeProperties?.length > 0 ||
740
741
  update.addOrUpdateProperties?.length > 0;
741
- // if geometry changed, need to create new geojson feature and convert to simplified format
742
+ // if geometry changed, need to create a new geojson feature and convert to internal format
742
743
  if (changeGeometry) {
744
+ const vtFeature = vtFeatures[0];
743
745
  const geojsonFeature = {
744
746
  type: 'Feature',
745
747
  id: vtFeature.id,
746
748
  geometry: update.newGeometry,
747
749
  properties: changeProps ? applyPropertyUpdates(vtFeature.tags, update) : vtFeature.tags
748
750
  };
749
- // projects and adds simplification info
750
751
  let features = convertToInternal({ type: 'FeatureCollection', features: [geojsonFeature] }, options);
751
- // wraps features (ie extreme west and extreme east)
752
752
  features = wrap(features, options);
753
- return features[0];
753
+ return features;
754
754
  }
755
- // only properties changed - update tags directly
756
755
  if (changeProps) {
757
- const feature = { ...vtFeature };
758
- feature.tags = applyPropertyUpdates(feature.tags, update);
759
- return feature;
756
+ const updated = [];
757
+ for (const vtFeature of vtFeatures) {
758
+ const feature = { ...vtFeature };
759
+ feature.tags = applyPropertyUpdates(feature.tags, update);
760
+ updated.push(feature);
761
+ }
762
+ return updated;
760
763
  }
761
- return null;
764
+ return [];
762
765
  }
763
766
  /**
764
767
  * helper to apply property updates from a diff update object to a properties object
@@ -820,11 +823,6 @@ const OFFSET_PROP = 6;
820
823
  * This class allow clustering of geojson points.
821
824
  */
822
825
  class ClusterTileIndex {
823
- options;
824
- trees;
825
- stride;
826
- clusterProps;
827
- points;
828
826
  constructor(options) {
829
827
  this.options = Object.assign(Object.create(defaultClusterOptions), options);
830
828
  this.trees = new Array(this.options.maxZoom + 1);
@@ -1471,16 +1469,12 @@ function transformPoint(x, y, extent, z2, tx, ty) {
1471
1469
  }
1472
1470
 
1473
1471
  class TileIndex {
1474
- options;
1475
- tileCoords;
1476
- /** @internal */
1477
- tiles;
1478
- /** @internal */
1479
- stats = {};
1480
- /** @internal */
1481
- total = 0;
1482
1472
  constructor(options) {
1483
1473
  this.options = options;
1474
+ /** @internal */
1475
+ this.stats = {};
1476
+ /** @internal */
1477
+ this.total = 0;
1484
1478
  this.tiles = {};
1485
1479
  this.tileCoords = [];
1486
1480
  this.stats = {};
@@ -1779,9 +1773,6 @@ class GeoJSONVT {
1779
1773
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1780
1774
  return this.tileIndex.total;
1781
1775
  }
1782
- options;
1783
- source;
1784
- tileIndex;
1785
1776
  constructor(data, options) {
1786
1777
  options = this.options = Object.assign({}, defaultOptions, options);
1787
1778
  const debug = options.debug;