venue-js 1.2.0-next.1 → 1.2.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,3 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
1
7
  // src/data/index.ts
2
8
  import { QueryObserver as QueryObserver2 } from "@tanstack/query-core";
3
9
 
@@ -191,6 +197,115 @@ var safeFetchFeature = async (featureType, params) => {
191
197
  }
192
198
  };
193
199
 
200
+ // src/data/utils/geometry-validator.ts
201
+ var isValidCoordinate = (point2) => {
202
+ return point2.length === 2 && point2.every((coord) => typeof coord === "number");
203
+ };
204
+ function isValidLinearRingCoordinates(ring) {
205
+ if (ring.length < 4) {
206
+ return false;
207
+ }
208
+ return ring.every(isValidCoordinate) && ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1];
209
+ }
210
+ var isValidPolygonCoordinates = (polygon) => {
211
+ if (Array.isArray(polygon[0]) && (polygon[0].length === 0 || typeof polygon[0][0] === "number")) {
212
+ return isValidLinearRingCoordinates(polygon);
213
+ }
214
+ if (Array.isArray(polygon) && polygon.length > 0 && Array.isArray(polygon[0])) {
215
+ if (!isValidLinearRingCoordinates(polygon[0])) {
216
+ return false;
217
+ }
218
+ for (let i = 1; i < polygon.length; i++) {
219
+ if (!isValidLinearRingCoordinates(polygon[i])) {
220
+ return false;
221
+ }
222
+ }
223
+ return true;
224
+ }
225
+ return false;
226
+ };
227
+ var isValidMultiPolygonCoordinates = (multipolygon) => {
228
+ return multipolygon.every(isValidPolygonCoordinates);
229
+ };
230
+ var isValidLineStringCoordinates = (lineString2) => {
231
+ if (!Array.isArray(lineString2) || lineString2.length < 2) {
232
+ return false;
233
+ }
234
+ const firstPoint = lineString2[0];
235
+ const lastPoint = lineString2[lineString2.length - 1];
236
+ if (firstPoint[0] === lastPoint[0] && firstPoint[1] === lastPoint[1]) {
237
+ return false;
238
+ }
239
+ return lineString2.every(isValidCoordinate);
240
+ };
241
+ var isValidMultiPolygon = (geometry) => {
242
+ const { type, coordinates } = geometry;
243
+ return type === "MultiPolygon" && isValidMultiPolygonCoordinates(coordinates);
244
+ };
245
+ var isValidPolygon = (geometry) => {
246
+ const { type, coordinates } = geometry;
247
+ return type === "Polygon" && isValidPolygonCoordinates(coordinates);
248
+ };
249
+ var isValidLineString = (geometry) => {
250
+ const { type, coordinates } = geometry;
251
+ return type === "LineString" && isValidLineStringCoordinates(coordinates);
252
+ };
253
+ var isValidPoint = (geometry) => {
254
+ const { type, coordinates } = geometry;
255
+ return type === "Point" && isValidCoordinate(coordinates);
256
+ };
257
+
258
+ // src/data/utils/match-filters.ts
259
+ function isInFilter(filter) {
260
+ return typeof filter === "object" && filter !== null && "$in" in filter && Array.isArray(filter.$in);
261
+ }
262
+ var someIntersect = (a, b) => a.some((v) => b.includes(v));
263
+ function matchFilter(value, filter) {
264
+ if (Array.isArray(value)) {
265
+ if (isInFilter(filter)) return someIntersect(value, filter.$in);
266
+ return value.includes(filter);
267
+ } else {
268
+ if (isInFilter(filter)) return filter.$in.includes(value);
269
+ return value === filter;
270
+ }
271
+ }
272
+ function matchFilters(item, filters) {
273
+ return Object.entries(filters).every(([key, filter]) => {
274
+ return matchFilter(item.properties[key], filter);
275
+ });
276
+ }
277
+
278
+ // src/data/utils/occupant-helper.ts
279
+ var occupant_helper_exports = {};
280
+ __export(occupant_helper_exports, {
281
+ getOccupantCorrelatedLocations: () => getOccupantCorrelatedLocations,
282
+ getOccupantMainLocation: () => getOccupantMainLocation,
283
+ getOccupantMarkerLocations: () => getOccupantMarkerLocations
284
+ });
285
+ import _compact from "lodash/compact";
286
+ var getOccupantMainLocation = (occupant) => {
287
+ return occupant.properties.kiosk || occupant.properties.unit;
288
+ };
289
+ var getOccupantCorrelatedLocations = (occupant) => {
290
+ const allCorrelatedLocations = [
291
+ ...occupant.properties.units,
292
+ ...occupant.properties.kiosks
293
+ ];
294
+ return _compact(allCorrelatedLocations);
295
+ };
296
+ var getOccupantMarkerLocations = (occupant, options) => {
297
+ const placementType = options?.type ? options.type : occupant.properties.show_name_on_all_units ? "ALL_LOCATIONS" : "ONCE_PER_LEVEL";
298
+ const mainLocation = getOccupantMainLocation(occupant);
299
+ const mainLocationLevel = mainLocation?.properties?.level_id;
300
+ const allCorrelatedLocations = getOccupantCorrelatedLocations(occupant);
301
+ if (placementType === "ALL_LOCATIONS") {
302
+ return _compact([mainLocation, ...allCorrelatedLocations]);
303
+ }
304
+ const otherLevelLocations = allCorrelatedLocations.filter((f) => f.properties.level_id !== mainLocationLevel);
305
+ const onePerLevelLocations = [...new Map(otherLevelLocations.map((loc) => [loc.properties.level_id, loc])).values()];
306
+ return _compact([mainLocation, ...onePerLevelLocations]);
307
+ };
308
+
194
309
  // src/data/getDataClient.ts
195
310
  import {
196
311
  QueryClient,
@@ -349,8 +464,8 @@ var createPopulator = ({
349
464
  venue,
350
465
  promotions,
351
466
  privileges,
352
- kiosk,
353
- unit,
467
+ kiosk: kiosk ? await populateKiosk(kiosk) : null,
468
+ unit: unit ? await populateUnit(unit) : null,
354
469
  kiosks: await Promise.all(kiosks.map(populateKiosk)),
355
470
  units: await Promise.all(units.map(populateUnit))
356
471
  }
@@ -442,26 +557,6 @@ var createPopulator = ({
442
557
  };
443
558
  };
444
559
 
445
- // src/data/utils/match-filters.ts
446
- function isInFilter(filter) {
447
- return typeof filter === "object" && filter !== null && "$in" in filter && Array.isArray(filter.$in);
448
- }
449
- var someIntersect = (a, b) => a.some((v) => b.includes(v));
450
- function matchFilter(value, filter) {
451
- if (Array.isArray(value)) {
452
- if (isInFilter(filter)) return someIntersect(value, filter.$in);
453
- return value.includes(filter);
454
- } else {
455
- if (isInFilter(filter)) return filter.$in.includes(value);
456
- return value === filter;
457
- }
458
- }
459
- function matchFilters(item, filters) {
460
- return Object.entries(filters).every(([key, filter]) => {
461
- return matchFilter(item.properties[key], filter);
462
- });
463
- }
464
-
465
560
  // src/data/getDataClient.ts
466
561
  var getDataClient = (options) => {
467
562
  const observers = /* @__PURE__ */ new Map();
@@ -593,11 +688,13 @@ import {
593
688
  ui as ui3,
594
689
  Map as Map2,
595
690
  TileLayer,
596
- Extent,
597
691
  LineString as LineString3,
598
692
  Marker as Marker2,
599
- Coordinate as Coordinate4
693
+ Coordinate as Coordinate4,
694
+ GroupGLLayer,
695
+ GLTFLayer
600
696
  } from "maptalks-gl";
697
+ import "@maptalks/transcoders.draco";
601
698
  import TWEEN2 from "@tweenjs/tween.js";
602
699
  import _6 from "lodash";
603
700
 
@@ -679,133 +776,8 @@ function isNumber(num) {
679
776
  // src/IndoorMap/IndoorMap.ts
680
777
  import turfDistance from "@turf/distance";
681
778
  import turfCenter3 from "@turf/center";
682
-
683
- // ../../node_modules/@turf/meta/dist/esm/index.js
684
- function coordEach(geojson, callback, excludeWrapCoord) {
685
- if (geojson === null) return;
686
- var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
687
- for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
688
- geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
689
- isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
690
- stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
691
- for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
692
- var multiFeatureIndex = 0;
693
- var geometryIndex = 0;
694
- geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
695
- if (geometry === null) continue;
696
- coords = geometry.coordinates;
697
- var geomType = geometry.type;
698
- wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0;
699
- switch (geomType) {
700
- case null:
701
- break;
702
- case "Point":
703
- if (callback(
704
- coords,
705
- coordIndex,
706
- featureIndex,
707
- multiFeatureIndex,
708
- geometryIndex
709
- ) === false)
710
- return false;
711
- coordIndex++;
712
- multiFeatureIndex++;
713
- break;
714
- case "LineString":
715
- case "MultiPoint":
716
- for (j = 0; j < coords.length; j++) {
717
- if (callback(
718
- coords[j],
719
- coordIndex,
720
- featureIndex,
721
- multiFeatureIndex,
722
- geometryIndex
723
- ) === false)
724
- return false;
725
- coordIndex++;
726
- if (geomType === "MultiPoint") multiFeatureIndex++;
727
- }
728
- if (geomType === "LineString") multiFeatureIndex++;
729
- break;
730
- case "Polygon":
731
- case "MultiLineString":
732
- for (j = 0; j < coords.length; j++) {
733
- for (k = 0; k < coords[j].length - wrapShrink; k++) {
734
- if (callback(
735
- coords[j][k],
736
- coordIndex,
737
- featureIndex,
738
- multiFeatureIndex,
739
- geometryIndex
740
- ) === false)
741
- return false;
742
- coordIndex++;
743
- }
744
- if (geomType === "MultiLineString") multiFeatureIndex++;
745
- if (geomType === "Polygon") geometryIndex++;
746
- }
747
- if (geomType === "Polygon") multiFeatureIndex++;
748
- break;
749
- case "MultiPolygon":
750
- for (j = 0; j < coords.length; j++) {
751
- geometryIndex = 0;
752
- for (k = 0; k < coords[j].length; k++) {
753
- for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
754
- if (callback(
755
- coords[j][k][l],
756
- coordIndex,
757
- featureIndex,
758
- multiFeatureIndex,
759
- geometryIndex
760
- ) === false)
761
- return false;
762
- coordIndex++;
763
- }
764
- geometryIndex++;
765
- }
766
- multiFeatureIndex++;
767
- }
768
- break;
769
- case "GeometryCollection":
770
- for (j = 0; j < geometry.geometries.length; j++)
771
- if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false)
772
- return false;
773
- break;
774
- default:
775
- throw new Error("Unknown Geometry Type");
776
- }
777
- }
778
- }
779
- }
780
-
781
- // ../../node_modules/@turf/bbox/dist/esm/index.js
782
- function bbox(geojson, options = {}) {
783
- if (geojson.bbox != null && true !== options.recompute) {
784
- return geojson.bbox;
785
- }
786
- const result = [Infinity, Infinity, -Infinity, -Infinity];
787
- coordEach(geojson, (coord) => {
788
- if (result[0] > coord[0]) {
789
- result[0] = coord[0];
790
- }
791
- if (result[1] > coord[1]) {
792
- result[1] = coord[1];
793
- }
794
- if (result[2] < coord[0]) {
795
- result[2] = coord[0];
796
- }
797
- if (result[3] < coord[1]) {
798
- result[3] = coord[1];
799
- }
800
- });
801
- return result;
802
- }
803
- var index_default = bbox;
804
-
805
- // src/IndoorMap/IndoorMap.ts
806
- import scale from "@turf/transform-scale";
807
- import bboxPolygon from "@turf/bbox-polygon";
808
779
  import { PerspectiveCamera } from "three";
780
+ import { ThreeLayer as ThreeLayer4 } from "maptalks.three";
809
781
 
810
782
  // src/IndoorMap/constants.ts
811
783
  var defaultLayerOption = { enableAltitude: true };
@@ -1827,18 +1799,6 @@ var loadModel3d = (model3d, coordinate, threeLayer) => {
1827
1799
  );
