@maplibre/geojson-vt 6.1.2 → 6.3.0

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 (41) hide show
  1. package/README.md +8 -0
  2. package/dist/cluster-tile-index.d.ts +43 -5
  3. package/dist/cluster-tile-index.d.ts.map +1 -1
  4. package/dist/convert.d.ts +2 -9
  5. package/dist/convert.d.ts.map +1 -1
  6. package/dist/deconvert.d.ts +4 -11
  7. package/dist/deconvert.d.ts.map +1 -1
  8. package/dist/definitions.d.ts +47 -7
  9. package/dist/definitions.d.ts.map +1 -1
  10. package/dist/difference.d.ts +2 -1
  11. package/dist/difference.d.ts.map +1 -1
  12. package/dist/geojson-vt-dev.js +462 -181
  13. package/dist/geojson-vt.js +1 -1
  14. package/dist/geojson-vt.mjs +459 -180
  15. package/dist/geojson-vt.mjs.map +1 -1
  16. package/dist/geojsonvt.d.ts +8 -4
  17. package/dist/geojsonvt.d.ts.map +1 -1
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/tile-index.d.ts +7 -0
  21. package/dist/tile-index.d.ts.map +1 -1
  22. package/dist/world-coordinate-helper.d.ts +13 -0
  23. package/dist/world-coordinate-helper.d.ts.map +1 -0
  24. package/dist/wrap.d.ts.map +1 -1
  25. package/package.json +5 -5
  26. package/src/clip.ts +2 -2
  27. package/src/cluster-tile-index.test.ts +123 -0
  28. package/src/cluster-tile-index.ts +270 -99
  29. package/src/convert.ts +49 -44
  30. package/src/deconvert.test.ts +4 -4
  31. package/src/deconvert.ts +15 -29
  32. package/src/definitions.ts +48 -7
  33. package/src/difference.test.ts +71 -0
  34. package/src/difference.ts +50 -21
  35. package/src/geojson-to-tile.ts +2 -2
  36. package/src/geojsonvt.test.ts +387 -1
  37. package/src/geojsonvt.ts +25 -10
  38. package/src/index.ts +2 -1
  39. package/src/tile-index.ts +19 -3
  40. package/src/world-coordinate-helper.ts +63 -0
  41. package/src/wrap.ts +2 -0
@@ -1,12 +1,14 @@
1
1
  import { type GeoJSONVTSourceDiff } from './difference';
2
- import type { ClusterOrPointFeature, GeoJSONVTOptions, GeoJSONVTTile, SuperclusterOptions } from './definitions';
2
+ import type { ClusterOrPointFeature, GeoJSONVTOptions, GeoJSONVTTile } from './definitions';
3
3
  export declare const defaultOptions: GeoJSONVTOptions;
4
4
  /**
5
5
  * Main class for creating and managing a vector tile index from GeoJSON data.
6
6
  */
