@mapvx/web-js 1.3.0-dev.2 → 1.4.0-dev.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.
- package/dist/cjs/config/draco.js +15 -0
- package/dist/cjs/config/draco.js.map +1 -0
- package/dist/cjs/domain/models/mapConfig.js.map +1 -1
- package/dist/cjs/domain/models/scene3D.js +3 -0
- package/dist/cjs/domain/models/scene3D.js.map +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/logger/logger.js +1 -1
- package/dist/cjs/logger/rollbar.js +1 -1
- package/dist/cjs/map/map.js +298 -245
- package/dist/cjs/map/map.js.map +1 -1
- package/dist/cjs/utils/3d.js +104 -3
- package/dist/cjs/utils/3d.js.map +1 -1
- package/dist/cjs/utils/loadGlb.js +63 -0
- package/dist/cjs/utils/loadGlb.js.map +1 -0
- package/dist/cjs/utils/three.js +55 -0
- package/dist/cjs/utils/three.js.map +1 -0
- package/dist/es/config/draco.d.ts +12 -0
- package/dist/es/config/draco.d.ts.map +1 -0
- package/dist/es/config/draco.js +12 -0
- package/dist/es/config/draco.js.map +1 -0
- package/dist/es/domain/models/mapConfig.d.ts +13 -0
- package/dist/es/domain/models/mapConfig.d.ts.map +1 -1
- package/dist/es/domain/models/mapConfig.js.map +1 -1
- package/dist/es/domain/models/scene3D.d.ts +308 -0
- package/dist/es/domain/models/scene3D.d.ts.map +1 -0
- package/dist/es/domain/models/scene3D.js +2 -0
- package/dist/es/domain/models/scene3D.js.map +1 -0
- package/dist/es/index.d.ts +1 -0
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js.map +1 -1
- package/dist/es/logger/logger.js +1 -1
- package/dist/es/logger/rollbar.js +1 -1
- package/dist/es/map/map.d.ts +30 -18
- package/dist/es/map/map.d.ts.map +1 -1
- package/dist/es/map/map.js +291 -238
- package/dist/es/map/map.js.map +1 -1
- package/dist/es/utils/3d.d.ts +39 -1
- package/dist/es/utils/3d.d.ts.map +1 -1
- package/dist/es/utils/3d.js +95 -2
- package/dist/es/utils/3d.js.map +1 -1
- package/dist/es/utils/loadGlb.d.ts +22 -0
- package/dist/es/utils/loadGlb.d.ts.map +1 -0
- package/dist/es/utils/loadGlb.js +57 -0
- package/dist/es/utils/loadGlb.js.map +1 -0
- package/dist/es/utils/three.d.ts +26 -0
- package/dist/es/utils/three.d.ts.map +1 -0
- package/dist/es/utils/three.js +26 -0
- package/dist/es/utils/three.js.map +1 -0
- package/dist/umd/index.js +23965 -21381
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -2
package/dist/es/map/map.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { MVTLayer } from "@deck.gl/geo-layers";
|
|
2
2
|
import { IconLayer, PathLayer, TextLayer } from "@deck.gl/layers";
|
|
3
3
|
import maplibregl, { LngLatBounds, Map, MercatorCoordinate, NavigationControl, setRTLTextPlugin, } from "maplibre-gl";
|
|
4
|
-
import * as THREE from "three";
|
|
5
|
-
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
6
4
|
import { Semaphore } from "../utils/semaphore";
|
|
5
|
+
import { THREE } from "../utils/three";
|
|
7
6
|
/** Shared GeoJSON source holding every circle drawn through the circle API. */
|
|
8
7
|
const CIRCLE_SOURCE_ID = "mapvx-circles";
|
|
9
8
|
/** Fill layer rendering the translucent interior of the circles. */
|
|
@@ -136,13 +135,15 @@ import { userLocationDataUrl } from "../assets/icons";
|
|
|
136
135
|
import { RouteController } from "../controllers/routeController";
|
|
137
136
|
import { rtlLanguages } from "../domain/models/_rtl";
|
|
138
137
|
import { InternalAnimationConfig, InternalAnimationDrawingConfig, } from "../domain/models/animation";
|
|
139
|
-
import { CIRCLE_RENDER_ORDERS, circleRing, cloneCircleRecord, MAPVX_BRAND_COLOR, resolveCircleConfig, } from "../domain/models/circle";
|
|
140
138
|
import { Loggeable } from "../domain/models/loggeable";
|
|
141
139
|
import { DEFAULT_TILE_CACHE_CONFIG, MAPLIBRE_MAX_TILE_CACHE_HARD_CAP, } from "../domain/models/mapConfig";
|
|
140
|
+
import { CIRCLE_RENDER_ORDERS, circleRing, cloneCircleRecord, MAPVX_BRAND_COLOR, resolveCircleConfig, } from "../domain/models/circle";
|
|
142
141
|
import { MarkerAttribute } from "../domain/models/marker";
|
|
143
142
|
import { MVXRoute } from "../domain/models/route";
|
|
144
143
|
import { InternalDrawRouteConfiguration, InternalGetRouteConfiguration, } from "../domain/models/routeConfiguration";
|
|
145
144
|
import { Repository } from "../repository/repository";
|
|
145
|
+
import { hexToRgb, isPlacementVisibleOnFloor, mergeGlbScale, mergeRotation3D, opacityForZoom, resolveModels3DLights, resolveZoomTransparency, } from "../utils/3d";
|
|
146
|
+
import { addScene3DLights, computeGlbBottomAnchor, loadGlbRoot } from "../utils/loadGlb";
|
|
146
147
|
import { extractStepCoordinates } from "../utils/route-utils";
|
|
147
148
|
import { getBoundingBox } from "../utils/utils";
|
|
148
149
|
import { buildInteractionOptions, shouldDisableTouchRotation } from "./mapInteractionOptions";
|
|
@@ -161,7 +162,7 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
161
162
|
* @returns A new instance of MapVXMap.
|
|
162
163
|
*/
|
|
163
164
|
constructor(mapConfig, container, token) {
|
|
164
|
-
var _a, _b, _c;
|
|
165
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
165
166
|
super();
|
|
166
167
|
this.potentialParentPlaces = [];
|
|
167
168
|
this.innerFloors = [];
|
|
@@ -176,18 +177,17 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
176
177
|
this.geoLocation = navigator.geolocation;
|
|
177
178
|
// 3d related variables
|
|
178
179
|
this.mode = "2D";
|
|
180
|
+
this.scene3DConfig = undefined;
|
|
179
181
|
this.deckOverlay = undefined;
|
|
180
|
-
this.
|
|
181
|
-
|
|
182
|
-
this.
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
/**
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.ESCALATOR_LIGHTS = 3;
|
|
190
|
-
this.SPRITE_URL = "https://lazarillo.app/internal/maps/vector-style/cenco-cl-pe-co-ar-3D/sprites_cencosud";
|
|
182
|
+
this.scene3DGlbScene = undefined;
|
|
183
|
+
/** Loaded GLB roots keyed by URL (deduplicated). */
|
|
184
|
+
this.scene3DGlbRootByUrl = new globalThis.Map();
|
|
185
|
+
/** Per-asset template root and bottom anchor for cloning. */
|
|
186
|
+
this.scene3DGlbTemplateById = new globalThis.Map();
|
|
187
|
+
/** Number of light objects in `scene3DGlbScene` (kept when clearing meshes). */
|
|
188
|
+
this.scene3DGlbLightCount = 0;
|
|
189
|
+
/** Container group holding all placed GLB pivots; rebuilt on each floor change. */
|
|
190
|
+
this.scene3DModelsGroup = undefined;
|
|
191
191
|
this.spriteIconMapping = {};
|
|
192
192
|
this.spriteAtlasImage = new Image();
|
|
193
193
|
if (rtlLanguages.includes((_a = mapConfig.lang) !== null && _a !== void 0 ? _a : "")) {
|
|
@@ -201,15 +201,16 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
201
201
|
this.watchPositionID = undefined;
|
|
202
202
|
this.onFloorChange = mapConfig.onFloorChange;
|
|
203
203
|
this.onParentPlaceChange = mapConfig.onParentPlaceChange;
|
|
204
|
-
this.mode = (_c = mapConfig.mode) !== null && _c !== void 0 ? _c : "2D";
|
|
205
|
-
this.initialCenter = mapConfig.center;
|
|
206
204
|
this.tileCacheConfig = (() => {
|
|
207
205
|
const merged = Object.assign(Object.assign({}, DEFAULT_TILE_CACHE_CONFIG), mapConfig.tileCache);
|
|
208
206
|
merged.maxTiles = Math.min(merged.maxTiles, MAPLIBRE_MAX_TILE_CACHE_HARD_CAP);
|
|
209
207
|
return merged;
|
|
210
208
|
})();
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
this.mode = (_c = mapConfig.mode) !== null && _c !== void 0 ? _c : "2D";
|
|
210
|
+
this.scene3DConfig = mapConfig.scene3D;
|
|
211
|
+
this.initialCenter = mapConfig.center;
|
|
212
|
+
if (this.is3DSceneActive() && ((_f = (_e = (_d = this.scene3DConfig) === null || _d === void 0 ? void 0 : _d.customLayers) === null || _e === void 0 ? void 0 : _e.iconLayers) === null || _f === void 0 ? void 0 : _f.spriteUrl)) {
|
|
213
|
+
this.loadSpriteAtlas((_j = (_h = (_g = this.scene3DConfig) === null || _g === void 0 ? void 0 : _g.customLayers) === null || _h === void 0 ? void 0 : _h.iconLayers) === null || _j === void 0 ? void 0 : _j.spriteUrl).catch(console.error);
|
|
213
214
|
}
|
|
214
215
|
if (mapConfig.parentPlaceId != null) {
|
|
215
216
|
this.initialPlaceDetailSetUp(mapConfig.parentPlaceId, mapConfig.authToken);
|
|
@@ -337,35 +338,22 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
337
338
|
showZoom: mapConfig.showZoom !== undefined ? mapConfig.showZoom : true,
|
|
338
339
|
}), (_e = mapConfig.navigationPosition) !== null && _e !== void 0 ? _e : "top-right");
|
|
339
340
|
this.map.on("load", () => {
|
|
340
|
-
var _a;
|
|
341
|
-
if (this.
|
|
341
|
+
var _a, _b, _c;
|
|
342
|
+
if (this.is3DSceneActive()) {
|
|
342
343
|
this.deckOverlay = new MapboxOverlay({ layers: [] });
|
|
343
344
|
this.map.addControl(this.deckOverlay);
|
|
344
|
-
this.hideIndoorSymbolLayers();
|
|
345
345
|
// Hide MapLibre icon layers — replaced by deck.gl IconLayer
|
|
346
|
-
this.
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
346
|
+
this.hideLayers((_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.hideLayers);
|
|
347
|
+
const models = (_b = this.scene3DConfig) === null || _b === void 0 ? void 0 : _b.models;
|
|
348
|
+
const glbModelsActive = models !== undefined && models.enabled !== false && models.assets.length > 0;
|
|
349
|
+
if (glbModelsActive) {
|
|
350
|
+
this.map.addLayer(this.createGlbCustomLayer());
|
|
352
351
|
}
|
|
353
|
-
// Add 3D escalator layer and hide 2D transportation line
|
|
354
|
-
this.map.addLayer(this.createEscalatorLayer());
|
|
355
|
-
this.map.setPaintProperty("indoor-transportation", "line-opacity", 0);
|
|
356
|
-
// Capture escalator positions when new tiles arrive (stops once cached)
|
|
357
|
-
this.map.on("sourcedata", (e) => {
|
|
358
|
-
if (e.sourceId === "indoorequal" &&
|
|
359
|
-
this.currentFloor &&
|
|
360
|
-
!this.escalatorCache[this.currentFloor]) {
|
|
361
|
-
this.placeEscalators();
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
352
|
}
|
|
365
353
|
this.whenStyleUpdates(style);
|
|
366
354
|
if (mapConfig.lang)
|
|
367
355
|
this.setLayersForLanguage(mapConfig.lang);
|
|
368
|
-
(
|
|
356
|
+
(_c = mapConfig.onMapReady) === null || _c === void 0 ? void 0 : _c.call(mapConfig);
|
|
369
357
|
this.onHover();
|
|
370
358
|
this.subscribeToFailedTiles();
|
|
371
359
|
});
|
|
@@ -375,6 +363,11 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
375
363
|
if (this.circles.length > 0)
|
|
376
364
|
this.ensureCircleLayers();
|
|
377
365
|
});
|
|
366
|
+
this.map.on("zoom", () => {
|
|
367
|
+
if (this.is3DSceneActive()) {
|
|
368
|
+
this.applyModelZoomOpacity();
|
|
369
|
+
}
|
|
370
|
+
});
|
|
378
371
|
this.map.on("zoomend", () => {
|
|
379
372
|
var _a;
|
|
380
373
|
(_a = mapConfig.onZoomEnd) === null || _a === void 0 ? void 0 : _a.call(mapConfig, this.getZoomLevel());
|
|
@@ -512,48 +505,43 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
512
505
|
// Tile cache clear may fail if cache doesn't exist
|
|
513
506
|
}
|
|
514
507
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
// Hide text-only layers (replaced by deck.gl)
|
|
524
|
-
if (hasText && !hasIcon) {
|
|
525
|
-
this.map.setLayoutProperty(layer.id, "visibility", "none");
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
508
|
+
/**
|
|
509
|
+
* Whether 3D scene features (deck.gl overlay, declarative GLB custom layer, etc.) are active.
|
|
510
|
+
* Requires {@link MapConfig.mode} `"3D"` and {@link Scene3DConfig.enabled} not `false`.
|
|
511
|
+
* When `scene3D` is omitted, 3D features remain available for backward compatibility.
|
|
512
|
+
*/
|
|
513
|
+
is3DSceneActive() {
|
|
514
|
+
var _a;
|
|
515
|
+
return this.mode === "3D" && ((_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.enabled) !== false;
|
|
529
516
|
}
|
|
530
|
-
|
|
517
|
+
// Start 3D related methods ------------------------------------------------------------
|
|
518
|
+
createGlbCustomLayer() {
|
|
519
|
+
var _a;
|
|
531
520
|
const refMercator = MercatorCoordinate.fromLngLat(this.initialCenter, 0);
|
|
532
521
|
const meterScale = refMercator.meterInMercatorCoordinateUnits();
|
|
533
522
|
const modelTransform = new THREE.Matrix4()
|
|
534
523
|
.makeTranslation(refMercator.x, refMercator.y, refMercator.z)
|
|
535
524
|
.scale(new THREE.Vector3(meterScale, -meterScale, meterScale))
|
|
536
525
|
.multiply(new THREE.Matrix4().makeRotationX(Math.PI / 2));
|
|
537
|
-
this.
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
this.placeEscalators();
|
|
526
|
+
this.scene3DGlbScene = new THREE.Scene();
|
|
527
|
+
const models = (_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.models;
|
|
528
|
+
if (models && models.enabled !== false && models.assets.length > 0) {
|
|
529
|
+
const lights = resolveModels3DLights(models);
|
|
530
|
+
this.scene3DGlbLightCount = addScene3DLights(this.scene3DGlbScene, lights);
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
this.scene3DGlbLightCount = 0;
|
|
534
|
+
}
|
|
535
|
+
void this.loadScene3DGlbTemplates()
|
|
536
|
+
.then(() => this.placeScene3DModels())
|
|
537
|
+
.catch((err) => {
|
|
538
|
+
console.error("Failed to initialize declarative GLB models", err);
|
|
551
539
|
});
|
|
552
540
|
let renderer = undefined;
|
|
553
541
|
let camera = undefined;
|
|
554
542
|
const tmpMatrix = new THREE.Matrix4();
|
|
555
543
|
return {
|
|
556
|
-
id: "3d-
|
|
544
|
+
id: "3d-glb-models",
|
|
557
545
|
type: "custom",
|
|
558
546
|
renderingMode: "3d",
|
|
559
547
|
onAdd(_map, gl) {
|
|
@@ -564,162 +552,206 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
564
552
|
antialias: true,
|
|
565
553
|
});
|
|
566
554
|
renderer.autoClear = false;
|
|
555
|
+
// MapLibre owns canvas dimensions; only sync the GL viewport on resize.
|
|
556
|
+
renderer.setSize = function (width, height) {
|
|
557
|
+
this.setViewport(0, 0, width, height);
|
|
558
|
+
};
|
|
567
559
|
},
|
|
568
|
-
render: (
|
|
569
|
-
var _a
|
|
560
|
+
render: (_gl, args) => {
|
|
561
|
+
var _a;
|
|
570
562
|
if (!camera ||
|
|
571
563
|
!renderer ||
|
|
572
|
-
!this.
|
|
573
|
-
!this.
|
|
574
|
-
this.
|
|
564
|
+
!this.scene3DGlbScene ||
|
|
565
|
+
!this.scene3DModelsGroup ||
|
|
566
|
+
this.scene3DModelsGroup.children.length === 0) {
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
const canvas = this.map.getCanvas();
|
|
570
|
+
const width = canvas.width;
|
|
571
|
+
const height = canvas.height;
|
|
572
|
+
// Skip while the framebuffer has no drawable area (e.g. devtools opening).
|
|
573
|
+
if (width === 0 || height === 0) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const mainMatrix = (_a = args.defaultProjectionData) === null || _a === void 0 ? void 0 : _a.mainMatrix;
|
|
577
|
+
if (!mainMatrix) {
|
|
575
578
|
return;
|
|
576
|
-
|
|
577
|
-
|
|
579
|
+
}
|
|
580
|
+
renderer.setSize(width, height);
|
|
581
|
+
tmpMatrix.fromArray(mainMatrix).multiply(modelTransform);
|
|
578
582
|
camera.projectionMatrix.copy(tmpMatrix);
|
|
579
583
|
renderer.resetState();
|
|
580
|
-
renderer.render(this.
|
|
584
|
+
renderer.render(this.scene3DGlbScene, camera);
|
|
581
585
|
},
|
|
582
586
|
};
|
|
583
587
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
!this.escalatorCenter)
|
|
589
|
-
return;
|
|
590
|
-
// Try to capture positions if not cached yet
|
|
591
|
-
this.captureEscalatorPositions();
|
|
592
|
-
const positions = this.escalatorCache[this.currentFloor];
|
|
593
|
-
if (!positions)
|
|
588
|
+
async loadScene3DGlbTemplates() {
|
|
589
|
+
var _a;
|
|
590
|
+
const models = (_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.models;
|
|
591
|
+
if (!models || models.enabled === false || models.assets.length === 0) {
|
|
594
592
|
return;
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
593
|
+
}
|
|
594
|
+
this.scene3DGlbRootByUrl.clear();
|
|
595
|
+
this.scene3DGlbTemplateById.clear();
|
|
596
|
+
for (const asset of models.assets) {
|
|
597
|
+
try {
|
|
598
|
+
let root = this.scene3DGlbRootByUrl.get(asset.url);
|
|
599
|
+
if (!root) {
|
|
600
|
+
root = await loadGlbRoot(asset.url);
|
|
601
|
+
this.scene3DGlbRootByUrl.set(asset.url, root);
|
|
602
|
+
}
|
|
603
|
+
const center = computeGlbBottomAnchor(root);
|
|
604
|
+
this.scene3DGlbTemplateById.set(asset.id, { root, center });
|
|
605
|
+
}
|
|
606
|
+
catch (err) {
|
|
607
|
+
console.error(`Failed to load GLB asset "${asset.id}" from ${asset.url}`, err);
|
|
600
608
|
}
|
|
601
609
|
}
|
|
610
|
+
}
|
|
611
|
+
placeScene3DModels() {
|
|
612
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
613
|
+
if (!this.scene3DGlbScene) {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
const models = (_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.models;
|
|
617
|
+
if (!models || models.enabled === false) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (this.scene3DModelsGroup) {
|
|
621
|
+
this.scene3DGlbScene.remove(this.scene3DModelsGroup);
|
|
622
|
+
this.scene3DModelsGroup = undefined;
|
|
623
|
+
}
|
|
624
|
+
if (this.scene3DGlbTemplateById.size === 0) {
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
602
627
|
// Guard against an invalid initial center before it reaches fromLngLat.
|
|
603
628
|
if (!this.initialCenter ||
|
|
604
629
|
!Number.isFinite(this.initialCenter.lng) ||
|
|
605
|
-
!Number.isFinite(this.initialCenter.lat))
|
|
630
|
+
!Number.isFinite(this.initialCenter.lat)) {
|
|
606
631
|
return;
|
|
632
|
+
}
|
|
607
633
|
const refMercator = MercatorCoordinate.fromLngLat(this.initialCenter, 0);
|
|
608
634
|
const meterScale = refMercator.meterInMercatorCoordinateUnits();
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
635
|
+
const floorKey = (_b = this.currentFloor) !== null && _b !== void 0 ? _b : "";
|
|
636
|
+
const modelsGroup = new THREE.Group();
|
|
637
|
+
modelsGroup.position.set((_d = (_c = models.globalOffset) === null || _c === void 0 ? void 0 : _c.x) !== null && _d !== void 0 ? _d : 0, (_f = (_e = models.globalOffset) === null || _e === void 0 ? void 0 : _e.y) !== null && _f !== void 0 ? _f : 0, (_h = (_g = models.globalOffset) === null || _g === void 0 ? void 0 : _g.z) !== null && _h !== void 0 ? _h : 0);
|
|
638
|
+
for (const placement of models.placements) {
|
|
639
|
+
if (!isPlacementVisibleOnFloor(placement, floorKey)) {
|
|
612
640
|
continue;
|
|
613
|
-
|
|
641
|
+
}
|
|
642
|
+
const template = this.scene3DGlbTemplateById.get(placement.assetId);
|
|
643
|
+
if (!template) {
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
const asset = models.assets.find((a) => a.id === placement.assetId);
|
|
647
|
+
if (!asset) {
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
// Placement positions come from external consumer config: skip any
|
|
651
|
+
// non-finite coordinate so a malformed config can never crash
|
|
652
|
+
// fromLngLat and break the whole floor render.
|
|
653
|
+
if (!placement.position ||
|
|
654
|
+
!Number.isFinite(placement.position.lng) ||
|
|
655
|
+
!Number.isFinite(placement.position.lat)) {
|
|
656
|
+
this.logWarning(new Error(`Invalid scene3D placement position (assetId=${placement.assetId}, floorKey=${floorKey})`));
|
|
657
|
+
continue;
|
|
658
|
+
}
|
|
659
|
+
const target = maplibregl.MercatorCoordinate.fromLngLat([placement.position.lng, placement.position.lat], (_j = placement.position.altitude) !== null && _j !== void 0 ? _j : 0);
|
|
614
660
|
const sx = (target.x - refMercator.x) / meterScale;
|
|
615
661
|
const sz = (target.y - refMercator.y) / meterScale;
|
|
662
|
+
const ax = (_l = (_k = asset.defaultModelOffset) === null || _k === void 0 ? void 0 : _k.x) !== null && _l !== void 0 ? _l : 0;
|
|
663
|
+
const ay = (_o = (_m = asset.defaultModelOffset) === null || _m === void 0 ? void 0 : _m.y) !== null && _o !== void 0 ? _o : 0;
|
|
664
|
+
const az = (_q = (_p = asset.defaultModelOffset) === null || _p === void 0 ? void 0 : _p.z) !== null && _q !== void 0 ? _q : 0;
|
|
665
|
+
const px = (_s = (_r = placement.offset) === null || _r === void 0 ? void 0 : _r.x) !== null && _s !== void 0 ? _s : 0;
|
|
666
|
+
const py = (_u = (_t = placement.offset) === null || _t === void 0 ? void 0 : _t.y) !== null && _u !== void 0 ? _u : 0;
|
|
667
|
+
const pz = (_w = (_v = placement.offset) === null || _v === void 0 ? void 0 : _v.z) !== null && _w !== void 0 ? _w : 0;
|
|
616
668
|
const pivot = new THREE.Group();
|
|
617
|
-
pivot.position.set(sx,
|
|
618
|
-
|
|
619
|
-
pivot.
|
|
620
|
-
const
|
|
621
|
-
|
|
669
|
+
pivot.position.set(sx + ax + px, ay + py, sz + az + pz);
|
|
670
|
+
const mergedRot = mergeRotation3D(asset.defaultRotation, placement.rotation);
|
|
671
|
+
pivot.rotation.set(THREE.MathUtils.degToRad(mergedRot.pitch), THREE.MathUtils.degToRad(-mergedRot.yaw), THREE.MathUtils.degToRad(mergedRot.roll), "YXZ");
|
|
672
|
+
const [sx3, sy3, sz3] = mergeGlbScale(asset.defaultScale, placement.scale);
|
|
673
|
+
pivot.scale.set(sx3, sy3, sz3);
|
|
674
|
+
const model = template.root.clone(true);
|
|
675
|
+
// `clone(true)` shares materials between instances; clone them per placement so each
|
|
676
|
+
// placement's zoom-based opacity is independent and does not bleed into sibling models.
|
|
677
|
+
model.traverse((obj) => {
|
|
678
|
+
const mesh = obj;
|
|
679
|
+
if (!mesh.isMesh) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
mesh.material = Array.isArray(mesh.material)
|
|
683
|
+
? mesh.material.map((m) => m.clone())
|
|
684
|
+
: mesh.material.clone();
|
|
685
|
+
});
|
|
686
|
+
model.position.set(-template.center.x, -template.center.y, -template.center.z);
|
|
687
|
+
// Stash the resolved zoom-transparency config so it can be re-applied on every zoom change.
|
|
688
|
+
pivot.userData.zoomTransparency = resolveZoomTransparency(models, asset, placement);
|
|
622
689
|
pivot.add(model);
|
|
623
|
-
|
|
690
|
+
modelsGroup.add(pivot);
|
|
624
691
|
}
|
|
692
|
+
this.scene3DModelsGroup = modelsGroup;
|
|
693
|
+
this.scene3DGlbScene.add(modelsGroup);
|
|
694
|
+
this.applyModelZoomOpacity();
|
|
625
695
|
this.map.triggerRepaint();
|
|
626
696
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
.filter((f) => { var _a; return ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.floor_key) === this.currentFloor; });
|
|
636
|
-
if (!features.length)
|
|
697
|
+
/**
|
|
698
|
+
* Applies zoom-based transparency to placed GLB models, using each placement's resolved
|
|
699
|
+
* {@link ZoomTransparencyConfig} stored in `pivot.userData.zoomTransparency`. Hard threshold:
|
|
700
|
+
* fully opaque below the configured zoom, configured opacity at/above it. Only triggers a
|
|
701
|
+
* repaint when at least one material actually changed.
|
|
702
|
+
*/
|
|
703
|
+
applyModelZoomOpacity() {
|
|
704
|
+
if (!this.scene3DModelsGroup) {
|
|
637
705
|
return;
|
|
638
|
-
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
// feature (a MultiLineString is just one escalator line split across
|
|
649
|
-
// tiles, not several escalators).
|
|
650
|
-
let lineParts;
|
|
651
|
-
if (geom.type === "LineString") {
|
|
652
|
-
lineParts = [geom.coordinates];
|
|
653
|
-
}
|
|
654
|
-
else if (geom.type === "MultiLineString") {
|
|
655
|
-
lineParts = geom.coordinates;
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
const coords = lineParts.flat();
|
|
661
|
-
if (coords.length < 2)
|
|
662
|
-
continue;
|
|
663
|
-
const start = coords[0];
|
|
664
|
-
const end = coords[coords.length - 1];
|
|
665
|
-
const midLng = (start[0] + end[0]) / 2;
|
|
666
|
-
const midLat = (start[1] + end[1]) / 2;
|
|
667
|
-
const bearing = Math.atan2(end[0] - start[0], end[1] - start[1]);
|
|
668
|
-
// Skip any non-finite result so a bad feature can never poison the
|
|
669
|
-
// cache (and later crash MercatorCoordinate.fromLngLat).
|
|
670
|
-
if (!Number.isFinite(midLng) || !Number.isFinite(midLat) || !Number.isFinite(bearing))
|
|
671
|
-
continue;
|
|
672
|
-
allMids.push({ lng: midLng, lat: midLat, bearing });
|
|
673
|
-
}
|
|
674
|
-
// Merge points within ~15m of each other into one
|
|
675
|
-
const MERGE_DEG = 0.00015; // ~15m
|
|
676
|
-
const positions = [];
|
|
677
|
-
const used = new Set();
|
|
678
|
-
for (let i = 0; i < allMids.length; i++) {
|
|
679
|
-
if (used.has(i))
|
|
680
|
-
continue;
|
|
681
|
-
used.add(i);
|
|
682
|
-
const group = [allMids[i]];
|
|
683
|
-
for (let j = i + 1; j < allMids.length; j++) {
|
|
684
|
-
if (used.has(j))
|
|
685
|
-
continue;
|
|
686
|
-
const dLng = allMids[i].lng - allMids[j].lng;
|
|
687
|
-
const dLat = allMids[i].lat - allMids[j].lat;
|
|
688
|
-
if (Math.abs(dLng) < MERGE_DEG && Math.abs(dLat) < MERGE_DEG) {
|
|
689
|
-
used.add(j);
|
|
690
|
-
group.push(allMids[j]);
|
|
706
|
+
}
|
|
707
|
+
const zoom = this.getZoomLevel();
|
|
708
|
+
let changed = false;
|
|
709
|
+
for (const pivot of this.scene3DModelsGroup.children) {
|
|
710
|
+
const cfg = pivot.userData.zoomTransparency;
|
|
711
|
+
const opacity = opacityForZoom(cfg, zoom);
|
|
712
|
+
pivot.traverse((obj) => {
|
|
713
|
+
const mesh = obj;
|
|
714
|
+
if (!mesh.isMesh) {
|
|
715
|
+
return;
|
|
691
716
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
717
|
+
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
|
|
718
|
+
for (const material of materials) {
|
|
719
|
+
if (material.opacity !== opacity) {
|
|
720
|
+
material.transparent = opacity < 1;
|
|
721
|
+
material.opacity = opacity;
|
|
722
|
+
// Disable depth writes while transparent to avoid draw-order artifacts.
|
|
723
|
+
material.depthWrite = opacity >= 1;
|
|
724
|
+
changed = true;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
});
|
|
697
728
|
}
|
|
698
|
-
if (
|
|
699
|
-
this.
|
|
729
|
+
if (changed) {
|
|
730
|
+
this.map.triggerRepaint();
|
|
700
731
|
}
|
|
701
732
|
}
|
|
702
|
-
async loadSpriteAtlas() {
|
|
733
|
+
async loadSpriteAtlas(spriteUrl) {
|
|
703
734
|
const [json, img] = await Promise.all([
|
|
704
|
-
fetch(`${
|
|
735
|
+
fetch(`${spriteUrl}.json`).then((r) => r.json()),
|
|
705
736
|
new Promise((resolve, reject) => {
|
|
706
737
|
const image = new Image();
|
|
707
738
|
image.crossOrigin = "anonymous";
|
|
708
739
|
image.onload = () => resolve(image);
|
|
709
740
|
image.onerror = reject;
|
|
710
|
-
image.src = `${
|
|
741
|
+
image.src = `${spriteUrl}.png`;
|
|
711
742
|
}),
|
|
712
743
|
]);
|
|
713
744
|
this.spriteIconMapping = json;
|
|
714
745
|
this.spriteAtlasImage = img;
|
|
715
746
|
}
|
|
716
|
-
|
|
747
|
+
makeElevatedLinesLayer(floorKey, layerConfig) {
|
|
748
|
+
var _a;
|
|
717
749
|
return new MVTLayer({
|
|
718
750
|
id: "indoor-lines-elevated",
|
|
719
|
-
data:
|
|
720
|
-
binary: false,
|
|
751
|
+
data: layerConfig.dataUrl,
|
|
752
|
+
binary: (_a = layerConfig.binaryData) !== null && _a !== void 0 ? _a : false,
|
|
721
753
|
renderSubLayers: (props) => {
|
|
722
|
-
var _a;
|
|
754
|
+
var _a, _b, _c, _d, _e;
|
|
723
755
|
const roomData = (props.data || []);
|
|
724
756
|
const roomFeatures = roomData.filter((f) => {
|
|
725
757
|
var _a, _b, _c;
|
|
@@ -731,7 +763,9 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
731
763
|
return null;
|
|
732
764
|
const paths = [];
|
|
733
765
|
for (const f of roomFeatures) {
|
|
734
|
-
const z = ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height)
|
|
766
|
+
const z = ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height)
|
|
767
|
+
? Number(f.properties.height)
|
|
768
|
+
: ((_b = layerConfig.defaultHeight) !== null && _b !== void 0 ? _b : 5);
|
|
735
769
|
const geom = f.geometry;
|
|
736
770
|
const polygons = geom.type === "Polygon"
|
|
737
771
|
? [geom.coordinates]
|
|
@@ -744,21 +778,23 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
744
778
|
}
|
|
745
779
|
}
|
|
746
780
|
}
|
|
747
|
-
return new PathLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-paths`, data: paths, getPath: (d) => d.path, getColor:
|
|
781
|
+
return new PathLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-paths`, data: paths, getPath: (d) => d.path, getColor: hexToRgb((_c = layerConfig.lineColor) !== null && _c !== void 0 ? _c : "#cbcbcb"), getWidth: (_d = layerConfig.lineWidth) !== null && _d !== void 0 ? _d : 1.5, widthUnits: (_e = layerConfig.widthUnits) !== null && _e !== void 0 ? _e : "pixels", pickable: false }));
|
|
748
782
|
},
|
|
749
783
|
updateTriggers: {
|
|
750
784
|
renderSubLayers: [floorKey],
|
|
751
785
|
},
|
|
752
786
|
});
|
|
753
787
|
}
|
|
754
|
-
makeLabelLayer(floorKey, useSdf = true) {
|
|
788
|
+
makeLabelLayer(floorKey, layerConfig, useSdf = true) {
|
|
789
|
+
var _a, _b, _c;
|
|
755
790
|
return new MVTLayer({
|
|
756
791
|
id: "indoor-labels",
|
|
757
|
-
data:
|
|
758
|
-
binary: false,
|
|
759
|
-
minZoom: 19.5,
|
|
760
|
-
maxZoom: 24,
|
|
792
|
+
data: layerConfig.dataUrl,
|
|
793
|
+
binary: (_a = layerConfig.binaryData) !== null && _a !== void 0 ? _a : false,
|
|
794
|
+
minZoom: (_b = layerConfig.minZoom) !== null && _b !== void 0 ? _b : 19.5,
|
|
795
|
+
maxZoom: (_c = layerConfig.maxZoom) !== null && _c !== void 0 ? _c : 24,
|
|
761
796
|
renderSubLayers: (props) => {
|
|
797
|
+
var _a, _b, _c, _d, _e;
|
|
762
798
|
// Use area_name and poi Point features — unique per tile, no duplicates
|
|
763
799
|
// If logo-{name} image exists in sprite, icon has priority over text label
|
|
764
800
|
const labelData = (props.data || []);
|
|
@@ -780,32 +816,34 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
780
816
|
if (!labelFeatures.length)
|
|
781
817
|
return null;
|
|
782
818
|
const textData = labelFeatures.map((f) => {
|
|
783
|
-
var _a, _b, _c;
|
|
819
|
+
var _a, _b, _c, _d;
|
|
784
820
|
return ({
|
|
785
821
|
position: [
|
|
786
822
|
...f.geometry.coordinates.slice(0, 2),
|
|
787
|
-
((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height) ? Number(f.properties.height) : 5,
|
|
823
|
+
((_a = f.properties) === null || _a === void 0 ? void 0 : _a.height) ? Number(f.properties.height) : ((_b = layerConfig.defaultHeight) !== null && _b !== void 0 ? _b : 5),
|
|
788
824
|
],
|
|
789
|
-
text: ((
|
|
825
|
+
text: ((_c = f.properties) === null || _c === void 0 ? void 0 : _c["name:latin"]) || ((_d = f.properties) === null || _d === void 0 ? void 0 : _d.name) || "",
|
|
790
826
|
});
|
|
791
827
|
});
|
|
792
|
-
return new TextLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-labels`, data: textData, getPosition: (d) => d.position, getText: (d) => d.text, getSize: 16, getColor:
|
|
828
|
+
return new TextLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-labels`, data: textData, getPosition: (d) => d.position, getText: (d) => d.text, getSize: (_a = layerConfig.size) !== null && _a !== void 0 ? _a : 16, getColor: hexToRgb((_b = layerConfig.color) !== null && _b !== void 0 ? _b : "#91969b"), outlineColor: useSdf ? [255, 255, 255, 255] : [0, 0, 0, 0], outlineWidth: useSdf ? 4 : 0, fontSettings: { sdf: useSdf }, fontFamily: (_c = layerConfig.fontFamily) !== null && _c !== void 0 ? _c : "Open Sans, sans-serif", fontWeight: (_d = layerConfig.fontWeight) !== null && _d !== void 0 ? _d : 600, billboard: true, pickable: false, characterSet: "auto", wordBreak: "break-word", maxWidth: (_e = layerConfig.maxWidth) !== null && _e !== void 0 ? _e : 150 }));
|
|
793
829
|
},
|
|
794
830
|
updateTriggers: {
|
|
795
831
|
renderSubLayers: [floorKey],
|
|
796
832
|
},
|
|
797
833
|
});
|
|
798
834
|
}
|
|
799
|
-
makePoiIconLayer(floorKey) {
|
|
835
|
+
makePoiIconLayer(floorKey, layerConfig) {
|
|
836
|
+
var _a, _b, _c;
|
|
800
837
|
if (!this.spriteIconMapping || !this.spriteAtlasImage)
|
|
801
838
|
return null;
|
|
802
839
|
return new MVTLayer({
|
|
803
840
|
id: "indoor-poi-icons",
|
|
804
|
-
data:
|
|
805
|
-
binary: false,
|
|
806
|
-
minZoom: 17,
|
|
807
|
-
maxZoom: 24,
|
|
841
|
+
data: layerConfig.dataUrl,
|
|
842
|
+
binary: (_a = layerConfig.binaryData) !== null && _a !== void 0 ? _a : false,
|
|
843
|
+
minZoom: (_b = layerConfig.minZoom) !== null && _b !== void 0 ? _b : 17,
|
|
844
|
+
maxZoom: (_c = layerConfig.maxZoom) !== null && _c !== void 0 ? _c : 24,
|
|
808
845
|
renderSubLayers: (props) => {
|
|
846
|
+
var _a, _b, _c, _d;
|
|
809
847
|
const poiData = (props.data || []);
|
|
810
848
|
const poiFeatures = poiData.filter((f) => {
|
|
811
849
|
var _a, _b, _c;
|
|
@@ -819,7 +857,7 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
819
857
|
if (!poiFeatures.length)
|
|
820
858
|
return null;
|
|
821
859
|
const iconData = poiFeatures.map((f) => {
|
|
822
|
-
var _a, _b, _c;
|
|
860
|
+
var _a, _b, _c, _d;
|
|
823
861
|
const tags = ((_a = f.properties) === null || _a === void 0 ? void 0 : _a.tags) || "";
|
|
824
862
|
let icon;
|
|
825
863
|
if (tags.includes("wheelchair"))
|
|
@@ -831,28 +869,30 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
831
869
|
return {
|
|
832
870
|
position: [
|
|
833
871
|
...f.geometry.coordinates.slice(0, 2),
|
|
834
|
-
((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : 5,
|
|
872
|
+
((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : ((_d = layerConfig.defaultHeight) !== null && _d !== void 0 ? _d : 5),
|
|
835
873
|
],
|
|
836
874
|
icon,
|
|
837
875
|
};
|
|
838
876
|
});
|
|
839
|
-
return new IconLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-poi-icons`, data: iconData, iconAtlas: this.spriteAtlasImage, iconMapping: this.spriteIconMapping, getIcon: (d) => d.icon, getPosition: (d) => d.position, getSize: 2, sizeUnits: "meters", sizeScale: 1, billboard: true, pickable: false }));
|
|
877
|
+
return new IconLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-poi-icons`, data: iconData, iconAtlas: this.spriteAtlasImage, iconMapping: this.spriteIconMapping, getIcon: (d) => d.icon, getPosition: (d) => d.position, getSize: (_a = layerConfig.size) !== null && _a !== void 0 ? _a : 2, sizeUnits: (_b = layerConfig.sizeUnits) !== null && _b !== void 0 ? _b : "meters", sizeScale: (_c = layerConfig.sizeScale) !== null && _c !== void 0 ? _c : 1, billboard: (_d = layerConfig.billboard) !== null && _d !== void 0 ? _d : true, pickable: false }));
|
|
840
878
|
},
|
|
841
879
|
updateTriggers: {
|
|
842
880
|
renderSubLayers: [floorKey],
|
|
843
881
|
},
|
|
844
882
|
});
|
|
845
883
|
}
|
|
846
|
-
makeStoreLogoLayer(floorKey) {
|
|
884
|
+
makeStoreLogoLayer(floorKey, layerConfig) {
|
|
885
|
+
var _a, _b, _c;
|
|
847
886
|
if (!this.spriteIconMapping || !this.spriteAtlasImage)
|
|
848
887
|
return null;
|
|
849
888
|
return new MVTLayer({
|
|
850
889
|
id: "indoor-store-logos",
|
|
851
|
-
data:
|
|
852
|
-
binary: false,
|
|
853
|
-
minZoom: 13,
|
|
854
|
-
maxZoom: 24,
|
|
890
|
+
data: layerConfig.dataUrl,
|
|
891
|
+
binary: (_a = layerConfig.binaryData) !== null && _a !== void 0 ? _a : false,
|
|
892
|
+
minZoom: (_b = layerConfig.minZoom) !== null && _b !== void 0 ? _b : 13,
|
|
893
|
+
maxZoom: (_c = layerConfig.maxZoom) !== null && _c !== void 0 ? _c : 24,
|
|
855
894
|
renderSubLayers: (props) => {
|
|
895
|
+
var _a, _b, _c;
|
|
856
896
|
const propsData = (props.data || []);
|
|
857
897
|
const logoFeatures = propsData.filter((f) => {
|
|
858
898
|
var _a, _b, _c;
|
|
@@ -868,30 +908,22 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
868
908
|
if (!logoFeatures.length)
|
|
869
909
|
return null;
|
|
870
910
|
const logoData = logoFeatures.map((f) => {
|
|
871
|
-
var _a, _b, _c;
|
|
911
|
+
var _a, _b, _c, _d;
|
|
872
912
|
const name = (_a = f.properties) === null || _a === void 0 ? void 0 : _a.name;
|
|
873
913
|
const icon = "logo-" + name;
|
|
874
914
|
const rotation = ((_b = f.properties) === null || _b === void 0 ? void 0 : _b.rotation_icon) ? Number(f.properties.rotation_icon) : 0;
|
|
875
915
|
return {
|
|
876
916
|
position: [
|
|
877
917
|
...f.geometry.coordinates.slice(0, 2),
|
|
878
|
-
((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : 5,
|
|
918
|
+
((_c = f.properties) === null || _c === void 0 ? void 0 : _c.height) ? Number(f.properties.height) : ((_d = layerConfig.defaultHeight) !== null && _d !== void 0 ? _d : 5),
|
|
879
919
|
],
|
|
880
920
|
icon,
|
|
881
921
|
rotation,
|
|
882
922
|
};
|
|
883
923
|
});
|
|
884
924
|
return new IconLayer(Object.assign(Object.assign({}, props), { id: `${props.id}-store-logos`, data: logoData, iconAtlas: this.spriteAtlasImage, iconMapping: this.spriteIconMapping, getIcon: (d) => d.icon, getPosition: (d) => d.position, getAngle: (d) => -d.rotation, getSize: (d) => {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
"logo-Ripley": 2,
|
|
888
|
-
"logo-Falabella": 2,
|
|
889
|
-
"logo-CasaIdeas": 2,
|
|
890
|
-
"logo-Sky Costanera": 0.6,
|
|
891
|
-
"logo-Easy": 1.4,
|
|
892
|
-
"logo-Jumbo": 2,
|
|
893
|
-
"logo-Decathlon": 1.4,
|
|
894
|
-
};
|
|
925
|
+
var _a;
|
|
926
|
+
const LOGO_SCALE = (_a = layerConfig.logoScale) !== null && _a !== void 0 ? _a : {};
|
|
895
927
|
const m = this.spriteIconMapping[d.icon];
|
|
896
928
|
if (!m)
|
|
897
929
|
return 10;
|
|
@@ -900,7 +932,7 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
900
932
|
const h = m.height / pr;
|
|
901
933
|
const base = 10 * (h / Math.max(w, h));
|
|
902
934
|
return base * (LOGO_SCALE[d.icon] || 1);
|
|
903
|
-
}, sizeUnits: "meters", sizeScale: 1, billboard: false, pickable: false }));
|
|
935
|
+
}, sizeUnits: (_a = layerConfig.sizeUnits) !== null && _a !== void 0 ? _a : "meters", sizeScale: (_b = layerConfig.sizeScale) !== null && _b !== void 0 ? _b : 1, billboard: (_c = layerConfig.billboard) !== null && _c !== void 0 ? _c : false, pickable: false }));
|
|
904
936
|
},
|
|
905
937
|
updateTriggers: {
|
|
906
938
|
renderSubLayers: [floorKey],
|
|
@@ -908,20 +940,40 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
908
940
|
});
|
|
909
941
|
}
|
|
910
942
|
updateDeckOverlay() {
|
|
943
|
+
var _a;
|
|
911
944
|
if (!this.deckOverlay || !this.currentFloor)
|
|
912
945
|
return;
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
];
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
946
|
+
if (!((_a = this.scene3DConfig) === null || _a === void 0 ? void 0 : _a.customLayers))
|
|
947
|
+
return;
|
|
948
|
+
const { customLayers } = this.scene3DConfig;
|
|
949
|
+
const layers = [];
|
|
950
|
+
if (customLayers.elevatedLinesLayer) {
|
|
951
|
+
layers.push(this.makeElevatedLinesLayer(this.currentFloor, customLayers.elevatedLinesLayer));
|
|
952
|
+
}
|
|
953
|
+
if (customLayers.labelsLayer) {
|
|
954
|
+
layers.push(this.makeLabelLayer(this.currentFloor, customLayers.labelsLayer, false));
|
|
955
|
+
}
|
|
956
|
+
if (customLayers.iconLayers) {
|
|
957
|
+
const { storeLogosLayer, poiIconsLayer } = customLayers.iconLayers;
|
|
958
|
+
if (storeLogosLayer) {
|
|
959
|
+
layers.push(this.makeStoreLogoLayer(this.currentFloor, storeLogosLayer));
|
|
960
|
+
}
|
|
961
|
+
if (poiIconsLayer) {
|
|
962
|
+
layers.push(this.makePoiIconLayer(this.currentFloor, poiIconsLayer));
|
|
963
|
+
}
|
|
964
|
+
}
|
|
923
965
|
this.deckOverlay.setProps({ layers });
|
|
924
966
|
}
|
|
967
|
+
hideLayers(layersIds) {
|
|
968
|
+
if (!layersIds)
|
|
969
|
+
return;
|
|
970
|
+
for (const layerId of layersIds) {
|
|
971
|
+
const layer = this.map.getLayer(layerId);
|
|
972
|
+
if (!layer)
|
|
973
|
+
continue;
|
|
974
|
+
this.map.setLayoutProperty(layer.id, "visibility", "none");
|
|
975
|
+
}
|
|
976
|
+
}
|
|
925
977
|
// End 3D related methods ------------------------------------------------------------
|
|
926
978
|
getCurrentFloor() {
|
|
927
979
|
var _a;
|
|
@@ -942,9 +994,9 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
942
994
|
if (place) {
|
|
943
995
|
this.subPlacesLoad(place.mapvxId);
|
|
944
996
|
}
|
|
945
|
-
if (this.
|
|
997
|
+
if (this.is3DSceneActive()) {
|
|
946
998
|
this.updateDeckOverlay();
|
|
947
|
-
this.
|
|
999
|
+
this.placeScene3DModels();
|
|
948
1000
|
}
|
|
949
1001
|
if (updateStyle) {
|
|
950
1002
|
this.repository
|
|
@@ -974,9 +1026,9 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
974
1026
|
this.innerFloors = (_a = place === null || place === void 0 ? void 0 : place.innerFloors.sort((a, b) => a.index - b.index)) !== null && _a !== void 0 ? _a : [];
|
|
975
1027
|
this.currentFloor =
|
|
976
1028
|
(_e = (_c = floorId !== null && floorId !== void 0 ? floorId : (_b = this.innerFloors.find((floor) => floor.defaultFloor)) === null || _b === void 0 ? void 0 : _b.key) !== null && _c !== void 0 ? _c : (_d = this.innerFloors[0]) === null || _d === void 0 ? void 0 : _d.key) !== null && _e !== void 0 ? _e : "";
|
|
977
|
-
if (this.
|
|
1029
|
+
if (this.is3DSceneActive()) {
|
|
978
1030
|
this.updateDeckOverlay();
|
|
979
|
-
this.
|
|
1031
|
+
this.placeScene3DModels();
|
|
980
1032
|
}
|
|
981
1033
|
}
|
|
982
1034
|
updateParentPlaceAndFloor(parentPlaceId, floorId, options) {
|
|
@@ -1030,7 +1082,7 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
1030
1082
|
this.routeController.addSourcesAndLayers();
|
|
1031
1083
|
this.refreshCircles();
|
|
1032
1084
|
this.filterByFloorKey(this.currentFloor);
|
|
1033
|
-
if (this.
|
|
1085
|
+
if (this.is3DSceneActive()) {
|
|
1034
1086
|
this.updateDeckOverlay();
|
|
1035
1087
|
}
|
|
1036
1088
|
}
|
|
@@ -1462,9 +1514,10 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
1462
1514
|
this.logEvent("invalidFloorKey", { floorKey: floorKeyString });
|
|
1463
1515
|
}
|
|
1464
1516
|
// Critical base-map updates run first and must never be blocked by an
|
|
1465
|
-
// optional 3D decoration failing. A throw in
|
|
1466
|
-
// this method before updateFiltersTo, leaving the base polygons
|
|
1467
|
-
// (showing the wrong floor) while the caller's empty catch hid
|
|
1517
|
+
// optional 3D decoration failing. A throw in placeScene3DModels used to
|
|
1518
|
+
// abort this method before updateFiltersTo, leaving the base polygons
|
|
1519
|
+
// unfiltered (showing the wrong floor) while the caller's empty catch hid
|
|
1520
|
+
// the error.
|
|
1468
1521
|
this.updateFiltersTo(floorKeyString);
|
|
1469
1522
|
this.updateMarkersTo(floorKeyString);
|
|
1470
1523
|
this.refreshCircles();
|
|
@@ -1472,10 +1525,10 @@ export class InternalMapVXMap extends Loggeable {
|
|
|
1472
1525
|
this.routeController.updateRouteMarkerVisibility(floorKeyString);
|
|
1473
1526
|
// 3D decorations are best-effort: isolate so any failure here can never
|
|
1474
1527
|
// break base-map rendering.
|
|
1475
|
-
if (this.
|
|
1528
|
+
if (this.is3DSceneActive()) {
|
|
1476
1529
|
try {
|
|
1477
1530
|
this.updateDeckOverlay();
|
|
1478
|
-
this.
|
|
1531
|
+
this.placeScene3DModels();
|
|
1479
1532
|
}
|
|
1480
1533
|
catch (error) {
|
|
1481
1534
|
this.logError(error, "filterByFloorKey: 3D layer update failed");
|