1828
1800
  });
1829
1801
  };
1830
- var create3DModels = async (models, defaultCoordinate, properties, threeLayer) => {
1831
- let modelObjs = [];
1832
- for (let j = 0; j < models.length; j++) {
1833
- const model = models[j];
1834
- const positionCoord = _4.get(model, "properties.position");
1835
- const coord = positionCoord || defaultCoordinate;
1836
- const object = await loadModel3d(model, coord, threeLayer);
1837
- object.properties = properties;
1838
- modelObjs.push(object);
1839
- }
1840
- return modelObjs;
1841
- };
1842
1802
  var createExtrudePolygon = (geometry, threeLayer, material, height, properties = {}, options) => {
1843
1803
  const { offset = 0, altitude = 0 } = options;
1844
1804
  const offsetGeometry = turfBuffer(geometry, offset, { units: "meters" });
@@ -2746,44 +2706,6 @@ var styledFeatureGenerator = (mapTheme) => {
2746
2706
  markerProperties
2747
2707
  );
2748
2708
  },
2749
- createVenue3DModel: async (venue, threeLayer) => {
2750
- const { id, feature_type, properties } = venue;
2751
- const { category, model3d } = properties;
2752
- const modelProperty = {
2753
- id,
2754
- feature_type,
2755
- category
2756
- };
2757
- const center2 = turfCenter(venue);
2758
- const centerCoord = _4.get(center2, "geometry.coordinates");
2759
- const modelPosition = _4.get(model3d, "properties.position", centerCoord);
2760
- const models = await create3DModels(
2761
- model3d,
2762
- modelPosition,
2763
- modelProperty,
2764
- threeLayer
2765
- );
2766
- return models;
2767
- },
2768
- create3DFixture: async (fixture, threeLayer) => {
2769
- const { id, feature_type, properties } = fixture;
2770
- const { category, ordinal, model3d } = properties;
2771
- const modelProperty = {
2772
- id,
2773
- feature_type,
2774
- category,
2775
- ordinal
2776
- };
2777
- const center2 = turfCenter(fixture);
2778
- const coordinate = _4.get(center2, "geometry.coordinates");
2779
- const models = await create3DModels(
2780
- model3d,
2781
- coordinate,
2782
- modelProperty,
2783
- threeLayer
2784
- );
2785
- return models;
2786
- },
2787
2709
  createExtrudedUnit: (unit, threeLayer, options) => {
2788
2710
  const extrudeHeight = _4.get(options, "height");
2789
2711
  if (!extrudeHeight) return;
@@ -2823,24 +2745,6 @@ var styledFeatureGenerator = (mapTheme) => {
2823
2745
  options3d
2824
2746
  );
2825
2747
  return object;
2826
- },
2827
- createAmbientLight: (config) => {
2828
- const { color: colorString = "0xffffff", intensity = 1 } = config;
2829
- const color = parseInt(colorString, 16);
2830
- const ambientLight = new AmbientLight(color, intensity);
2831
- return ambientLight;
2832
- },
2833
- createDirectionalLight: (config) => {
2834
- const {
2835
- color: colorString = "0xffffff",
2836
- intensity = 1,
2837
- position: positionString = [0, 0, 0]
2838
- } = config;
2839
- const color = parseInt(colorString, 16);
2840
- const [x, y, z] = positionString;
2841
- const light = new DirectionalLight(color, intensity);
2842
- light.position.set(x, y, z).normalize();
2843
- return light;
2844
2748
  }
2845
2749
  };
2846
2750
  };
@@ -3010,311 +2914,229 @@ var createHighlighExtrudeObjectController = (obj, { color }) => {
3010
2914
  };
3011
2915
 
3012
2916
  // src/IndoorMap/camera/CameraManager.ts
3013
- var ZOOM_OUT_LEVEL = 21;
3014
- var ZOOM_IN_LEVEL = 24;
3015
- var CameraManager = class {
3016
- map;
3017
- constructor(map, options) {
3018
- this.map = map;
3019
- if (options?.defaultView) {
3020
- this.setView(options?.defaultView);
3021
- }
3022
- }
3023
- /** Private method */
3024
- #animateflyTo(viewOptions = {}, options = {}, callbackOption = () => {
3025
- }) {
3026
- const { start, end } = {
3027
- start: (frame) => {
3028
- },
3029
- end: (frame) => {
3030
- },
3031
- ...callbackOption
3032
- };
3033
- this.map.flyTo(viewOptions, options, (frame) => {
3034
- if (frame.state.playState === "running" && frame.state.progress === 0)
3035
- start(frame);
3036
- if (frame.state.playState === "finished") end(frame);
3037
- });
3038
- }
3039
- /** Public methods */
3040
- getView = () => {
3041
- return this.map.getView();
3042
- };
3043
- getZoom = () => {
3044
- return this.map.getView().zoom;
3045
- };
3046
- setView = (value) => {
3047
- this.map.setView(value);
3048
- };
3049
- flyTo = (center2, options = {}) => {
3050
- const currentView = this.getView();
3051
- const {
3052
- zoom = ZOOM_OUT_LEVEL,
3053
- pitch = 60,
3054
- duration = 600,
3055
- easing = "out",
3056
- bearing = currentView.bearing
3057
- } = options;
3058
- this.#animateflyTo(
3059
- {
3060
- center: center2,
3061
- zoom,
3062
- pitch,
3063
- bearing
3064
- },
3065
- { duration, easing }
3066
- );
3067
- };
3068
- flyToAndZoomIn = (centerPoint, options = {}) => {
3069
- const {
3070
- zoom = ZOOM_IN_LEVEL,
3071
- pitch = 60,
3072
- duration = 600,
3073
- easing = "out"
3074
- } = options;
3075
- this.#animateflyTo(
3076
- {
3077
- center: centerPoint,
3078
- zoom,
3079
- pitch
3080
- },
3081
- { duration, easing }
3082
- );
3083
- };
3084
- };
3085
-
3086
- // src/IndoorMap/renderer/RendererManager.ts
3087
- import _min from "lodash/min";
3088
- import { center as turfCenter2 } from "@turf/center";
3089
- import { ThreeLayer as ThreeLayer3 } from "maptalks.three";
3090
- import * as THREE3 from "three";
3091
-
3092
- // src/IndoorMap/renderer/3d/Element3DRenderer.ts
3093
- import * as maptalks4 from "maptalks";
3094
- import * as THREE2 from "three";
3095
- import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader";
3096
- import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
3097
- import turfBuffer2 from "@turf/buffer";
2917
+ import { Extent } from "maptalks";
3098
2918
 
3099
- // src/IndoorMap/renderer/3d/element3DRendererOptions.ts
3100
- var element3DRendererOptions = {
3101
- unit: {
3102
- default: { color: "#ffffff", height: 4 },
3103
- byCategory: {
3104
- walkway: { color: "#cccccc", height: 0.1 },
3105
- terrace: { color: "#cccccc", height: 0.1 },
3106
- unenclosedarea: { color: "#cccccc", height: 0.2 },
3107
- nonpublic: { color: "#999999", height: 0.3 },
3108
- escalator: { height: 0.2 },
3109
- room: { color: "#ffffff", height: 2, bottomHeight: 0.12 }
3110
- }
3111
- },
3112
- kiosk: {
3113
- default: { color: "#666666", height: 0.6, bottomHeight: 0.12 }
3114
- },
3115
- fixture: {
3116
- default: { color: "#ffffff", height: 0.5 },
3117
- byCategory: {
3118
- water: { color: "#ACD7EC", height: 0.1 },
3119
- vegetation: { color: "#91C499", height: 0.5 }
2919
+ // ../../node_modules/@turf/meta/dist/esm/index.js
2920
+ function coordEach(geojson, callback, excludeWrapCoord) {
2921
+ if (geojson === null) return;
2922
+ var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
2923
+ for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
2924
+ geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
2925
+ isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
2926
+ stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
2927
+ for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
2928
+ var multiFeatureIndex = 0;
2929
+ var geometryIndex = 0;
2930
+ geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
2931
+ if (geometry === null) continue;
2932
+ coords = geometry.coordinates;
2933
+ var geomType = geometry.type;
2934
+ wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0;
2935
+ switch (geomType) {
2936
+ case null:
2937
+ break;
2938
+ case "Point":
2939
+ if (callback(
2940
+ coords,
2941
+ coordIndex,
2942
+ featureIndex,
2943
+ multiFeatureIndex,
2944
+ geometryIndex
2945
+ ) === false)
2946
+ return false;
2947
+ coordIndex++;
2948
+ multiFeatureIndex++;
2949
+ break;
2950
+ case "LineString":
2951
+ case "MultiPoint":
2952
+ for (j = 0; j < coords.length; j++) {
2953
+ if (callback(
2954
+ coords[j],
2955
+ coordIndex,
2956
+ featureIndex,
2957
+ multiFeatureIndex,
2958
+ geometryIndex
2959
+ ) === false)
2960
+ return false;
2961
+ coordIndex++;
2962
+ if (geomType === "MultiPoint") multiFeatureIndex++;
2963
+ }
2964
+ if (geomType === "LineString") multiFeatureIndex++;
2965
+ break;
2966
+ case "Polygon":
2967
+ case "MultiLineString":
2968
+ for (j = 0; j < coords.length; j++) {
2969
+ for (k = 0; k < coords[j].length - wrapShrink; k++) {
2970
+ if (callback(
2971
+ coords[j][k],
2972
+ coordIndex,
2973
+ featureIndex,
2974
+ multiFeatureIndex,
2975
+ geometryIndex
2976
+ ) === false)
2977
+ return false;
2978
+ coordIndex++;
2979
+ }
2980
+ if (geomType === "MultiLineString") multiFeatureIndex++;
2981
+ if (geomType === "Polygon") geometryIndex++;
2982
+ }
2983
+ if (geomType === "Polygon") multiFeatureIndex++;
2984
+ break;
2985
+ case "MultiPolygon":
2986
+ for (j = 0; j < coords.length; j++) {
2987
+ geometryIndex = 0;
2988
+ for (k = 0; k < coords[j].length; k++) {
2989
+ for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
2990
+ if (callback(
2991
+ coords[j][k][l],
2992
+ coordIndex,
2993
+ featureIndex,
2994
+ multiFeatureIndex,
2995
+ geometryIndex
2996
+ ) === false)
2997
+ return false;
2998
+ coordIndex++;
2999
+ }
3000
+ geometryIndex++;
3001
+ }
3002
+ multiFeatureIndex++;
3003
+ }
3004
+ break;
3005
+ case "GeometryCollection":
3006
+ for (j = 0; j < geometry.geometries.length; j++)
3007
+ if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false)
3008
+ return false;
3009
+ break;
3010
+ default:
3011
+ throw new Error("Unknown Geometry Type");
3012
+ }
3120
3013
  }
3121
3014
  }
3122
- };
3123
-
3124
- // src/IndoorMap/renderer/3d/objects/TextSpriteMarker.ts
3125
- import { Coordinate as Coordinate2, Util as Util4 } from "maptalks";
3126
- import * as THREE from "three";
3127
- import { BaseObject as BaseObject5 } from "maptalks.three";
3128
- import { isNil, set } from "lodash";
3015
+ }
3129
3016
 