7
7
  export declare class GeoJSONVT {
8
8
  private options;
9
+ private worldCoordinateHelper;
9
10
  private source?;
11
+ private unlocated?;
10
12
  private tileIndex;
11
13
  constructor(data: GeoJSON.GeoJSON, options?: GeoJSONVTOptions);
12
14
  private initializeIndex;
@@ -24,7 +26,9 @@ export declare class GeoJSONVT {
24
26
  */
25
27
  updateData(diff: GeoJSONVTSourceDiff, filter?: (feature: GeoJSON.Feature) => boolean): void;
26
28
  /**
27
- * Filter an update using a predicate function. Returns the affected and updated source features.
29
+ * Filter an update using a predicate function, the features an update emptied included, so that one the filter
30
+ * rejects can't come back with a later update. A feature without a geometry at all isn't passed to the predicate.
31
+ * Returns the affected and updated source features.
28
32
  */
29
33
  private filterUpdate;
30
34
  /**
@@ -34,9 +38,9 @@ export declare class GeoJSONVT {
34
38
  /**
35
39
  * Update supercluster options and regenerate the index.
36
40
  * @param cluster - whether to enable clustering
37
- * @param clusterOptions - {@link SuperclusterOptions}
41
+ * @param clusterOptions - {@link SuperclusterOptions} without `coordinates` and `wrap`, which come from the index options
38
42
  */
39
- updateClusterOptions(cluster: boolean, clusterOptions: SuperclusterOptions): void;
43
+ updateClusterOptions(cluster: boolean, clusterOptions: GeoJSONVTOptions['clusterOptions']): void;
40
44
  /**
41
45
  * Returns the zoom level at which a cluster expands into multiple children.
42
46
  * @param clusterId - The target cluster id.
@@ -1 +1 @@
1
- {"version":3,"file":"geojsonvt.d.ts","sourceRoot":"","sources":["../src/geojsonvt.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,mBAAmB,EAAC,MAAM,cAAc,CAAC;AAGvE,OAAO,KAAK,EAAC,qBAAqB,EAAgD,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAC,MAAM,eAAe,CAAC;AAE7J,eAAO,MAAM,cAAc,EAAE,gBAc5B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,OAAO,CAAmB;IAElC,OAAO,CAAC,MAAM,CAAC,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAqB;gBAE1B,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,gBAAgB;IA8B7D,OAAO,CAAC,eAAe;IAMvB;;;;;;OAMG;IACH,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI;IAUzF;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO;IAqBpF;;OAEG;IACH,OAAO,CAAC,YAAY;IAcpB;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO;IAK1B;;;;OAIG;IACH,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,mBAAmB;IAa1E;;;;OAIG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIzD;;;;OAIG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI;IAIrE;;;;;;OAMG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI;CAG9G"}
1
+ {"version":3,"file":"geojsonvt.d.ts","sourceRoot":"","sources":["../src/geojsonvt.ts"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,mBAAmB,EAAC,MAAM,cAAc,CAAC;AAGvE,OAAO,KAAK,EAAC,qBAAqB,EAAgD,gBAAgB,EAAE,aAAa,EAAC,MAAM,eAAe,CAAC;AAExI,eAAO,MAAM,cAAc,EAAE,gBAgB5B,CAAC;AAEF;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,qBAAqB,CAAwB;IAErD,OAAO,CAAC,MAAM,CAAC,CAA6B;IAC5C,OAAO,CAAC,SAAS,CAAC,CAAwC;IAC1D,OAAO,CAAC,SAAS,CAAqB;gBAE1B,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,gBAAgB;IAkC7D,OAAO,CAAC,eAAe;IAMvB;;;;;;OAMG;IACH,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,IAAI;IAUzF;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO;IAqBpF;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAkBpB;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO;IAK1B;;;;OAIG;IACH,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC;IAazF;;;;OAIG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIzD;;;;OAIG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI;IAIrE;;;;;;OAMG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI;CAG9G"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { GeoJSONVTFeatureDiff, GeoJSONVTSourceDiff } from './difference';
2
- import type { GeoJSONVTInternalFeature, GeoJSONVTInternalLineStringFeature, GeoJSONVTInternalMultiLineStringFeature, GeoJSONVTInternalMultiPointFeature, GeoJSONVTInternalMultiPolygonFeature, GeoJSONVTInternalPointFeature, GeoJSONVTInternalPolygonFeature, GeoJSONVTOptions, GeoJSONToTileOptions, PartialGeoJSONVTFeature, SliceArray, SliceFixedArray, ClusterProperties, ClusterFeature, ClusterOrPointFeature, GeoJSONVTTile, GeoJSONVTFeature, GeoJSONVTFeaturePoint, GeoJSONVTFeatureNonPoint, GeoJSONVTInternalTileFeaturePoint, GeoJSONVTInternalTileFeatureNonPoint, GeoJSONVTInternalTile, GeoJSONVTInternalTileFeature, GeoJSONVTTileIndex, SuperclusterOptions } from './definitions';
2
+ import type { GeoJSONVTInternalFeature, GeoJSONVTInternalLineStringFeature, GeoJSONVTInternalMultiLineStringFeature, GeoJSONVTInternalMultiPointFeature, GeoJSONVTInternalMultiPolygonFeature, GeoJSONVTInternalPointFeature, GeoJSONVTInternalPolygonFeature, GeoJSONVTOptions, GeoJSONToTileOptions, PartialGeoJSONVTFeature, SliceArray, SliceFixedArray, ClusterProperties, ClusterFeature, ClusterOrPointFeature, GeoJSONVTTile, GeoJSONVTFeature, GeoJSONVTFeaturePoint, GeoJSONVTFeatureNonPoint, GeoJSONVTInternalTileFeaturePoint, GeoJSONVTInternalTileFeatureNonPoint, GeoJSONVTInternalTile, GeoJSONVTInternalTileFeature, GeoJSONVTTileIndex, SuperclusterOptions, GeoJSONVTCoordinatesType } from './definitions';
3
3
  import type { KDBushWithData } from './cluster-tile-index';
4
4
  import { GeoJSONVT } from './geojsonvt';
5
5
  import { ClusterTileIndex } from './cluster-tile-index';
6
6
  import { geoJSONToTile } from './geojson-to-tile';
7
7
  import { GEOJSONVT_CLIP_START, GEOJSONVT_CLIP_END } from './tile';
8
8
  export { GeoJSONVT, ClusterTileIndex as Supercluster, geoJSONToTile, GEOJSONVT_CLIP_START, GEOJSONVT_CLIP_END };
9
- export type { GeoJSONVTInternalFeature, GeoJSONVTOptions, GeoJSONToTileOptions, GeoJSONVTInternalTile, GeoJSONVTInternalTileFeature, PartialGeoJSONVTFeature, SliceArray, SliceFixedArray, GeoJSONVTTile, GeoJSONVTFeature, GeoJSONVTSourceDiff, GeoJSONVTFeatureDiff, GeoJSONVTFeaturePoint, GeoJSONVTFeatureNonPoint, GeoJSONVTInternalTileFeaturePoint, GeoJSONVTInternalTileFeatureNonPoint, GeoJSONVTInternalPointFeature, GeoJSONVTInternalMultiPointFeature, GeoJSONVTInternalLineStringFeature, GeoJSONVTInternalMultiLineStringFeature, GeoJSONVTInternalPolygonFeature, GeoJSONVTInternalMultiPolygonFeature, SuperclusterOptions, ClusterProperties, ClusterFeature, ClusterOrPointFeature, KDBushWithData, GeoJSONVTTileIndex };
9
+ export type { GeoJSONVTInternalFeature, GeoJSONVTOptions, GeoJSONToTileOptions, GeoJSONVTInternalTile, GeoJSONVTInternalTileFeature, PartialGeoJSONVTFeature, SliceArray, SliceFixedArray, GeoJSONVTTile, GeoJSONVTFeature, GeoJSONVTSourceDiff, GeoJSONVTFeatureDiff, GeoJSONVTFeaturePoint, GeoJSONVTFeatureNonPoint, GeoJSONVTInternalTileFeaturePoint, GeoJSONVTInternalTileFeatureNonPoint, GeoJSONVTInternalPointFeature, GeoJSONVTInternalMultiPointFeature, GeoJSONVTInternalLineStringFeature, GeoJSONVTInternalMultiLineStringFeature, GeoJSONVTInternalPolygonFeature, GeoJSONVTInternalMultiPolygonFeature, SuperclusterOptions, GeoJSONVTCoordinatesType, ClusterProperties, ClusterFeature, ClusterOrPointFeature, KDBushWithData, GeoJSONVTTileIndex };
10
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAC,wBAAwB,EAAE,kCAAkC,EAAE,uCAAuC,EAAE,kCAAkC,EAAE,oCAAoC,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,iCAAiC,EAAE,oCAAoC,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,mBAAmB,EAAC,MAAM,eAAe,CAAC;AACpqB,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,QAAQ,CAAC;AAEhE,OAAO,EACH,SAAS,EACT,gBAAgB,IAAI,YAAY,EAChC,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EACrB,CAAA;AAED,YAAY,EACR,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,iCAAiC,EACjC,oCAAoC,EACpC,6BAA6B,EAC7B,kCAAkC,EAClC,kCAAkC,EAClC,uCAAuC,EACvC,+BAA+B,EAC/B,oCAAoC,EACpC,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EACrB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,oBAAoB,EAAE,mBAAmB,EAAC,MAAM,cAAc,CAAC;AAC5E,OAAO,KAAK,EAAC,wBAAwB,EAAE,kCAAkC,EAAE,uCAAuC,EAAE,kCAAkC,EAAE,oCAAoC,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,qBAAqB,EAAE,aAAa,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,iCAAiC,EAAE,oCAAoC,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,wBAAwB,EAAC,MAAM,eAAe,CAAC;AAC9rB,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AACtC,OAAO,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAC,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAC,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,QAAQ,CAAC;AAEhE,OAAO,EACH,SAAS,EACT,gBAAgB,IAAI,YAAY,EAChC,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EACrB,CAAA;AAED,YAAY,EACR,wBAAwB,EACxB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,4BAA4B,EAC5B,uBAAuB,EACvB,UAAU,EACV,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,wBAAwB,EACxB,iCAAiC,EACjC,oCAAoC,EACpC,6BAA6B,EAC7B,kCAAkC,EAClC,kCAAkC,EAClC,uCAAuC,EACvC,+BAA+B,EAC/B,oCAAoC,EACpC,mBAAmB,EACnB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,kBAAkB,EACrB,CAAC"}
@@ -23,6 +23,13 @@ export declare class TileIndex implements GeoJSONVTTileIndex {
23
23
  getLeaves(_clusterId: number, _limit?: number, _offset?: number): GeoJSON.Feature<GeoJSON.Point>[] | null;
24
24
  /** {@inheritdoc} */
25
25
  getTile(z: number, x: number, y: number): GeoJSONVTTile | null;
26
+ /**
27
+ * The features the top tile starts from. A world that wraps keeps them all left and right, where wrapping already
28
+ * put them inside, and one that doesn't only what lies inside the world square and its buffer. Positions in the
29
+ * unit square are also cut above and below in a world that wraps, where lng/lat is clamped already. The index keeps
30
+ * the rest, so an update can still move a feature in from outside.
31
+ */
32
+ private clipToWorld;
26
33
  /**
27
34
  * splits features from a parent tile to sub-tiles.
28
35
  * z, x, and y are the coordinates of the parent tile
@@ -1 +1 @@
1
- {"version":3,"file":"tile-index.d.ts","sourceRoot":"","sources":["../src/tile-index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEjK,qBAAa,SAAU,YAAW,kBAAkB;IAWpC,OAAO,CAAC,OAAO;IAT3B,OAAO,CAAC,UAAU,CAAkD;IACpE,OAAO,CAAC,KAAK,CAAa;IAE1B,gBAAgB;IACT,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAA;KAAC,CAAC;IACrD,gBAAgB;IACT,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAM;gBAGvB,OAAO,EAAE,gBAAgB;IAO7C,UAAU,CAAC,QAAQ,EAAE,wBAAwB,EAAE,GAAG,IAAI;IAWtD,oBAAoB;IACpB,WAAW,CAAC,MAAM,EAAE,wBAAwB,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IA2BtH,oBAAoB;IAEpB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI1D,oBAAoB;IAEpB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI;IAI/D,oBAAoB;IAEpB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI;IAIzG,oBAAoB;IACpB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAwC9D;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,SAAS;IA4FjB;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAuE1B"}
1
+ {"version":3,"file":"tile-index.d.ts","sourceRoot":"","sources":["../src/tile-index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEjK,qBAAa,SAAU,YAAW,kBAAkB;IAWpC,OAAO,CAAC,OAAO;IAT3B,OAAO,CAAC,UAAU,CAAkD;IACpE,OAAO,CAAC,KAAK,CAAa;IAE1B,gBAAgB;IACT,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAA;KAAC,CAAC;IACrD,gBAAgB;IACT,KAAK,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAC,CAAM;gBAGvB,OAAO,EAAE,gBAAgB;IAO7C,UAAU,CAAC,QAAQ,EAAE,wBAAwB,EAAE,GAAG,IAAI;IAWtD,oBAAoB;IACpB,WAAW,CAAC,MAAM,EAAE,wBAAwB,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IA4BtH,oBAAoB;IAEpB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAI1D,oBAAoB;IAEpB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,EAAE,GAAG,IAAI;IAI/D,oBAAoB;IAEpB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI;IAIzG,oBAAoB;IACpB,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAyC9D;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAQnB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,SAAS;IA4FjB;;;;OAIG;IACH,OAAO,CAAC,eAAe;CAuE1B"}
@@ -0,0 +1,13 @@
1
+ import type { GeoJSONVTCoordinatesType } from './definitions';
2
+ /**
3
+ * How the positions of the input relate to the world square the tiles cover, in which x and y run from 0 to 1.
4
+ */
5
+ export interface WorldCoordinateHelper {
6
+ projectX(x: number): number;
7
+ projectY(y: number): number;
8
+ unprojectX(x: number): number;
9
+ unprojectY(y: number): number;
10
+ }
11
+ export declare const mercatorWorldCoordinateHelper: WorldCoordinateHelper;
12
+ export declare function getWorldCoordinateHelper(coordinates?: GeoJSONVTCoordinatesType): WorldCoordinateHelper;
13
+ //# sourceMappingURL=world-coordinate-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world-coordinate-helper.d.ts","sourceRoot":"","sources":["../src/world-coordinate-helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,eAAe,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AA+CD,eAAO,MAAM,6BAA6B,EAAE,qBAA2D,CAAC;AAGxG,wBAAgB,wBAAwB,CAAC,WAAW,CAAC,EAAE,wBAAwB,GAAG,qBAAqB,CAEtG"}
@@ -1 +1 @@
1
- {"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAA+B,MAAM,eAAe,CAAC;AAG7G,wBAAgB,IAAI,CAAC,QAAQ,EAAE,wBAAwB,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,wBAAwB,EAAE,CAehH"}
1
+ {"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../src/wrap.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,gBAAgB,EAA+B,MAAM,eAAe,CAAC;AAG7G,wBAAgB,IAAI,CAAC,QAAQ,EAAE,wBAAwB,EAAE,EAAE,OAAO,EAAE,gBAAgB,GAAG,wBAAwB,EAAE,CAiBhH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maplibre/geojson-vt",
3
- "version": "6.1.2",
3
+ "version": "6.3.0",
4
4
  "description": "Slice GeoJSON data into vector tiles efficiently",
5
5
  "type": "module",
6
6
  "exports": {
@@ -27,15 +27,15 @@
27
27
  "@eslint/js": "^10.0.1",
28
28
  "@types/benchmark": "^2.1.5",
29
29
  "@types/geojson": "^7946.0.16",
30
- "@types/node": "^26.6.3",
30
+ "@types/node": "^26.6.5",
31
31
  "@vitest/coverage-v8": "^5.0.3",
32
32
  "benchmark": "^2.1.4",
33
- "eslint": "^10.11.0",
34
- "rolldown": "^1.2.12",
33
+ "eslint": "^10.12.0",
34
+ "rolldown": "^1.2.13",
35
35
  "tsx": "^4.23.15",
36
36
  "typedoc": "^0.28.20",
37
37
  "typescript": "^6.0.3",
38
- "typescript-eslint": "^8.71.0",
38
+ "typescript-eslint": "^8.71.1",
39
39
  "vitest": "^5.0.3"
40
40
  },
41
41
  "license": "ISC",
package/src/clip.ts CHANGED
@@ -184,13 +184,13 @@ function clipLine(geom: SliceFixedArray, newGeom: SliceArray[], start: number, e
184
184
 
185
185
  if (a < start) {
186
186
  // ---|--> | (line enters the clip region from the left)
187
- if (b > start) {
187
+ if (b >= start) {
188
188
  t = intersect(slice, ax, ay, bx, by, start);
189
189
  if (trackMetrics) slice.start = len + segLen * t;
190
190
  }
191
191
  } else if (a > end) {
192
192
  // | <--|--- (line enters the clip region from the right)
193
- if (b < end) {
193
+ if (b <= end) {
194
194
  t = intersect(slice, ax, ay, bx, by, end);
195
195
  if (trackMetrics) slice.start = len + segLen * t;
196
196
  }
@@ -203,3 +203,126 @@ test('does not throw on zero items', () => {
203
203
  expect(index.getClusters([-180, -85, 180, 85], 0)).toEqual([]);
204
204
  }).not.toThrow();
205
205
  });
206
+
207
+ test('does not keep the cluster properties of an earlier load', () => {
208
+ const index = new ClusterTileIndex({
209
+ map: (props) => ({sum: (props as {scalerank: number})?.scalerank}),
210
+ reduce: (a, b) => { (a as {sum: number}).sum += (b as {sum: number}).sum; },
211
+ radius: 100
212
+ });
213
+ index.load(places.features);
214
+ const count = index.clusterProps.length;
215
+
216
+ index.load(places.features);
217
+
218
+ expect(index.clusterProps.length).toBe(count);
219
+ });
220
+
221
+ test('takes points and the getClusters bounding box in the unit square with unitSquare coordinates', () => {
222
+ const index = new ClusterTileIndex({coordinates: 'unitSquare', wrap: false});
223
+ index.load([
224
+ {type: 'Feature', properties: {name: 'a'}, geometry: {type: 'Point', coordinates: [0.25, 0.25]}},
225
+ {type: 'Feature', properties: {name: 'b'}, geometry: {type: 'Point', coordinates: [0.75, 0.75]}}
226
+ ]);
227
+
228
+ expect(index.getClusters([0, 0, 0.5, 0.5], 0).map(f => f.geometry.coordinates)).toEqual([[0.25, 0.25]]);
229
+ });
230
+
231
+ test('leaves points outside the world out of load in a unit square without wrap', () => {
232
+ const index = new ClusterTileIndex({coordinates: 'unitSquare', wrap: false});
233
+ index.load([
234
+ {type: 'Feature', properties: {name: 'inside'}, geometry: {type: 'Point', coordinates: [0.99, 0.5]}},
235
+ {type: 'Feature', properties: {name: 'outside'}, geometry: {type: 'Point', coordinates: [1.03, 0.5]}}
236
+ ]);
237
+
238
+ expect(index.getTile(0, 0, 0).features.map(feature => feature.geometry)).toEqual([[[507, 256]]]);
239
+ });
240
+
241
+ test('returns no tile outside the world in a unit square without wrap', () => {
242
+ const index = new ClusterTileIndex({coordinates: 'unitSquare', wrap: false});
243
+ index.load([
244
+ {type: 'Feature', properties: {name: 'west'}, geometry: {type: 'Point', coordinates: [0.01, 0.5]}},
245
+ {type: 'Feature', properties: {name: 'east'}, geometry: {type: 'Point', coordinates: [0.99, 0.5]}},
246
+ {type: 'Feature', properties: {name: 'north'}, geometry: {type: 'Point', coordinates: [0.5, 0.01]}},
247
+ {type: 'Feature', properties: {name: 'south'}, geometry: {type: 'Point', coordinates: [0.5, 0.99]}}
248
+ ]);
249
+
250
+ expect([index.getTile(0, -1, 0), index.getTile(0, 1, 0), index.getTile(0, 0, -1), index.getTile(0, 0, 1)]).toEqual([null, null, null, null]);
251
+ });
252
+
253
+ test('limits minZoom and maxZoom to 30, the highest zoom level a cluster id can hold', () => {
254
+ const index = new ClusterTileIndex({minZoom: 40, maxZoom: 40});
255
+ const point: GeoJSON.Feature<GeoJSON.Point> = {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [10, 10]}};
256
+ index.load([point, point, point]);
257
+
258
+ const cluster = index.getClusters([-180, -90, 180, 90], 30)[0];
259
+ const clusterId = (cluster.properties as ClusterProperties).cluster_id;
260
+
261
+ expect(index.getLeaves(clusterId)).toHaveLength(3);
262
+ expect(index.getChildren(clusterId)).toHaveLength(3);
263
+ expect(index.getClusterExpansionZoom(clusterId)).toBe(31);
264
+ });
265
+
266
+ test('clusters each position of a MultiPoint feature', () => {
267
+ const multiPoint: GeoJSON.Feature<GeoJSON.MultiPoint> = {
268
+ type: 'Feature',
269
+ id: 7,
270
+ properties: {name: 'multi'},
271
+ geometry: {type: 'MultiPoint', coordinates: [[20, 20], [20.0001, 20], [60, 20]]}
272
+ };
273
+ const index = new ClusterTileIndex();
274
+ index.load([multiPoint]);
275
+
276
+ expect(index.getTile(0, 0, 0).features).toEqual([
277
+ {type: 1, geometry: [[284, 227]], tags: {cluster: true, cluster_id: 20, point_count: 2, point_count_abbreviated: 2}, id: 20},
278
+ {type: 1, geometry: [[341, 227]], tags: {name: 'multi'}, id: 7}
279
+ ]);
280
+ });
281
+
282
+ test('does not cluster points that are farther apart than the radius on a high zoom level', () => {
283
+ const index = new ClusterTileIndex({
284
+ maxZoom: 20,
285
+ extent: 8192,
286
+ radius: 16
287
+ });
288
+ index.load([
289
+ {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [-1.426798, 53.943034]}},
290
+ {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [-1.426796, 53.943034]}}
291
+ ]);
292
+
293
+ expect(index.getClusters([-180, -90, 180, 90], 20)).toHaveLength(2);
294
+ });
295
+
296
+ test('returns a cluster within a step of the mean of its points in a unit square without wrap', () => {
297
+ const index = new ClusterTileIndex({coordinates: 'unitSquare', wrap: false});
298
+ index.load([
299
+ {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [0.54, 0.42]}},
300
+ {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [0.54, 0.42]}},
301
+ {type: 'Feature', properties: null, geometry: {type: 'Point', coordinates: [0.56, 0.4]}}
302
+ ]);
303
+
304
+ const [x, y] = index.getClusters([0, 0, 1, 1], 0)[0].geometry.coordinates;
305
+
306
+ expect(x).toBeCloseTo(0.5466666667, 9);
307
+ expect(y).toBeCloseTo(0.4133333333, 9);
308
+ });
309
+
310
+ test('getClusters keeps only the part of a box inside a world that does not wrap', () => {
311
+ const index = new ClusterTileIndex({wrap: false});
312
+ index.load([
313
+ {type: 'Feature', properties: {name: 'west'}, geometry: {type: 'Point', coordinates: [-175, 0]}},
314
+ {type: 'Feature', properties: {name: 'east'}, geometry: {type: 'Point', coordinates: [175, 0]}}
315
+ ]);
316
+
317
+ expect(index.getClusters([170, -20, 190, 20], 17).map(f => f.properties.name)).toEqual(['east']);
318
+ });
319
+
320
+ test('getClusters repeats a box across the edge of a unit square that wraps', () => {
321
+ const index = new ClusterTileIndex({coordinates: 'unitSquare', wrap: true});
322
+ index.load([
323
+ {type: 'Feature', properties: {name: 'west'}, geometry: {type: 'Point', coordinates: [0.01, 0.5]}},
324
+ {type: 'Feature', properties: {name: 'east'}, geometry: {type: 'Point', coordinates: [0.99, 0.5]}}
325
+ ]);
326
+
327
+ expect(index.getClusters([0.95, 0, 1.05, 1], 17).map(f => f.properties.name).sort()).toEqual(['east', 'west']);
328
+ });