3130
- // src/IndoorMap/renderer/utils/interpolateStops.ts
3131
- var interpolateStops = ({ stops }, zoom) => {
3132
- if (zoom <= stops[0][0]) return stops[0][1];
3133
- if (zoom >= stops[stops.length - 1][0]) return stops[stops.length - 1][1];
3134
- for (let i = 0; i < stops.length - 1; i++) {
3135
- const [z1, v1] = stops[i];
3136
- const [z2, v2] = stops[i + 1];
3137
- if (zoom >= z1 && zoom <= z2) {
3138
- const t = (zoom - z1) / (z2 - z1);
3139
- return v1 + t * (v2 - v1);
3140
- }
3017
+ // ../../node_modules/@turf/bbox/dist/esm/index.js
3018
+ function bbox(geojson, options = {}) {
3019
+ if (geojson.bbox != null && true !== options.recompute) {
3020
+ return geojson.bbox;
3141
3021
  }
3142
- };
3022
+ const result = [Infinity, Infinity, -Infinity, -Infinity];
3023
+ coordEach(geojson, (coord) => {
3024
+ if (result[0] > coord[0]) {
3025
+ result[0] = coord[0];
3026
+ }
3027
+ if (result[1] > coord[1]) {
3028
+ result[1] = coord[1];
3029
+ }
3030
+ if (result[2] < coord[0]) {
3031
+ result[2] = coord[0];
3032
+ }
3033
+ if (result[3] < coord[1]) {
3034
+ result[3] = coord[1];
3035
+ }
3036
+ });
3037
+ return result;
3038
+ }
3039
+ var index_default = bbox;
3143
3040
 
3144
- // src/IndoorMap/renderer/3d/objects/TextSpriteMarker.ts
3145
- var OPTIONS4 = {
3146
- // Texture options
3147
- text: "",
3148
- textAlign: "center",
3149
- color: "#ffffff",
3150
- fontFamily: "sans-serif",
3151
- fontSize: 28,
3152
- fontWeight: 400,
3153
- background: "rgba(0, 0, 0, 0.2)",
3154
- lineHeight: 32,
3155
- padding: 8,
3156
- strokeColor: "#000000",
3157
- strokeWidth: 6,
3158
- strokeStyle: "round",
3159
- // Sprite options
3160
- /* Overall scale multiplier */
3161
- scale: 1,
3162
- altitude: 0,
3163
- opacity: 1
3164
- };
3165
- var TextSpriteMarker = class extends BaseObject5 {
3166
- #altitudeOffset = 0;
3167
- constructor(coordinate, options, layer, properties = {}) {
3168
- options = Util4.extend({}, OPTIONS4, options, { layer });
3169
- super();
3170
- this._coordinate = new Coordinate2(coordinate);
3171
- this._initOptions(options);
3172
- this._createGroup();
3173
- this.properties = { ...properties };
3174
- const sprite = this._createSprite();
3175
- this.getObject3d().add(sprite);
3176
- this._updatePosition();
3177
- this.type = "TextSpriteMarker";
3178
- }
3179
- getOptions() {
3180
- return super.getOptions();
3181
- }
3182
- _createSprite() {
3183
- const options = this.getOptions();
3184
- const texture = this._createTextTexture(options.text, options);
3185
- const material = new THREE.SpriteMaterial({
3186
- map: texture,
3187
- transparent: true,
3188
- alphaTest: 0.1
3189
- });
3190
- const sprite = new THREE.Sprite(material);
3191
- const w = texture.image.width;
3192
- const h = texture.image.height;
3193
- const base = 1 / 16;
3194
- const normalizedScale = options.scale / this.getMap().getGLRes();
3195
- sprite.scale.set(w * base * normalizedScale, h * base * normalizedScale, 1);
3196
- this.#altitudeOffset = Math.max(
3197
- h * base * options.scale * 0.5,
3198
- 0.05
3199
- // minimum lift in world units
3200
- );
3201
- return sprite;
3202
- }
3203
- _createTextTexture(text, options = {}) {
3204
- const {
3205
- padding,
3206
- fontSize,
3207
- fontFamily,
3208
- fontWeight,
3209
- lineHeight,
3210
- background,
3211
- color,
3212
- textAlign,
3213
- strokeColor,
3214
- strokeWidth,
3215
- maxWidth
3216
- } = options || {};
3217
- const canvas = document.createElement("canvas");
3218
- const ctx = canvas.getContext("2d");
3219
- ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
3220
- const paragraphs = String(text).split("\n");
3221
- const wrappedLines = [];
3222
- paragraphs.forEach((paragraph) => {
3223
- if (isNil(maxWidth) || isNaN(maxWidth)) {
3224
- wrappedLines.push(paragraph);
3225
- return;
3226
- }
3227
- const words = paragraph.split(/\s+/);
3228
- let currentLine = "";
3229
- words.forEach((word) => {
3230
- const testLine = currentLine ? currentLine + " " + word : word;
3231
- const testWidth = ctx.measureText(testLine).width;
3232
- if (testWidth > maxWidth && currentLine) {
3233
- wrappedLines.push(currentLine);
3234
- currentLine = word;
3235
- } else {
3236
- currentLine = testLine;
3237
- }
3238
- });
3239
- if (currentLine) {
3240
- wrappedLines.push(currentLine);
3241
- }
3242
- });
3243
- const lines = wrappedLines.length ? wrappedLines : [""];
3244
- const widest = Math.max(...lines.map((l) => ctx.measureText(l).width), 0);
3245
- const finalWidth = (maxWidth ? Math.min(widest, maxWidth) : widest) + padding * 2;
3246
- const finalHeight = lineHeight * lines.length + padding * 2;
3247
- canvas.width = finalWidth;
3248
- canvas.height = finalHeight;
3249
- const ctx2 = canvas.getContext("2d");
3250
- ctx2.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
3251
- ctx2.textAlign = textAlign;
3252
- if (background && background !== "transparent") {
3253
- ctx2.fillStyle = background;
3254
- ctx2.fillRect(0, 0, canvas.width, canvas.height);
3041
+ // src/IndoorMap/camera/CameraManager.ts
3042
+ import scale from "@turf/transform-scale";
3043
+ import bboxPolygon from "@turf/bbox-polygon";
3044
+ var CameraManager = class {
3045
+ map;
3046
+ constructor(map, options) {
3047
+ this.map = map;
3048
+ if (options?.defaultView) {
3049
+ this.setView(options?.defaultView);
3255
3050
  }
3256
- lines.forEach((line, i) => {
3257
- const y = padding + lineHeight * (i + 0.8);
3258
- let x = padding;
3259
- if (textAlign === "center") x = canvas.width / 2;
3260
- if (textAlign === "right" || textAlign === "end")
3261
- x = canvas.width - padding;
3262
- if (strokeWidth > 0) {
3263
- ctx2.lineWidth = strokeWidth;
3264
- ctx2.lineJoin = "round";
3265
- ctx2.miterLimit = 2;
3266
- ctx2.strokeStyle = strokeColor;
3267
- ctx2.strokeText(line, x, y);
3268
- }
3269
- ctx2.fillStyle = color;
3270
- ctx2.fillText(line, x, y);
3271
- });
3272
- const texture = new THREE.CanvasTexture(canvas);
3273
- texture.needsUpdate = true;
3274
- texture.minFilter = THREE.LinearFilter;
3275
- return texture;
3276
3051
  }
3277
- _updatePosition() {
3278
- const options = this.getOptions();
3279
- const layer = options.layer;
3280
- if (!layer) return;
3281
- const altitude = (options.altitude || 0) + this.#altitudeOffset;
3282
- const z = layer.altitudeToVector3(altitude, altitude).x;
3283
- const position = layer.coordinateToVector3(this._coordinate, z);
3284
- set(this.properties, "default.position", position);
3285
- this.getObject3d().position.copy(position);
3052
+ /** Public methods */
3053
+ getView = () => {
3054
+ return this.map.getView();
3055
+ };
3056
+ setView = (value) => {
3057
+ if (this.map && Object.keys(value).length !== 0) {
3058
+ this.map.setView(value);
3059
+ }
3060
+ };
3061
+ animateTo = (view, options = {}, step) => {
3062
+ this.map.animateTo(view, options, step);
3063
+ };
3064
+ setMaxExtent(extent) {
3065
+ return this.map.setMaxExtent(extent);
3286
3066
  }
3287
- _animation() {
3288
- const layer = this.getLayer();
3289
- if (!this.isAdd || !layer) return;
3290
- if (this._visible === true) {
3291
- const zoom = layer.map.getZoom();
3292
- const object3d = this.getObject3d();
3293
- const { opacity } = this.getOptions();
3294
- let opacityValue;
3295
- if (typeof opacity === "number") {
3296
- opacityValue = opacity ?? 1;
3297
- } else if (Array.isArray(opacity.stops)) {
3298
- opacityValue = interpolateStops(opacity, zoom);
3299
- } else {
3300
- throw new Error(`Unknown opacity value ${opacity}`);
3301
- }
3302
- const visible = opacityValue > 0.5;
3303
- object3d.visible = visible;
3067
+ getFeatureExtent = (feature2, scaleFactor = 1) => {
3068
+ const [minX, minY, maxX, maxY] = index_default(
3069
+ scale(bboxPolygon(index_default(feature2)), scaleFactor)
3070
+ );
3071
+ return new Extent(minX, minY, maxX, maxY);
3072
+ };
3073
+ getExtentZoom = (extent, options = {
3074
+ isFraction: false,
3075
+ padding: {
3076
+ paddingLeft: 0,
3077
+ paddingRight: 0,
3078
+ paddingTop: 0,
3079
+ paddingBottom: 0
3304
3080
  }
3081
+ }) => {
3082
+ const { isFraction = false, padding } = options;
3083
+ return this.map.getFitZoom(extent, isFraction, padding);
3084
+ };
3085
+ set maxZoom(value) {
3086
+ this.map.setMaxZoom(value);
3087
+ const spatialReference = {
3088
+ projection: "EPSG:3857",
3089
+ resolutions: (function() {
3090
+ const resolutions = [];
3091
+ const d = 2 * 6378137 * Math.PI;
3092
+ for (let i = 0; i < value; i++) {
3093
+ resolutions[i] = d / (256 * Math.pow(2, i));
3094
+ }
3095
+ return resolutions;
3096
+ })()
3097
+ };
3098
+ this.map.setSpatialReference(spatialReference);
3305
3099
  }
3306
- setText(text) {
3307
- const options = this.getOptions();
3308
- options.text = text;
3309
- const newSprite = this._createSprite();
3310
- const group = this.getObject3d();
3311
- group.children.forEach((child) => group.remove(child));
3312
- group.add(newSprite);
3313
- this._updatePosition();
3100
+ set minZoom(value) {
3101
+ this.map.setMinZoom(value);
3314
3102
  }
3315
- setAltitude(altitude) {
3316
- const bottomHeight = this.options.bottomHeight ?? 0;
3317
- return super.setAltitude(altitude + bottomHeight + this.#altitudeOffset);
3103
+ };
3104
+
3105
+ // src/IndoorMap/renderer/RendererManager.ts
3106
+ import _isFunction from "lodash/isFunction";
3107
+ import _min from "lodash/min";
3108
+ import { center as turfCenter2 } from "@turf/center";
3109
+ import * as THREE3 from "three";
3110
+
3111
+ // src/IndoorMap/renderer/3d/Element3DRenderer.ts
3112
+ import * as maptalks4 from "maptalks-gl";
3113
+ import * as THREE from "three";
3114
+ import { BaseObject as BaseObject5 } from "maptalks.three";
3115
+ import turfBuffer2 from "@turf/buffer";
3116
+
3117
+ // src/IndoorMap/renderer/3d/element3DRendererOptions.ts
3118
+ var element3DRendererOptions = {
3119
+ unit: {
3120
+ default: { color: "#ffffff", height: 4 },
3121
+ byCategory: {
3122
+ walkway: { color: "#cccccc", height: 0.1 },
3123
+ terrace: { color: "#cccccc", height: 0.1 },
3124
+ unenclosedarea: { color: "#cccccc", height: 0.2 },
3125
+ nonpublic: { color: "#999999", height: 0.3 },
3126
+ escalator: { height: 0.2 },
3127
+ parking: { height: 0.1 },
3128
+ room: { color: "#ffffff", height: 2, bottomHeight: 0.12 }
3129
+ }
3130
+ },
3131
+ kiosk: {
3132
+ default: { color: "#666666", height: 0.6, bottomHeight: 0.12 }
3133
+ },
3134
+ fixture: {
3135
+ default: { color: "#ffffff", height: 0.5 },
3136
+ byCategory: {
3137
+ water: { color: "#ACD7EC", height: 0.1 },
3138
+ vegetation: { color: "#91C499", height: 0.5 }
3139
+ }
3318
3140
  }
3319
3141
  };
3320
3142
 
@@ -3338,21 +3160,22 @@ var getGeometryOption = (feature2, options) => {
3338
3160
  var Element3DRenderer = class extends EventTarget {
3339
3161
  options;
3340
3162
  map;
3163
+ gltfLayer;
3341
3164
  threeLayer;
3342
- dracoLoader;
3165
+ scene;
3166
+ // private dracoLoader: DRACOLoader
3343
3167
  lineMaterial;
3344
3168
  materialByColorMap;
3345
- markerRenderer;
3346
3169
  // Renderer is Ready
3347
3170
  isReady = false;
3348
- constructor(map, options, layer) {
3171
+ constructor(map, options) {
3349
3172
  super();
3350
3173
  this.options = options;
3351
3174
  this.map = map;
3352
- this.dracoLoader = new DRACOLoader();
3353
- this.dracoLoader.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.7/");
3354
- this.lineMaterial = new THREE2.LineBasicMaterial({ color: "#000" });
3355
- this.threeLayer = layer;
3175
+ const groupLayer = this.map.getLayer("group");
3176
+ this.threeLayer = groupLayer.getLayer("three");
3177
+ this.gltfLayer = groupLayer.getLayer("gltf");
3178
+ this.lineMaterial = new THREE.LineBasicMaterial({ color: "#000" });
3356
3179
  this.render();
3357
3180
  }
3358
3181
  animation() {
@@ -3367,7 +3190,7 @@ var Element3DRenderer = class extends EventTarget {
3367
3190
  if (!this.materialByColorMap) this.materialByColorMap = /* @__PURE__ */ new Map();
3368
3191
  const existingMaterial = this.materialByColorMap.get(color);
3369
3192
  if (existingMaterial) return existingMaterial;
3370
- const created = new THREE2.MeshLambertMaterial({ color, transparent: true });
3193
+ const created = new THREE.MeshLambertMaterial({ color, transparent: true });
3371
3194
  created.toneMapped = false;
3372
3195
  this.materialByColorMap.set(color, created);
3373
3196
  return created;
@@ -3382,46 +3205,48 @@ var Element3DRenderer = class extends EventTarget {
3382
3205
  } = getGeometryOption(feature2, this.options);
3383
3206
  const _this = this;
3384
3207
  const createPolygon = (geometry, feature3) => {
3385
- const [outerRing, ...innerRings] = geometry.coordinates;
3386
- const offsetFeature = offset !== 0 ? turfBuffer2(geometry, offset, { units: "meters" }) : feature3;
3387
- const color = feature3.properties.style.polygonFill ?? colorOptions ?? "#ffffff";
3388
- if (color === "transparent") return;
3389
- const material = this.getOrCreateMaterialByColor(color);
3390
- const altitude = feature3.properties.ordinal * HEIGHT_METER;
3391
- const height = feature3.properties.height ?? heightOptions ?? HEIGHT_METER;
3392
- const bottomHeight = feature3.properties.bottomHeight ?? bottomHeightOptions ?? 0;
3393
- const extrudedPolygon = this.threeLayer.toExtrudePolygon(
3394
- offsetFeature,
3395
- { asynchronous: true, ...options, height, bottomHeight, altitude },
3396
- material
3397
- );
3398
- extrudedPolygon.on("click", (e) => {
3399
- console.log(e.target.options.polygon.id);
3400
- });
3401
- const topLineStrings = [
3402
- new maptalks4.LineString(outerRing),
3403
- ...innerRings.map((innerRing) => new maptalks4.LineString(innerRing))
3404
- ];
3405
- const topLines = this.threeLayer.toLines(
3406
- topLineStrings,
3407
- { altitude, bottomHeight: bottomHeight + height + 1e-3, interactive: false },
3408
- this.lineMaterial
3409
- );
3410
- const bottomLineStrings = [
3411
- new maptalks4.LineString(outerRing),
3412
- ...innerRings.map((innerRing) => new maptalks4.LineString(innerRing))
3413
- ];
3414
- const bottomLines = this.threeLayer.toLines(
3415
- bottomLineStrings,
3416
- { altitude, bottomHeight, interactive: false },
3417
- this.lineMaterial
3418
- );
3419
- return [extrudedPolygon, topLines, bottomLines];
3208
+ try {
3209
+ const [outerRing, ...innerRings] = geometry.coordinates;
3210
+ const offsetFeature = offset !== 0 ? turfBuffer2(geometry, offset, { units: "meters" }) : feature3;
3211
+ const color = feature3.properties.style.polygonFill ?? colorOptions ?? "#ffffff";
3212
+ if (color === "transparent") return;
3213
+ const material = this.getOrCreateMaterialByColor(color);
3214
+ const altitude = 0;
3215
+ const height = feature3.properties.height ?? heightOptions ?? HEIGHT_METER;
3216
+ const bottomHeight = feature3.properties.bottomHeight ?? bottomHeightOptions ?? 0;
3217
+ const extrudedPolygon = this.threeLayer.toExtrudePolygon(
3218
+ offsetFeature,
3219
+ { asynchronous: true, ...options, height, bottomHeight, altitude },
3220
+ material
3221
+ );
3222
+ const topLineStrings = [
3223
+ new maptalks4.LineString(outerRing),
3224
+ ...innerRings.map((innerRing) => new maptalks4.LineString(innerRing))
3225
+ ];
3226
+ const topLines = this.threeLayer.toLines(
3227
+ topLineStrings,
3228
+ { altitude, bottomHeight: bottomHeight + height + 1e-3, interactive: false },
3229
+ this.lineMaterial
3230
+ );
3231
+ const bottomLineStrings = [
3232
+ new maptalks4.LineString(outerRing),
3233
+ ...innerRings.map((innerRing) => new maptalks4.LineString(innerRing))
3234
+ ];
3235
+ const bottomLines = this.threeLayer.toLines(
3236
+ bottomLineStrings,
3237
+ { altitude, bottomHeight, interactive: false },
3238
+ this.lineMaterial
3239
+ );
3240
+ return [extrudedPolygon, topLines, bottomLines];
3241
+ } catch (err) {
3242
+ return [];
3243
+ }
3420
3244
  };
3421
3245
  try {
3422
3246
  switch (feature2.geometry.type) {
3423
3247
  case "MultiPolygon": {
3424
3248
  const { coordinates } = feature2.geometry;
3249
+ if (!coordinates) return [];
3425
3250
  const multiMeshes = coordinates.flatMap((polygonCoordinates) => {
3426
3251
  const meshes = createPolygon({ type: "Polygon", coordinates: polygonCoordinates }, feature2);
3427
3252
  this.threeLayer.addMesh(meshes);
@@ -3430,70 +3255,47 @@ var Element3DRenderer = class extends EventTarget {
3430
3255
  return multiMeshes;
3431
3256
  }
3432
3257
  case "Polygon": {
3258
+ const { coordinates } = feature2.geometry;
3259
+ if (!coordinates) return [];
3433
3260
  const meshes = createPolygon(feature2.geometry, feature2);
3434
3261
  this.threeLayer.addMesh(meshes);
3435
3262
  return meshes;
3436
3263
  }
3437
3264
  }
3438
3265
  } catch (err) {
3439
- console.log(`error createGeometry`, { feature: feature2, options });
3266
+ console.log(`error createGeometry`, err, { feature: feature2, options });
3440
3267
  }
3441
3268
  };
3442
3269
  async createEscalator(f, coordinate, options) {
3270
+ const model = {
3271
+ url: "https://cdn.venue.in.th/static/glb/escalator.glb",
3272
+ size: 4.4
3273
+ };
3443
3274
  const { direction: dir, angle } = options;
3444
- const model = await this.loadModel3d({
3445
- url: "https://dashboard.situm.com/uploads/3dmodels/demoaccount/new_escalator.glb",
3446
- properties: {
3447
- rotation: {
3448
- x: 0.5 * Math.PI,
3449
- // Rotate the model up (new_escalator.glb)
3450
- y: 0,
3451
- z: 0
3452
- },
3453
- position: { x: 0, y: 0, z: 0 },
3454
- scale: 0.01
3275
+ const rotationZ = dir === "up" ? 180 + angle : angle;
3276
+ var escalatorMarker = new maptalks4.GLTFMarker(coordinate, {
3277
+ symbol: {
3278
+ url: model.url,
3279
+ rotationZ,
3280
+ translationX: dir === "up" ? 0 : model.size * Math.cos(Math.PI * rotationZ / 180),
3281
+ translationY: dir === "up" ? 0 : model.size * Math.sin(Math.PI * rotationZ / 180),
3282
+ translationZ: dir === "up" ? -0.05 * model.size : -0.5 * model.size
3455
3283
  }
3456
3284
  });
3457
- model.rotation.y += dir === "up" ? Math.PI + angle : angle;
3458
- const box = new THREE2.Box3().setFromObject(model);
3459
- const pivotPoint = dir === "up" ? new THREE2.Vector3(0, 0, 0) : new THREE2.Vector3(
3460
- 1 * (box.min.x + box.max.x),
3461
- 1 * (box.min.y + box.max.y),
3462
- 0.6 * box.max.z
3463
- );
3464
- const pivot = new THREE2.Group();
3465
- pivot.add(model);
3466
- model.position.sub(pivotPoint);
3467
- model.updateMatrixWorld(true);
3468
- const altitude = f.properties.ordinal * HEIGHT_METER;
3469
- const baseObjectModel = this.threeLayer.toModel(pivot, {
3470
- coordinate,
3471
- altitude
3472
- });
3473
- this.threeLayer.addMesh(baseObjectModel);
3474
- return baseObjectModel;
3285
+ escalatorMarker.addTo(this.gltfLayer);
3286
+ return escalatorMarker;
3475
3287
  }
3476
3288
  async createTree(coordinate, ordinal) {
3477
- const model = await this.loadModel3d({
3478
- url: "https://dashboard.situm.com/uploads/3dmodels/demoaccount/arbol.glb",
3479
- properties: {
3480
- rotation: {
3481
- x: 0.5 * Math.PI,
3482
- // Rotate the model up (new_escalator.glb)
3483
- y: 0,
3484
- z: 0
3485
- },
3486
- position: { x: 0, y: 0, z: 0 },
3487
- scale: 0.01
3289
+ const treeMarker = new maptalks4.GLTFMarker(coordinate, {
3290
+ symbol: {
3291
+ url: "https://dashboard.situm.com/uploads/3dmodels/demoaccount/new_escalator.glb"
3488
3292
  }
3489
3293
  });
3490
- const altitude = ordinal * HEIGHT_METER;
3491
- const baseObjectModel = this.threeLayer.toModel(model, {
3492
- coordinate,
3493
- altitude
3494
- });
3495
- this.threeLayer.addMesh(baseObjectModel);
3496
- return baseObjectModel;
3294
+ treeMarker.addTo(this.gltfLayer);
3295
+ return treeMarker;
3296
+ }
3297
+ async createBuilding(coordinate, ordinal) {
3298
+ return Promise.resolve(null);
3497
3299
  }
3498
3300
  createElement(f) {
3499
3301
  switch (f.feature_type) {
@@ -3516,34 +3318,34 @@ var Element3DRenderer = class extends EventTarget {
3516
3318
  }
3517
3319
  });
3518
3320
  }
3519
- async loadModel3d(model3d) {
3520
- const loader = new GLTFLoader2();
3521
- loader.setDRACOLoader(this.dracoLoader);
3522
- const { url, properties: modelProperties } = model3d;
3523
- const gltf = await loader.loadAsync(url);
3524
- const model = gltf.scene;
3525
- model.rotation.x = modelProperties.rotation.x;
3526
- model.rotation.y = modelProperties.rotation.y;
3527
- model.position.x = modelProperties.position.x;
3528
- model.position.y = modelProperties.position.y;
3529
- model.position.z = modelProperties.position.z;
3530
- const scale2 = modelProperties.scale;
3531
- model.scale.set(scale2, scale2, scale2);
3532
- return model;
3533
- }
3534
- createMarker = (coordinates, ordinal, text) => {
3535
- const options = {
3536
- // scale: 0.05,
3537
- // altitude: ordinal * HEIGHT_METER,
3538
- text
3539
- // interactive: true,
3540
- };
3541
- const marker = new TextSpriteMarker(coordinates, options, this.threeLayer);
3542
- this.threeLayer.addMesh([marker]);
3543
- return marker;
3544
- };
3545
- removeMarker = () => {
3546
- };
3321
+ createHighlightController(element) {
3322
+ if (!(element instanceof BaseObject5)) {
3323
+ return null;
3324
+ }
3325
+ switch (element.type) {
3326
+ case "ExtrudePolygon": {
3327
+ const mesh = element.getObject3d();
3328
+ const originalMaterial = mesh.material;
3329
+ const highlightMaterial = this.getOrCreateMaterialByColor("#ff0000");
3330
+ return {
3331
+ start: () => {
3332
+ mesh.material = highlightMaterial;
3333
+ },
3334
+ clear: () => {
3335
+ mesh.material = originalMaterial;
3336
+ }
3337
+ };
3338
+ }
3339
+ default: {
3340
+ return {
3341
+ start() {
3342
+ },
3343
+ clear() {
3344
+ }
3345
+ };
3346
+ }
3347
+ }
3348
+ }
3547
3349
  render() {
3548
3350
  this.threeLayer._needsUpdate = !this.threeLayer._needsUpdate;
3549
3351
  if (this.threeLayer._needsUpdate) {
@@ -3651,7 +3453,10 @@ var Element2DRenderer = class extends EventTarget {
3651
3453
  async createEscalator(f, coordinates) {
3652
3454
  return Promise.resolve(null);
3653
3455
  }
3654
- async createTree(f, coordinates) {
3456
+ async createTree(coordinates) {
3457
+ return Promise.resolve(null);
3458
+ }
3459
+ async createBuilding(coordinate, ordinal) {
3655
3460
  return Promise.resolve(null);
3656
3461
  }
3657
3462
  createElement = (imdfFeature) => {
@@ -3671,6 +3476,15 @@ var Element2DRenderer = class extends EventTarget {
3671
3476
  element.hide();
3672
3477
  });
3673
3478
  }
3479
+ createHighlightController(element) {
3480
+ if (!(element instanceof maptalks5.Geometry)) return null;
3481
+ return {
3482
+ start() {
3483
+ },
3484
+ clear() {
3485
+ }
3486
+ };
3487
+ }
3674
3488
  };
3675
3489
 
3676
3490
  // src/IndoorMap/renderer/2d/Marker2DRenderer.ts
@@ -3681,6 +3495,7 @@ var Marker2DRenderer = class extends EventTarget {
3681
3495
  markerLayer;
3682
3496
  constructor(map) {
3683
3497
  super();
3498
+ this.map = map;
3684
3499
  }
3685
3500
  createMarker = (coordinates, ordinal, content) => {
3686
3501
  const marker = new maptalks6.ui.UIMarker(coordinates, {
@@ -3689,86 +3504,216 @@ var Marker2DRenderer = class extends EventTarget {
3689
3504
  collisionFadeIn: true,
3690
3505
  altitude: 0
3691
3506
  });
3692
- marker.addTo(this.map);
3693
- return marker;
3694
- };
3695
- removeMarker = (marker) => {
3696
- marker.remove();
3697
- };
3698
- showMarkers(elements, ordinalDiff = 0) {
3507
+ marker.addTo(this.map);
3508
+ return marker;
3509
+ };
3510
+ removeMarker = (marker) => {
3511
+ marker.remove();
3512
+ };
3513
+ showMarkers(elements, ordinalDiff = 0) {
3514
+ }
3515
+ hideMarkers(elements, ordinalDiff = 0) {
3516
+ }
3517
+ };
3518
+
3519
+ // src/IndoorMap/renderer/3d/Marker3DRenderer.ts
3520
+ import * as maptalks7 from "maptalks-gl";
3521
+
3522
+ // src/IndoorMap/renderer/3d/objects/TextSpriteMarker.ts
3523
+ import { Coordinate as Coordinate2, Util as Util4 } from "maptalks";
3524
+ import * as THREE2 from "three";
3525
+ import { BaseObject as BaseObject6 } from "maptalks.three";
3526
+ import { isNil, set } from "lodash";
3527
+
3528
+ // src/IndoorMap/renderer/utils/interpolateStops.ts
3529
+ var interpolateStops = ({ stops }, zoom) => {
3530
+ if (zoom <= stops[0][0]) return stops[0][1];
3531
+ if (zoom >= stops[stops.length - 1][0]) return stops[stops.length - 1][1];
3532
+ for (let i = 0; i < stops.length - 1; i++) {
3533
+ const [z1, v1] = stops[i];
3534
+ const [z2, v2] = stops[i + 1];
3535
+ if (zoom >= z1 && zoom <= z2) {
3536
+ const t = (zoom - z1) / (z2 - z1);
3537
+ return v1 + t * (v2 - v1);
3538
+ }
3539
+ }
3540
+ };
3541
+
3542
+ // src/IndoorMap/renderer/3d/objects/TextSpriteMarker.ts
3543
+ var OPTIONS4 = {
3544
+ // Texture options
3545
+ text: "",
3546
+ textAlign: "center",
3547
+ color: "#ffffff",
3548
+ fontFamily: "sans-serif",
3549
+ fontSize: 28,
3550
+ fontWeight: 400,
3551
+ background: "transparent",
3552
+ lineHeight: 32,
3553
+ padding: 8,
3554
+ strokeColor: "#000000",
3555
+ strokeWidth: 3,
3556
+ strokeStyle: "round",
3557
+ // Sprite options
3558
+ /* Overall scale multiplier */
3559
+ scale: 1,
3560
+ altitude: 0,
3561
+ opacity: 1
3562
+ };
3563
+ var TextSpriteMarker = class extends BaseObject6 {
3564
+ #altitudeOffset = 0;
3565
+ constructor(coordinate, options, layer, properties = {}) {
3566
+ options = Util4.extend({}, OPTIONS4, options, { layer });
3567
+ super();
3568
+ this._coordinate = new Coordinate2(coordinate);
3569
+ this._initOptions(options);
3570
+ this._createGroup();
3571
+ this.properties = { ...properties };
3572
+ const sprite = this._createSprite();
3573
+ this.getObject3d().add(sprite);
3574
+ this._updatePosition();
3575
+ this.type = "TextSpriteMarker";
3576
+ }
3577
+ getOptions() {
3578
+ return super.getOptions();
3579
+ }
3580
+ _createSprite() {
3581
+ const options = this.getOptions();
3582
+ const texture = this._createTextTexture(options.text, options);
3583
+ const material = new THREE2.SpriteMaterial({
3584
+ map: texture,
3585
+ transparent: true,
3586
+ alphaTest: 0.1
3587
+ });
3588
+ const sprite = new THREE2.Sprite(material);
3589
+ const w = texture.image.width;
3590
+ const h = texture.image.height;
3591
+ const base = 1 / 16;
3592
+ const normalizedScale = options.scale / this.getMap().getGLRes();
3593
+ sprite.scale.set(w * base * normalizedScale, h * base * normalizedScale, 1);
3594
+ this.#altitudeOffset = Math.max(
3595
+ h * base * options.scale * 0.5,
3596
+ 0.05
3597
+ // minimum lift in world units
3598
+ );
3599
+ return sprite;
3600
+ }
3601
+ _createTextTexture(text, options = {}) {
3602
+ const {
3603
+ padding,
3604
+ fontSize,
3605
+ fontFamily,
3606
+ fontWeight,
3607
+ lineHeight,
3608
+ background,
3609
+ color,
3610
+ textAlign,
3611
+ strokeColor,
3612
+ strokeWidth,
3613
+ maxWidth
3614
+ } = options || {};
3615
+ const canvas = document.createElement("canvas");
3616
+ const ctx = canvas.getContext("2d");
3617
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
3618
+ const paragraphs = String(text).split("\n");
3619
+ const wrappedLines = [];
3620
+ paragraphs.forEach((paragraph) => {
3621
+ if (isNil(maxWidth) || isNaN(maxWidth)) {
3622
+ wrappedLines.push(paragraph);
3623
+ return;
3624
+ }
3625
+ const words = paragraph.split(/\s+/);
3626
+ let currentLine = "";
3627
+ words.forEach((word) => {
3628
+ const testLine = currentLine ? currentLine + " " + word : word;
3629
+ const testWidth = ctx.measureText(testLine).width;
3630
+ if (testWidth > maxWidth && currentLine) {
3631
+ wrappedLines.push(currentLine);
3632
+ currentLine = word;
3633
+ } else {
3634
+ currentLine = testLine;
3635
+ }
3636
+ });
3637
+ if (currentLine) {
3638
+ wrappedLines.push(currentLine);
3639
+ }
3640
+ });
3641
+ const lines = wrappedLines.length ? wrappedLines : [""];
3642
+ const widest = Math.max(...lines.map((l) => ctx.measureText(l).width), 0);
3643
+ const finalWidth = (maxWidth ? Math.min(widest, maxWidth) : widest) + padding * 2;
3644
+ const finalHeight = lineHeight * lines.length + padding * 2;
3645
+ canvas.width = finalWidth;
3646
+ canvas.height = finalHeight;
3647
+ const ctx2 = canvas.getContext("2d");
3648
+ ctx2.font = `${fontWeight} ${fontSize}px ${fontFamily}`;
3649
+ ctx2.textAlign = textAlign;
3650
+ if (background && background !== "transparent") {
3651
+ ctx2.fillStyle = background;
3652
+ ctx2.fillRect(0, 0, canvas.width, canvas.height);
3653
+ }
3654
+ lines.forEach((line, i) => {
3655
+ const y = padding + lineHeight * (i + 0.8);
3656
+ let x = padding;
3657
+ if (textAlign === "center") x = canvas.width / 2;
3658
+ if (textAlign === "right" || textAlign === "end")
3659
+ x = canvas.width - padding;
3660
+ if (strokeWidth > 0) {
3661
+ ctx2.lineWidth = strokeWidth;
3662
+ ctx2.lineJoin = "round";
3663
+ ctx2.miterLimit = 2;
3664
+ ctx2.strokeStyle = strokeColor;
3665
+ ctx2.strokeText(line, x, y);
3666
+ }
3667
+ ctx2.fillStyle = color;
3668
+ ctx2.fillText(line, x, y);
3669
+ });
3670
+ const texture = new THREE2.CanvasTexture(canvas);
3671
+ texture.needsUpdate = true;
3672
+ texture.minFilter = THREE2.LinearFilter;
3673
+ return texture;
3699
3674
  }
3700
- hideMarkers(elements, ordinalDiff = 0) {
3675
+ _updatePosition() {
3676
+ const options = this.getOptions();
3677
+ const layer = options.layer;
3678
+ if (!layer) return;
3679
+ const altitude = (options.altitude || 0) + this.#altitudeOffset;
3680
+ const z = layer.altitudeToVector3(altitude, altitude).x;
3681
+ const position = layer.coordinateToVector3(this._coordinate, z);
3682
+ set(this.properties, "default.position", position);
3683
+ this.getObject3d().position.copy(position);
3701
3684
  }
3702
- };
3703
-
3704
- // src/IndoorMap/renderer/3d/Marker3DRenderer.ts
3705
- import * as maptalks7 from "maptalks";
3706
-
3707
- // src/IndoorMap/renderer/utils/svg2material.ts
3708
- import { SpriteMaterial as SpriteMaterial5, TextureLoader as TextureLoader3 } from "three";
3709
- var svgToDataURL = (svgString, scaleFactor = 1) => {
3710
- const svgBlob = new Blob([svgString], { type: "image/svg+xml" });
3711
- const url = URL.createObjectURL(svgBlob);
3712
- const img = new Image();
3713
- return new Promise((resolve, reject) => {
3714
- img.onload = function() {
3715
- const newWidth = img.width * scaleFactor;
3716
- const newHeight = img.height * scaleFactor;
3717
- const canvas = document.createElement("canvas");
3718
- canvas.width = newWidth;
3719
- canvas.height = newHeight;
3720
- const ctx = canvas.getContext("2d");
3721
- ctx.drawImage(img, 0, 0, newWidth, newHeight);
3722
- const pngDataUrl = canvas.toDataURL("image/png");
3723
- resolve(pngDataUrl);
3724
- };
3725
- img.onerror = function(error) {
3726
- reject(error);
3727
- };
3728
- img.src = url;
3729
- });
3730
- };
3731
- var createSVGPathFromMarkerSymbol2 = (style) => {
3732
- const {
3733
- markerWidth = 24,
3734
- markerDx = 0,
3735
- markerDy = 0,
3736
- // markerFill,
3737
- markerPath,
3738
- fill = "#000000"
3739
- } = style;
3740
- const scale2 = markerWidth / 24;
3741
- const strokeWidth = 2;
3742
- const halfStrokeWidth = 0.5 * strokeWidth;
3743
- if (Array.isArray(markerPath)) {
3744
- return markerPath.map(
3745
- ({ path, fill: fill2 }) => `<path d="${path}" style="transform:translate(${markerDx}px, ${markerDy}px) scale(${scale2})" fill="${fill2}" stroke="#ffffff" stroke-width="${strokeWidth}" />`
3746
- );
3685
+ _animation() {
3686
+ const layer = this.getLayer();
3687
+ if (!this.isAdd || !layer) return;
3688
+ if (this._visible === true) {
3689
+ const zoom = layer.map.getZoom();
3690
+ const object3d = this.getObject3d();
3691
+ const { opacity } = this.getOptions();
3692
+ let opacityValue;
3693
+ if (typeof opacity === "number") {
3694
+ opacityValue = opacity ?? 1;
3695
+ } else if (Array.isArray(opacity.stops)) {
3696
+ opacityValue = interpolateStops(opacity, zoom);
3697
+ } else {
3698
+ throw new Error(`Unknown opacity value ${opacity}`);
3699
+ }
3700
+ const visible = opacityValue > 0.5;
3701
+ object3d.visible = visible;
3702
+ }
3747
3703
  }
3748
- return `<path d="${markerPath}" style="transform:translate(${markerDx}px, ${markerDy}px) scale(${scale2})" fill="${fill}" />`;
3749
- };
3750
- var createSpriteMaterialByLabelSymbol2 = (labelSymbol) => {
3751
- const material = new SpriteMaterial5();
3752
- try {
3753
- const [base, icon] = labelSymbol ?? [{}, {}];
3754
- const { markerWidth: baseWidth = 24 } = base;
3755
- const { markerWidth: iconWidth = 24 } = icon;
3756
- const viewBoxDimension = Math.max(baseWidth, iconWidth);
3757
- const baseSVG = createSVGPathFromMarkerSymbol2(base);
3758
- const iconSVG = icon ? createSVGPathFromMarkerSymbol2(icon) : "";
3759
- const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${viewBoxDimension}" height="${viewBoxDimension}">${baseSVG}${iconSVG}</svg>`;
3760
- const textureLoader = new TextureLoader3();
3761
- const scaleFactor = 200 / 24;
3762
- svgToDataURL(svg, scaleFactor).then((png) => {
3763
- const texture = textureLoader.load(png, () => {
3764
- material.map = texture;
3765
- material.needsUpdate = true;
3766
- });
3767
- });
3768
- } catch (error) {
3769
- console.warn(`Error createSpriteMaterialByLabelSymbol: `, labelSymbol);
3704
+ setText(text) {
3705
+ const options = this.getOptions();
3706
+ options.text = text;
3707
+ const newSprite = this._createSprite();
3708
+ const group = this.getObject3d();
3709
+ group.children.forEach((child) => group.remove(child));
3710
+ group.add(newSprite);
3711
+ this._updatePosition();
3712
+ }
3713
+ setAltitude(altitude) {
3714
+ const bottomHeight = this.options.bottomHeight ?? 0;
3715
+ return super.setAltitude(altitude + bottomHeight + this.#altitudeOffset);
3770
3716
  }
3771
- return material;
3772
3717
  };
3773
3718
 
3774
3719
  // src/IndoorMap/renderer/3d/Marker3DRenderer.ts
@@ -3819,40 +3764,41 @@ var Marker3DRenderer = class extends EventTarget {
3819
3764
  });
3820
3765
  }
3821
3766
  /** Marker */
3822
- getOrCreateIconMaterial(key) {
3823
- if (!this.materialByKey) this.materialByKey = /* @__PURE__ */ new Map();
3824
- const existingMaterial = this.materialByKey.get(key);
3825
- if (existingMaterial) return existingMaterial;
3826
- const baseSymbol = {
3827
- markerType: "path",
3828
- markerPath: [
3829
- {
3830
- path: "M20.775 1.2H1.225V20.35H8.215L11.3 22.8L14.385 20.35H20.775V1.2Z",
3831
- fill: "#ff0000"
3832
- }
3833
- ],
3834
- markerPathWidth: 24,
3835
- markerPathHeight: 24
3836
- };
3837
- const markerSymbol = {
3838
- markerType: "path",
3839
- markerPath: [],
3840
- // TODO: Get Path by featureType.category
3841
- // markerPath: [{ fill: "#FFFFFF", path: "M 19 3 H 5 c -1.1 0 -2 0.9 -2 2 v 14 c 0 1.1 0.9 2 2 2 h 14 c 1.1 0 2 -0.9 2 -2 V 5 c 0 -1.1 -0.9 -2 -2 -2 Z m -2 6 h -1.7 l -5 9 H 7 c -0.83 0 -1.5 -0.67 -1.5 -1.5 S 6.17 15 7 15 h 1.7 l 5 -9 H 17 c 0.83 0 1.5 0.67 1.5 1.5 S 17.83 9 17 9 Z" }],
3842
- markerPathWidth: 24,
3843
- markerPathHeight: 24,
3844
- markerWidth: 24,
3845
- markerHeight: 24,
3846
- markerDy: 1.5,
3847
- markerDx: 1.5
3848
- };
3849
- const created = createSpriteMaterialByLabelSymbol2([
3850
- baseSymbol,
3851
- markerSymbol
3852
- ]);
3853
- this.materialByKey.set(key, created);
3854
- return created;
3855
- }
3767
+ // getOrCreateIconMaterial(key) {
3768
+ // if (!this.materialByKey) this.materialByKey = new Map()
3769
+ // const existingMaterial = this.materialByKey.get(key)
3770
+ // if (existingMaterial) return existingMaterial
3771
+ // // Create new
3772
+ // const baseSymbol: maptalks.Path = {
3773
+ // markerType: "path",
3774
+ // markerPath: [
3775
+ // {
3776
+ // path: "M20.775 1.2H1.225V20.35H8.215L11.3 22.8L14.385 20.35H20.775V1.2Z",
3777
+ // fill: "#ff0000",
3778
+ // },
3779
+ // ],
3780
+ // markerPathWidth: 24,
3781
+ // markerPathHeight: 24
3782
+ // }
3783
+ // const markerSymbol: maptalks.PathMarkerSymbol = {
3784
+ // markerType: "path",
3785
+ // markerPath: [],
3786
+ // // TODO: Get Path by featureType.category
3787
+ // // markerPath: [{ fill: "#FFFFFF", path: "M 19 3 H 5 c -1.1 0 -2 0.9 -2 2 v 14 c 0 1.1 0.9 2 2 2 h 14 c 1.1 0 2 -0.9 2 -2 V 5 c 0 -1.1 -0.9 -2 -2 -2 Z m -2 6 h -1.7 l -5 9 H 7 c -0.83 0 -1.5 -0.67 -1.5 -1.5 S 6.17 15 7 15 h 1.7 l 5 -9 H 17 c 0.83 0 1.5 0.67 1.5 1.5 S 17.83 9 17 9 Z" }],
3788
+ // markerPathWidth: 24,
3789
+ // markerPathHeight: 24,
3790
+ // markerWidth: 24,
3791
+ // markerHeight: 24,
3792
+ // markerDy: 1.5,
3793
+ // markerDx: 1.5,
3794
+ // }
3795
+ // const created = createSpriteMaterialByLabelSymbol([
3796
+ // baseSymbol,
3797
+ // markerSymbol,
3798
+ // ])
3799
+ // this.materialByKey.set(key, created)
3800
+ // return created
3801
+ // }
3856
3802
  };
3857
3803
 
3858
3804
  // src/IndoorMap/renderer/utils/angleBetweenLineString.ts
@@ -3874,11 +3820,17 @@ var angleBetweenLineStrings = (line1, line2) => {
3874
3820
  };
3875
3821
 
3876
3822
  // src/IndoorMap/renderer/RendererManager.ts
3823
+ function delay(ms) {
3824
+ return new Promise((resolve) => setTimeout(resolve, ms));
3825
+ }
3877
3826
  var RendererManager = class extends EventTarget {
3878
3827
  map;
3879
3828
  options;
3880
3829
  // Client for fetching data
3881
3830
  #dataClient;
3831
+ #isClicked = false;
3832
+ #onClickElement = (e) => {
3833
+ };
3882
3834
  /** Elements: Responsible for converting feature info elements and add to map */
3883
3835
  elementRenderer;
3884
3836
  markerRenderer;
@@ -3887,6 +3839,7 @@ var RendererManager = class extends EventTarget {
3887
3839
  currentOrdinals;
3888
3840
  markersMap;
3889
3841
  markersByOrdinal;
3842
+ highlightControllers = [];
3890
3843
  constructor(map, dataClient, options) {
3891
3844
  super();
3892
3845
  this.map = map;
@@ -3896,48 +3849,52 @@ var RendererManager = class extends EventTarget {
3896
3849
  this.markersMap = /* @__PURE__ */ new Map();
3897
3850
  this.markersByOrdinal = /* @__PURE__ */ new Map();
3898
3851
  this.#dataClient = dataClient;
3852
+ const _this = this;
3899
3853
  if (options.type === "3D") {
3900
- const threeLayer = new ThreeLayer3("elements", {
3901
- forceRenderOnMoving: true,
3902
- forceRenderOnRotating: true
3903
- });
3904
- const _this = this;
3854
+ const groupLayer = this.map.getLayer("group");
3855
+ const threeLayer = groupLayer.getLayer("three");
3905
3856
  threeLayer.prepareToDraw = function(gl, scene, camera) {
3906
3857
  const ambientLight = new THREE3.AmbientLight(16777215, 0.3);
3907
3858
  scene.add(ambientLight);
3908
3859
  const dirColor = 16777215;
3909
3860
  const dllight = new THREE3.DirectionalLight(dirColor, 0.8);
3910
- dllight.position.set(0, -10, 10).normalize();
3861
+ dllight.position.set(0, -10, 20).normalize();
3911
3862
  scene.add(dllight);
3912
3863
  const hemi = new THREE3.HemisphereLight(16777215, 4473924, 0.4);
3913
3864
  scene.add(hemi);
3914
- _this.elementRenderer = new Element3DRenderer(map, options.elements, threeLayer);
3865
+ _this.elementRenderer = new Element3DRenderer(map, options.elements);
3915
3866
  _this.markerRenderer = new Marker3DRenderer(map, {}, threeLayer);
3916
3867
  if (typeof options.onRendererReady === "function") {
3917
3868
  options.onRendererReady();
3918
3869
  }
3919
3870
  _this.#createElements();
3920
3871
  };
3921
- threeLayer.addTo(this.map);
3922
3872
  } else {
3923
3873
  this.elementRenderer = new Element2DRenderer(map, options.elements);
3924
3874
  this.markerRenderer = new Marker2DRenderer(map);
3925
3875
  this.#createElements();
3926
3876
  }
3927
3877
  }
3878
+ set onClickElement(func) {
3879
+ this.#onClickElement = func;
3880
+ }
3881
+ handleClickElement = (e) => {
3882
+ if (this.#isClicked) return;
3883
+ this.#isClicked = true;
3884
+ const onClickElement = this.#onClickElement;
3885
+ if (!_isFunction(onClickElement)) return;
3886
+ this.#onClickElement(e);
3887
+ this.#isClicked = false;
3888
+ };
3928
3889
  getElementsByOrdinal = (ordinal) => {
3929
3890
  const exist = this.elementsByOrdinal.get(ordinal);
3930
3891
  if (!exist) this.elementsByOrdinal.set(ordinal, []);
3931
3892
  return this.elementsByOrdinal.get(ordinal);
3932
3893
  };
3933
- getMarkersByOrdinal = (ordinal) => {
3934
- const exist = this.markersByOrdinal.get(ordinal);
3935
- if (!exist) this.markersByOrdinal.set(ordinal, []);
3936
- return this.markersByOrdinal.get(ordinal);
3937
- };
3938
3894
  addElementsToManager = (id, elements, ordinal) => {
3939
3895
  this.elementsMap.set(id, elements);
3940
3896
  elements.forEach((el) => {
3897
+ el.on("click", (e) => this.handleClickElement(id));
3941
3898
  this.getElementsByOrdinal(ordinal).push(el);
3942
3899
  });
3943
3900
  const inOrdinal = Array.isArray(this.currentOrdinals) ? this.currentOrdinals.includes(ordinal) : ordinal === this.currentOrdinals;
@@ -3947,19 +3904,8 @@ var RendererManager = class extends EventTarget {
3947
3904
  this.elementRenderer.hideElements(elements, ordinal);
3948
3905
  }
3949
3906
  };
3950
- addMarkersToManager = (id, markers, ordinal) => {
3951
- this.markersMap.set(id, markers);
3952
- markers.forEach((el) => {
3953
- this.getMarkersByOrdinal(ordinal).push(el);
3954
- });
3955
- const inOrdinal = Array.isArray(this.currentOrdinals) ? this.currentOrdinals.includes(ordinal) : ordinal === this.currentOrdinals;
3956
- if (inOrdinal) {
3957
- this.markerRenderer.showMarkers(markers, ordinal);
3958
- } else {
3959
- this.markerRenderer.hideMarkers(markers, ordinal);
3960
- }
3961
- };
3962
3907
  async #createElements() {
3908
+ await delay(this.options.delayBeforeCreateElements ?? 0);
3963
3909
  const levels = await this.#dataClient.filterByType("level", {
3964
3910
  populate: true
3965
3911
  });
@@ -4006,13 +3952,15 @@ var RendererManager = class extends EventTarget {
4006
3952
  }
4007
3953
  const thisOrdinal = escalator.properties.ordinal;
4008
3954
  const relationship = escalatorRelationships[0];
3955
+ if (!relationship.properties.origin?.id) throw new Error(`relationship (id=${relationship.id}) - origin not exists`);
3956
+ if (!relationship.properties.destination?.id) throw new Error(`relationship (id=${relationship.id}) - destination not exists`);
4009
3957
  const bothOpeningIds = [relationship.properties.origin.id, relationship.properties.destination.id];
4010
3958
  const bothOpenings = await Promise.all(
4011
3959
  bothOpeningIds.map((id) => this.#dataClient.findById("opening", id, { populate: true }))
4012
3960
  );
4013
3961
  const thisLevelOpening = bothOpenings.find((opening) => opening.properties.ordinal === thisOrdinal);
4014
3962
  const thatLevelOpening = bothOpenings.find((opening) => opening.properties.ordinal !== thisOrdinal);
4015
- const angle = angleBetweenLineStrings(thisLevelOpening.geometry.coordinates, thatLevelOpening.geometry.coordinates);
3963
+ const angle = 180 * (1 / Math.PI) * angleBetweenLineStrings(thisLevelOpening.geometry.coordinates, thatLevelOpening.geometry.coordinates);
4016
3964
  const direction = thisOrdinal < thatLevelOpening.properties.ordinal ? "up" : "down";
4017
3965
  const escalatorEntryPoint = turfCenter2(thisLevelOpening).geometry.coordinates;
4018
3966
  const element = await this.elementRenderer.createEscalator(escalator, escalatorEntryPoint, { direction, angle });
@@ -4021,7 +3969,7 @@ var RendererManager = class extends EventTarget {
4021
3969
  this.addElementsToManager(escalator.id, _elements, escalator.properties.ordinal);
4022
3970
  }
4023
3971
  } catch (err) {
4024
- console.log(`cannot create escalator`, err);
3972
+ console.warn(`cannot create escalator`, err.message);
4025
3973
  }
4026
3974
  }
4027
3975
  this.changeLevelByOrdinal(this.currentOrdinals);
@@ -4057,14 +4005,48 @@ var RendererManager = class extends EventTarget {
4057
4005
  }
4058
4006
  }
4059
4007
  }
4008
+ highlightElements = (elemIds, options) => {
4009
+ const { reset = true } = options ?? {};
4010
+ if (reset) {
4011
+ this.clearHighlightElements();
4012
+ }
4013
+ const elements = elemIds.map((id) => this.elementsMap.get(id)).flat();
4014
+ elements.forEach((element) => {
4015
+ const controller = this.elementRenderer.createHighlightController(element);
4016
+ controller.start();
4017
+ this.highlightControllers.push(controller);
4018
+ });
4019
+ };
4020
+ clearHighlightElements = () => {
4021
+ this.highlightControllers.forEach((controller) => {
4022
+ if (_isFunction(controller?.clear)) controller.clear();
4023
+ });
4024
+ };
4060
4025
  /**
4061
4026
  * ========================================================================
4062
4027
  * Markers
4063
4028
  * ======================================================================== */
4029
+ _getMarkersByOrdinal = (ordinal) => {
4030
+ const exist = this.markersByOrdinal.get(ordinal);
4031
+ if (!exist) this.markersByOrdinal.set(ordinal, []);
4032
+ return this.markersByOrdinal.get(ordinal);
4033
+ };
4034
+ _addMarkersToManager = (id, markers, ordinal) => {
4035
+ this.markersMap.set(id, markers);
4036
+ markers.forEach((el) => {
4037
+ this._getMarkersByOrdinal(ordinal).push(el);
4038
+ });
4039
+ const inOrdinal = Array.isArray(this.currentOrdinals) ? this.currentOrdinals.includes(ordinal) : ordinal === this.currentOrdinals;
4040
+ if (inOrdinal) {
4041
+ this.markerRenderer.showMarkers(markers, ordinal);
4042
+ } else {
4043
+ this.markerRenderer.hideMarkers(markers, ordinal);
4044
+ }
4045
+ };
4064
4046
  createMarker(coordinate, ordinal, text, options) {
4065
4047
  const marker = this.markerRenderer.createMarker(coordinate, ordinal, text, options);
4066
4048
  const markerId = `${this.markersMap.size + 1}`;
4067
- this.addMarkersToManager(markerId, [marker], ordinal);
4049
+ this._addMarkersToManager(markerId, [marker], ordinal);
4068
4050
  }
4069
4051
  clearMarkers() {
4070
4052
  for (const [markerId, marker] of this.markersMap) {
@@ -4082,6 +4064,7 @@ var defaultOptions = {
4082
4064
  locale: DEFAULT_LOCALE
4083
4065
  };
4084
4066
  var IndoorMap = class extends EventTarget {
4067
+ options;
4085
4068
  //TODO: refac functions; let them do only 1 thing in a function
4086
4069
  /** Note: "#" means private variables */
4087
4070
  #styler = null;
@@ -4133,14 +4116,18 @@ var IndoorMap = class extends EventTarget {
4133
4116
  };
4134
4117
  constructor(elementId, options) {
4135
4118
  super();
4119
+ const combinedOptions = _6.merge({}, defaultOptions, options);
4120
+ this.options = options;
4136
4121
  const {
4137
4122
  onMapReady,
4138
4123
  onMapLoading,
4139
4124
  pixelRatio,
4140
4125
  locale
4141
- } = _6.merge({}, defaultOptions, options);
4126
+ } = combinedOptions;
4142
4127
  this.map = new Map2(elementId, {
4143
4128
  attribution: false,
4129
+ // Temporart set, not really default view
4130
+ // Default view is set in camera manager
4144
4131
  center: INITIAL_CENTER,
4145
4132
  zoom: INITIAL_ZOOM,
4146
4133
  clickTimeThreshold: 600,
@@ -4156,8 +4143,16 @@ var IndoorMap = class extends EventTarget {
4156
4143
  }),
4157
4144
  layers: []
4158
4145
  });
4146
+ const groupLayer = new GroupGLLayer("group", [], {}).addTo(this.map);
4147
+ const threeLayer = new ThreeLayer4("three", {
4148
+ forceRenderOnMoving: true,
4149
+ forceRenderOnRotating: true
4150
+ });
4151
+ groupLayer.addLayer(threeLayer);
4152
+ const gltfLayer = new GLTFLayer("gltf");
4153
+ groupLayer.addLayer(gltfLayer);
4159
4154
  this.rendererManager = new RendererManager(this.map, options.dataClient, options.renderer);
4160
- this.camera = new CameraManager(this.map);
4155
+ this.camera = new CameraManager(this.map, options.camera);
4161
4156
  this.locale = locale;
4162
4157
  this.pixelRatio = pixelRatio;
4163
4158
  this.onMapReady = onMapReady;
@@ -4168,19 +4163,21 @@ var IndoorMap = class extends EventTarget {
4168
4163
  }
4169
4164
  set dataClient(value) {
4170
4165
  this.#dataClient = value;
4171
- this.#dataClient.filterByType("venue").then((venues) => {
4172
- const venueCenters = turfCenter3(featureCollection(venues));
4173
- const [x, y] = venueCenters.geometry.coordinates;
4174
- const center2 = new Coordinate4(x, y);
4175
- this.camera.setView({ center: center2, pitch: 60, zoom: 19 });
4176
- });
4177
- }
4178
- on(eventName, handler) {
4179
- this.map.on(eventName, handler);
4166
+ if (!this.options.camera?.defaultView?.center) {
4167
+ this.#dataClient.filterByType("venue").then((venues) => {
4168
+ const venueCenters = turfCenter3(featureCollection(venues));
4169
+ const [x, y] = venueCenters.geometry.coordinates;
4170
+ const center2 = new Coordinate4(x, y);
4171
+ this.camera.setView({ center: center2, pitch: 60, zoom: 19 });
4172
+ });
4173
+ }
4180
4174
  }
4181
4175
  /**
4182
4176
  * Events
4183
4177
  */
4178
+ on(eventName, handler) {
4179
+ this.map.on(eventName, handler);
4180
+ }
4184
4181
  handleMapClick = ({ coordinate }) => {
4185
4182
  const { x, y } = coordinate;
4186
4183
  console.log(
@@ -4236,40 +4233,12 @@ var IndoorMap = class extends EventTarget {
4236
4233
  this.map.off("moveend", this.#findAndSetVenueInView);
4237
4234
  }
4238
4235
  }
4239
- get ordinals() {
4240
- return this.#ordinals || [];
4241
- }
4242
- set ordinals(value) {
4243
- if (!Array.isArray(value)) throw new Error("ordinals must be Array");
4244
- this.#ordinals = value;
4245
- }
4246
4236
  set billboards(value) {
4247
4237
  this.#billboards = value;
4248
4238
  }
4249
- set mapConfig(value) {
4250
- this.#mapConfig = value;
4251
- }
4252
4239
  set mapDecorations(value) {
4253
4240
  this.#mapDecorations = value;
4254
4241
  }
4255
- set maxZoom(value) {
4256
- this.map.setMaxZoom(value);
4257
- const spatialReference = {
4258
- projection: "EPSG:3857",
4259
- resolutions: (function() {
4260
- const resolutions = [];
4261
- const d = 2 * 6378137 * Math.PI;
4262
- for (let i = 0; i < value; i++) {
4263
- resolutions[i] = d / (256 * Math.pow(2, i));
4264
- }
4265
- return resolutions;
4266
- })()
4267
- };
4268
- this.map.setSpatialReference(spatialReference);
4269
- }
4270
- set minZoom(value) {
4271
- this.map.setMinZoom(value);
4272
- }
4273
4242
  set groundLabels(value) {
4274
4243
  this.#groundLabels = value;
4275
4244
  }
@@ -4277,7 +4246,7 @@ var IndoorMap = class extends EventTarget {
4277
4246
  this.map.setDevicePixelRatio(value);
4278
4247
  }
4279
4248
  set onClickElement(func) {
4280
- this.#onClickElement = func;
4249
+ this.rendererManager.onClickElement = func;
4281
4250
  }
4282
4251
  set locale(value) {
4283
4252
  this.#locale = value || defaultOptions.locale;
@@ -4305,9 +4274,6 @@ var IndoorMap = class extends EventTarget {
4305
4274
  this.#onClickElement(e);
4306
4275
  this.#isClicked = false;
4307
4276
  };
4308
- setCenter(center2, padding) {
4309
- this.map.setCenter(center2, padding);
4310
- }
4311
4277
  async #legacy_createElements() {
4312
4278
  const {
4313
4279
  // 2D
@@ -4321,33 +4287,14 @@ var IndoorMap = class extends EventTarget {
4321
4287
  create3DFootprint,
4322
4288
  create3DGroundLabel,
4323
4289
  create3DBillboard,
4324
- createVenue3DModel,
4325
4290
  createExtrudedUnit,
4326
- create3DFixture,
4327
4291
  create3DAmenityMarker,
4328
4292
  create3DOccupantAmenityMarker,
4329
4293
  create3DOpeningMarker,
4330
- createOccupantGroundLabel,
4331
- // Light
4332
- createAmbientLight,
4333
- createDirectionalLight
4294
+ createOccupantGroundLabel
4334
4295
  } = this.#styler;
4335
4296
  let elements = {};
4336
4297
  let object3ds = [];
4337
- const scene = this.threeLayer.getScene();
4338
- if (scene) {
4339
- const {
4340
- ambientLight: ambientLightConfig = {},
4341
- directionalLight: directionalLightConfig = {}
4342
- } = _6.get(this.#mapConfig, "light", {
4343
- ambientLight: {},
4344
- directionalLight: {}
4345
- });
4346
- const ambientLight = createAmbientLight(ambientLightConfig);
4347
- scene.add(ambientLight);
4348
- const light = createDirectionalLight(directionalLightConfig);
4349
- scene.add(light);
4350
- }
4351
4298
  for (const feature2 of this.#features) {
4352
4299
  try {
4353
4300
  const { feature_type: featureType, properties, id } = feature2;
@@ -4370,16 +4317,6 @@ var IndoorMap = class extends EventTarget {
4370
4317
  feature2
4371
4318
  );
4372
4319
  switch (featureType) {
4373
- case "venue": {
4374
- geometry = createVenue(feature2).addTo(layer);
4375
- const models = await createVenue3DModel(feature2, this.threeLayer);
4376
- models.forEach((model) => {
4377
- model.on("click", this.handleClickElement);
4378
- object3ds.push(model);
4379
- this.#venueObjects.push(model);
4380
- });
4381
- break;
4382
- }
4383
4320
  case "amenity": {
4384
4321
  if (feature2.properties.is_featured) {
4385
4322
  const billboardObj = create3DBillboard(feature2, this.threeLayer);
@@ -4423,127 +4360,6 @@ var IndoorMap = class extends EventTarget {
4423
4360
  geometry = createSection(feature2)?.addTo(layer);
4424
4361
  break;
4425
4362
  }
4426
- case "occupant": {
4427
- switch (category) {
4428
- // Create only marker if it is amenity occupant
4429
- case "currencyexchange":
4430
- case "donationcenter":
4431
- case "postoffice":
4432
- const markerFeature = {
4433
- ...feature2,
4434
- geometry: feature2.properties?.anchor?.geometry
4435
- };
4436
- const marker3d = create3DOccupantAmenityMarker(
4437
- markerFeature,
4438
- this.threeLayer,
4439
- extrudeConfig
4440
- )?.on("click", this.handleClickElement);
4441
- object3ds.push(marker3d);
4442
- break;
4443
- default: {
4444
- const { kiosk, anchor } = feature2.properties;
4445
- const { unit } = anchor.properties;
4446
- let mainLocation = kiosk || unit || null;
4447
- const relatedLocations = [
4448
- ...feature2.properties.units,
4449
- ...feature2.properties.kiosks
4450
- ].filter((f) => f.properties.ordinal !== properties.ordinal);
4451
- const occupantLocations = [mainLocation, ...relatedLocations];
4452
- const renderType = feature2.properties.render_type;
4453
- occupantLocations.forEach((location, index) => {
4454
- const isMainLocation = index === 0;
4455
- if (renderType === "Label") {
4456
- const occupantGroundLabel = createOccupantGroundLabel(
4457
- feature2,
4458
- location,
4459
- { textMarkerType, extrudeConfig },
4460
- this.threeLayer
4461
- );
4462
- if (occupantGroundLabel instanceof GroundLabel) {
4463
- occupantGroundLabel.on("click", this.handleClickElement);
4464
- occupantGroundLabel.addTo(this.threeLayer);
4465
- object3ds.push(occupantGroundLabel);
4466
- this.#groundObjects.push(occupantGroundLabel);
4467
- }
4468
- } else {
4469
- const occupantMarker = createOccupant(feature2, location, {
4470
- textMarkerType,
4471
- extrudeConfig
4472
- });
4473
- if (occupantMarker instanceof ui3.UIMarker) {
4474
- occupantMarker.addTo(this.map);
4475
- } else {
4476
- occupantMarker?.on("click", this.handleClickElement);
4477
- occupantMarker?.addTo(layer);
4478
- }
4479
- if (isMainLocation) {
4480
- geometry = occupantMarker;
4481
- } else {
4482
- elements[`${feature2.id}_${index}`] = {
4483
- geometry: occupantMarker,
4484
- properties: location.properties,
4485
- featureType: "occupant",
4486
- feature: feature2
4487
- };
4488
- }
4489
- }
4490
- });
4491
- }
4492
- }
4493
- break;
4494
- }
4495
- case "fixture": {
4496
- const models = await create3DFixture(feature2, this.threeLayer);
4497
- models.forEach((model) => {
4498
- model.on("click", this.handleClickElement);
4499
- object3ds.push(model);
4500
- this.#glbObjects.push(model);
4501
- });
4502
- if (!featureExtrudeConfig) {
4503
- geometry = createFixture(feature2)?.addTo(layer);
4504
- } else {
4505
- const locatedLevel = feature2?.properties?.level;
4506
- const levelExtrudeConfig = getExtrudeConfigByFeature(
4507
- extrudeConfig,
4508
- locatedLevel
4509
- );
4510
- const levelHeight = _6.get(levelExtrudeConfig, "height", 0);
4511
- const option = { ...featureExtrudeConfig, altitude: levelHeight };
4512
- const extrudedFixture = createExtrudedUnit(
4513
- feature2,
4514
- this.threeLayer,
4515
- option
4516
- );
4517
- object3ds.push(extrudedFixture);
4518
- }
4519
- break;
4520
- }
4521
- case "footprint": {
4522
- const objects = await create3DFootprint(
4523
- feature2,
4524
- this.threeLayer,
4525
- featureExtrudeConfig
4526
- );
4527
- objects.forEach((object) => {
4528
- object.on("click", () => {
4529
- const {
4530
- geometry: { coordinates }
4531
- } = turfCenter3(feature2);
4532
- this.camera.flyToAndZoomIn(coordinates, { pitch: 45 });
4533
- });
4534
- object3ds.push(object);
4535
- this.#objects.push(object);
4536
- });
4537
- if (feature2.properties.logo) {
4538
- const footprintMarker = create3DBillboard(
4539
- feature2,
4540
- this.threeLayer
4541
- );
4542
- object3ds.push(footprintMarker);
4543
- this.#billboardObjects.push(footprintMarker);
4544
- }
4545
- break;
4546
- }
4547
4363
  default:
4548
4364
  break;
4549
4365
  }
@@ -4612,27 +4428,6 @@ var IndoorMap = class extends EventTarget {
4612
4428
  changeLevelByOrdinal(ordinal) {
4613
4429
  this.rendererManager.changeLevelByOrdinal(ordinal);
4614
4430
  }
4615
- getFeatureExtent = (feature2, scaleFactor = 1) => {
4616
- const [minX, minY, maxX, maxY] = index_default(
4617
- scale(bboxPolygon(index_default(feature2)), scaleFactor)
4618
- );
4619
- return new Extent(minX, minY, maxX, maxY);
4620
- };
4621
- getExtentCenter = (extent) => {
4622
- return extent.getCenter();
4623
- };
4624
- getExtentZoom = (extent, options = {
4625
- isFraction: false,
4626
- padding: {
4627
- paddingLeft: 0,
4628
- paddingRight: 0,
4629
- paddingTop: 0,
4630
- paddingBottom: 0
4631
- }
4632
- }) => {
4633
- const { isFraction = false, padding } = options;
4634
- return this.map.getFitZoom(extent, isFraction, padding);
4635
- };
4636
4431
  findVenueInView = () => {
4637
4432
  const mapCenter = this.map.getCenter();
4638
4433
  const result = this.#venues.reduce((closest, venue) => {
@@ -4645,9 +4440,6 @@ var IndoorMap = class extends EventTarget {
4645
4440
  }, null);
4646
4441
  return result;
4647
4442
  };
4648
- flyTo = (center2, options) => {
4649
- this.camera.flyTo(center2, options);
4650
- };
4651
4443
  getLineStringBearing = (feature2) => {
4652
4444
  const { geometry } = feature2;
4653
4445
  const path = new LineString3(geometry.coordinates);
@@ -5163,33 +4955,6 @@ var IndoorMap = class extends EventTarget {
5163
4955
  /**
5164
4956
  * render (frame)
5165
4957
  */
5166
- getTargetViewCenter = (targetView, options = { offset: { top: 0, left: 0, right: 0, bottom: 0 } }) => {
5167
- const map = this.map;
5168
- const { offset } = options;
5169
- const { top = 0, left = 0, right = 0, bottom = 0 } = offset;
5170
- const originalState = {
5171
- bearing: map.getBearing(),
5172
- center: map.getCenter(),
5173
- pitch: map.getPitch(),
5174
- zoom: map.getZoom()
5175
- };
5176
- const finalView = {
5177
- bearing: _6.isNil(targetView.bearing) ? map.getBearing() : targetView.bearing,
5178
- center: _6.isNil(targetView.center) ? map.getCenter() : targetView.center,
5179
- pitch: _6.isNil(targetView.pitch) ? map.getPitch() : targetView.pitch,
5180
- zoom: _6.isNil(targetView.zoom) ? map.getZoom() : targetView.zoom
5181
- };
5182
- map.setView(finalView);
5183
- const projectedTargetCenter = map.coordinateToContainerPoint(finalView.center).add(right / 2 - left / 2, bottom / 2 - top / 2);
5184
- const adjustedTargetCenter = map.containerPointToCoordinate(
5185
- projectedTargetCenter
5186
- );
5187
- map.setView(originalState);
5188
- return adjustedTargetCenter;
5189
- };
5190
- setMaxExtent(extent) {
5191
- return this.map.setMaxExtent(extent);
5192
- }
5193
4958
  render() {
5194
4959
  const view = this.map.getView();
5195
4960
  const currBearing = view.bearing;
@@ -5198,7 +4963,8 @@ var IndoorMap = class extends EventTarget {
5198
4963
  this.threeLayer.redraw();
5199
4964
  }
5200
4965
  if (this.threeLayer) {
5201
- const objectOpacity = _6.clamp(38 - 2 * this.camera.getZoom(), 0, 1);
4966
+ const currentView = this.camera.getView();
4967
+ const objectOpacity = _6.clamp(38 - 2 * currentView.zoom, 0, 1);
5202
4968
  this.#objects.forEach((object) => {
5203
4969
  object.getObject3d().traverse((child) => {
5204
4970
  if (child.isMesh) child.material.opacity = objectOpacity;
@@ -5209,7 +4975,7 @@ var IndoorMap = class extends EventTarget {
5209
4975
  if (this.#billboardObjects) {
5210
4976
  this.#billboardObjects.forEach((object) => {
5211
4977
  const objectScale = _6.clamp(
5212
- 20 - 1 * this.camera.getZoom(),
4978
+ 20 - 1 * currentView.zoom,
5213
4979
  1,
5214
4980
  1.05
5215
4981
  );
@@ -5261,6 +5027,7 @@ export {
5261
5027
  MARKER_LAYER_NAME,
5262
5028
  NONIMDF_FEATURE_TYPES,
5263
5029
  ORIGIN_MARKER_ID,
5030
+ occupant_helper_exports as OccupantHelpers,
5264
5031
  POI_MARKER_LAYER_NAME,
5265
5032
  QueryObserver2 as QueryObserver,
5266
5033
  USER_LOCATION_ELEMENT_ID,
@@ -5288,6 +5055,16 @@ export {
5288
5055
  getRelatedLocationsByOccupant,
5289
5056
  getSuitablyValueBetweenBearings,
5290
5057
  isClickableFeature,
5058
+ isValidCoordinate,
5059
+ isValidLineString,
5060
+ isValidLineStringCoordinates,
5061
+ isValidMultiPolygon,
5062
+ isValidMultiPolygonCoordinates,
5063
+ isValidPoint,
5064
+ isValidPolygon,
5065
+ isValidPolygonCoordinates,
5066
+ matchFilter,
5067
+ matchFilters,
5291
5068
  safeFetchFeature,
5292
5069
  styledFeatureGenerator
5293
5070
  };