@mapless/core 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/index.js +360 -43
  2. package/dist/types/Mapless/Base.d.ts +5 -0
  3. package/dist/types/Mapless/Base.d.ts.map +1 -1
  4. package/dist/types/Mapless/icons/icons.d.ts +1 -0
  5. package/dist/types/Mapless/icons/icons.d.ts.map +1 -1
  6. package/dist/types/Mapless/mana-3d/airspace.d.ts +1 -0
  7. package/dist/types/Mapless/mana-3d/airspace.d.ts.map +1 -1
  8. package/dist/types/Mapless/mana-3d/elevatedLine.d.ts.map +1 -1
  9. package/dist/types/Mapless/mana-3d/mapModel.d.ts +5 -0
  10. package/dist/types/Mapless/mana-3d/mapModel.d.ts.map +1 -1
  11. package/dist/types/Mapless/mana-three/basicObject.d.ts +4 -0
  12. package/dist/types/Mapless/mana-three/basicObject.d.ts.map +1 -1
  13. package/dist/types/Mapless/mana-three/curve3d.d.ts +4 -0
  14. package/dist/types/Mapless/mana-three/curve3d.d.ts.map +1 -1
  15. package/dist/types/Mapless/mana-three/index.d.ts +1 -1
  16. package/dist/types/Mapless/mana-three/index.d.ts.map +1 -1
  17. package/dist/types/Mapless/mana-three/instancedModel.d.ts +32 -1
  18. package/dist/types/Mapless/mana-three/instancedModel.d.ts.map +1 -1
  19. package/dist/types/Mapless/mana-three/line2Manager.d.ts +8 -0
  20. package/dist/types/Mapless/mana-three/line2Manager.d.ts.map +1 -1
  21. package/dist/types/Mapless/mana-three/model.d.ts +5 -0
  22. package/dist/types/Mapless/mana-three/model.d.ts.map +1 -1
  23. package/dist/types/Mapless/mana-three/three.d.ts +9 -0
  24. package/dist/types/Mapless/mana-three/three.d.ts.map +1 -1
  25. package/dist/types/Three/MapThree.d.ts +5 -0
  26. package/dist/types/Three/MapThree.d.ts.map +1 -1
  27. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,7 +4,8 @@ import { AmbientLight, AnimationMixer, BoxGeometry, BoxHelper, BufferGeometry, C
4
4
  import gcoord from "gcoord";
5
5
  import mapbox_gl_draw from "@mapbox/mapbox-gl-draw";
6
6
  import "@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css";
7
- import { DRACOLoader, GLTFLoader, Line2, LineGeometry, LineMaterial } from "three-stdlib";
7
+ import { mergeGeometries } from "three/examples/jsm/utils/BufferGeometryUtils.js";
8
+ import { GLTFLoader, Line2, LineGeometry, LineMaterial } from "three-stdlib";
8
9
  class MapThree {
9
10
  mapless = void 0;
10
11
  scene = null;
@@ -470,6 +471,13 @@ class MapThree {
470
471
  this.camera = null;
471
472
  this.isInitialized = false;
472
473
  }
474
+ onStyleChanged() {
475
+ if (!this.mapless?.map || !this.isInitialized) return;
476
+ if (this.customLayerId) try {
477
+ this.mapless.map.removeLayer(this.customLayerId);
478
+ } catch {}
479
+ this.setupCustomLayer();
480
+ }
473
481
  }
474
482
  const STATUS_COLORS = {
475
483
  Idle: {
@@ -969,6 +977,7 @@ const center_namespaceObject = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI
969
977
  const fly_namespaceObject = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFGODkyQTNFNkJFRDExRUZCQzQzOTRDMjJCMTlEMDU3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFGODkyQTNGNkJFRDExRUZCQzQzOTRDMjJCMTlEMDU3Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUY4OTJBM0M2QkVEMTFFRkJDNDM5NEMyMkIxOUQwNTciIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUY4OTJBM0Q2QkVEMTFFRkJDNDM5NEMyMkIxOUQwNTciLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6Kn+fFAAAJmElEQVR42uxd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";
970
978
  const car_namespaceObject = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFFQjNCNEQ4NkJFRDExRUY5RDFCQzVGRTFERTM5QURDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFFQjNCNEQ5NkJFRDExRUY5RDFCQzVGRTFERTM5QURDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUVCM0I0RDY2QkVEMTFFRjlEMUJDNUZFMURFMzlBREMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUVCM0I0RDc2QkVEMTFFRjlEMUJDNUZFMURFMzlBREMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4N8EJcAAAKr0lEQVR42uxd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";
971
979
  const controller_namespaceObject = "data:image/png;base64,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";
980
+ const drone_namespaceObject = "data:image/png;base64,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";
972
981
  const flight_namespaceObject = "data:image/png;base64,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";
973
982
  const ship_namespaceObject = "data:image/png;base64,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";
974
983
  const circle_namespaceObject = "data:image/png;base64,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";
@@ -1004,6 +1013,7 @@ const icons = {
1004
1013
  dzCar: car_namespaceObject,
1005
1014
  dzFlight: flight_namespaceObject,
1006
1015
  dzShip: ship_namespaceObject,
1016
+ dzDrone: drone_namespaceObject,
1007
1017
  locating: locating_namespaceObject,
1008
1018
  monaloading: mona_loading_default_namespaceObject,
1009
1019
  react: react_namespaceObject,
@@ -11360,6 +11370,17 @@ class Mapless extends Base {
11360
11370
  pitch: 0
11361
11371
  });
11362
11372
  }
11373
+ setCoordSystem(coordSystem) {
11374
+ if (!this.CoordTrans) return;
11375
+ const prevSystem = this.CoordSystem || 'wgs84';
11376
+ if (prevSystem === coordSystem) return;
11377
+ this.CoordTrans = createCoordTransformer({
11378
+ dataSystem: coordSystem,
11379
+ tileSystem: this.CoordTrans.TileSystem
11380
+ });
11381
+ this.emitterless.emit('coordSystemChange', coordSystem, prevSystem);
11382
+ console.log(`CoordSystem changed: ${prevSystem} -> ${coordSystem}`);
11383
+ }
11363
11384
  fitBounds(coordinates, padding = 20) {
11364
11385
  if (!this.map || !coordinates.length) return;
11365
11386
  const bounds = coordinates.reduce((bounds, coord)=>bounds.extend(coord), new mapbox_gl.LngLatBounds(coordinates[0], coordinates[0]));
@@ -16593,6 +16614,7 @@ class AirspaceManager extends manager_Manager {
16593
16614
  defaultFillOpacity: 0.3
16594
16615
  };
16595
16616
  originalProperties = {};
16617
+ originalGeometries = {};
16596
16618
  constructor(mapless, options){
16597
16619
  super(mapless, options, 'airspace');
16598
16620
  this.onInitialized();
@@ -16606,7 +16628,19 @@ class AirspaceManager extends manager_Manager {
16606
16628
  handleCoordSystemChange(_system) {
16607
16629
  if (this.zones) Object.keys(this.zones).forEach((id)=>{
16608
16630
  const zone = this.zones[id];
16609
- this.drawZone(id, zone);
16631
+ const originalGeometry = this.originalGeometries[id];
16632
+ if (originalGeometry) this.drawZone(id, {
16633
+ name: zone.name,
16634
+ geometry: originalGeometry,
16635
+ minAltitude: zone.minAltitude,
16636
+ maxAltitude: zone.maxAltitude,
16637
+ color: zone.color,
16638
+ edgeColor: zone.edgeColor,
16639
+ edgeOpacity: zone.edgeOpacity,
16640
+ edgeWidth: zone.edgeWidth,
16641
+ fillColor: zone.fillColor,
16642
+ fillOpacity: zone.fillOpacity
16643
+ });
16610
16644
  });
16611
16645
  }
16612
16646
  createIdHub(_idHub) {
@@ -16686,11 +16720,16 @@ class AirspaceManager extends manager_Manager {
16686
16720
  }
16687
16721
  drawZone(id, options) {
16688
16722
  const { name = '', geometry, minAltitude = this.config.defaultMinAltitude, maxAltitude = this.config.defaultMaxAltitude, color = this.config.defaultColor, edgeColor = this.config.defaultEdgeColor, edgeOpacity = this.config.defaultEdgeOpacity, edgeWidth = this.config.defaultEdgeWidth, fillColor = this.config.defaultFillColor, fillOpacity = this.config.defaultFillOpacity } = options;
16723
+ this.originalGeometries[id] = geometry;
16724
+ const transformedGeometry = geometry.map((polygon)=>polygon.map((coord)=>this.mapless?.coordTrans('dataToTile', [
16725
+ coord[0],
16726
+ coord[1]
16727
+ ])));
16689
16728
  const feature = {
16690
16729
  type: 'Feature',
16691
16730
  geometry: {
16692
16731
  type: 'Polygon',
16693
- coordinates: geometry
16732
+ coordinates: transformedGeometry
16694
16733
  },
16695
16734
  properties: {
16696
16735
  id,
@@ -16708,7 +16747,7 @@ class AirspaceManager extends manager_Manager {
16708
16747
  this.zones[id] = {
16709
16748
  id,
16710
16749
  name,
16711
- geometry,
16750
+ geometry: transformedGeometry,
16712
16751
  minAltitude,
16713
16752
  maxAltitude,
16714
16753
  color,
@@ -16757,11 +16796,13 @@ class AirspaceManager extends manager_Manager {
16757
16796
  if (!this.zones[id]) return;
16758
16797
  delete this.zones[id];
16759
16798
  delete this.originalProperties[id];
16799
+ delete this.originalGeometries[id];
16760
16800
  this.updateSource();
16761
16801
  }
16762
16802
  clearZones() {
16763
16803
  this.zones = {};
16764
16804
  this.originalProperties = {};
16805
+ this.originalGeometries = {};
16765
16806
  this.mapless?.setEmptyData(this.idHub?.sourceId);
16766
16807
  }
16767
16808
  updateZone(id, options) {
@@ -16817,7 +16858,8 @@ class AirspaceManager extends manager_Manager {
16817
16858
  });
16818
16859
  });
16819
16860
  if (coordinates.length > 0 && this.mapless?.map) {
16820
- const bounds = coordinates.reduce((bounds, coord)=>bounds.extend(coord), new mapbox_gl.LngLatBounds(coordinates[0], coordinates[0]));
16861
+ const originalCoordinates = coordinates.map((coord)=>this.mapless?.coordTrans('tileToData', coord));
16862
+ const bounds = originalCoordinates.reduce((bounds, coord)=>bounds.extend(coord), new mapbox_gl.LngLatBounds(originalCoordinates[0], originalCoordinates[0]));
16821
16863
  const currentPitch = this.mapless.map.getPitch();
16822
16864
  const currentBearing = this.mapless.map.getBearing();
16823
16865
  this.mapless.map.fitBounds(bounds, {
@@ -16846,6 +16888,7 @@ class AirspaceManager extends manager_Manager {
16846
16888
  super.destroy();
16847
16889
  this.zones = {};
16848
16890
  this.originalProperties = {};
16891
+ this.originalGeometries = {};
16849
16892
  }
16850
16893
  }
16851
16894
  const attachAirspace = (mapless, name)=>mapless?.use(AirspaceManager, name);
@@ -17006,6 +17049,7 @@ class MapModelManager extends EmitManager {
17006
17049
  0
17007
17050
  ];
17008
17051
  themeColorModels = new Set();
17052
+ modelOptions = new Map();
17009
17053
  constructor(mapless, options){
17010
17054
  super(mapless, options, 'mapModel');
17011
17055
  this.map = mapless.map;
@@ -17016,6 +17060,14 @@ class MapModelManager extends EmitManager {
17016
17060
  this.onInitialized();
17017
17061
  this.setupGlobalClickHandler();
17018
17062
  }
17063
+ handleCoordSystemChange(_system) {
17064
+ if (this.modelOptions.size > 0) {
17065
+ this.clearModels();
17066
+ this.modelOptions.forEach((options)=>{
17067
+ this.addModel(options);
17068
+ });
17069
+ }
17070
+ }
17019
17071
  setupGlobalClickHandler() {
17020
17072
  if (!this.map) return;
17021
17073
  this.globalClickHandler = (e)=>{
@@ -17098,12 +17150,17 @@ class MapModelManager extends EmitManager {
17098
17150
  if (!this.map) throw new Error('Map not initialized');
17099
17151
  const sourceId = this.generateSourceId();
17100
17152
  const layerId = this.generateLayerId();
17153
+ const originalPosition = config.position || config.lngLat || [
17154
+ 0,
17155
+ 0
17156
+ ];
17157
+ const transformedPosition = this.mapless?.coordTrans('dataToTile', originalPosition);
17101
17158
  const sourceConfig = {
17102
17159
  type: 'model',
17103
17160
  models: {
17104
17161
  [modelId]: {
17105
17162
  uri: config.uri,
17106
- position: config.position || config.lngLat,
17163
+ position: transformedPosition,
17107
17164
  altitude: config.altitude || 0
17108
17165
  }
17109
17166
  }
@@ -17248,6 +17305,7 @@ class MapModelManager extends EmitManager {
17248
17305
  materialOverrides,
17249
17306
  nodeOverrides
17250
17307
  });
17308
+ this.modelOptions.set(id, options);
17251
17309
  if (!materialOverrides || 0 === Object.keys(materialOverrides).length) {
17252
17310
  this.themeColorModels.add(id);
17253
17311
  const themeColor = this.getDefaultThemeColor();
@@ -17263,9 +17321,10 @@ class MapModelManager extends EmitManager {
17263
17321
  const modelData = this.models.get(id);
17264
17322
  if (!modelData) return;
17265
17323
  if (!this.map) return;
17324
+ const transformedPosition = this.mapless?.coordTrans('dataToTile', lngLat);
17266
17325
  const source = this.map.getSource(modelData.sourceId);
17267
17326
  if (source?.models?.[id]) {
17268
- source.models[id].position = lngLat;
17327
+ source.models[id].position = transformedPosition;
17269
17328
  source.models[id].altitude = altitude;
17270
17329
  }
17271
17330
  if (this.map.getLayer(modelData.layerId)) this.map.setPaintProperty(modelData.layerId, 'model-translation', [
@@ -17273,6 +17332,11 @@ class MapModelManager extends EmitManager {
17273
17332
  0,
17274
17333
  altitude
17275
17334
  ]);
17335
+ const options = this.modelOptions.get(id);
17336
+ if (options) {
17337
+ options.lngLat = lngLat;
17338
+ if (void 0 !== altitude) options.altitude = altitude;
17339
+ }
17276
17340
  }
17277
17341
  updateModelRotation(id, rotation) {
17278
17342
  const modelData = this.models.get(id);
@@ -17301,6 +17365,7 @@ class MapModelManager extends EmitManager {
17301
17365
  if (this.map.getLayer(modelData.layerId)) this.map.removeLayer(modelData.layerId);
17302
17366
  if (this.map.getSource(modelData.sourceId)) this.map.removeSource(modelData.sourceId);
17303
17367
  this.models.delete(id);
17368
+ this.modelOptions.delete(id);
17304
17369
  this.themeColorModels.delete(id);
17305
17370
  if (this.selectedModelId === id) this.selectedModelId = null;
17306
17371
  }
@@ -17395,6 +17460,7 @@ class MapModelManager extends EmitManager {
17395
17460
  if (this.map && this.globalClickHandler) this.map.off('click', this.globalClickHandler);
17396
17461
  this.selectedModelId = null;
17397
17462
  this.themeColorModels.clear();
17463
+ this.modelOptions.clear();
17398
17464
  this.clearModels();
17399
17465
  }
17400
17466
  }
@@ -17481,7 +17547,8 @@ class BasicThreeObjectManager extends manager_Manager {
17481
17547
  matrix: matrix.clone()
17482
17548
  });
17483
17549
  else {
17484
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
17550
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
17551
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
17485
17552
  const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * scale;
17486
17553
  mapThree.addRenderableObject(id, mesh, {
17487
17554
  translateX: modelAsMercator.x,
@@ -17498,7 +17565,13 @@ class BasicThreeObjectManager extends manager_Manager {
17498
17565
  type,
17499
17566
  mesh,
17500
17567
  geometry,
17501
- material
17568
+ material,
17569
+ originalOptions: {
17570
+ lngLat,
17571
+ altitude,
17572
+ rotation,
17573
+ scale
17574
+ }
17502
17575
  });
17503
17576
  console.log(`BasicThreeObject added: ${id}`, {
17504
17577
  type,
@@ -17518,7 +17591,8 @@ class BasicThreeObjectManager extends manager_Manager {
17518
17591
  if (!mapThree) return;
17519
17592
  const objData = this.objects.get(id);
17520
17593
  if (!objData) return void console.warn(`Object with id "${id}" not found`);
17521
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
17594
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
17595
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
17522
17596
  const renderableObj = mapThree.getRenderableObject(id);
17523
17597
  if (renderableObj) mapThree.updateRenderableObjectTransform(id, {
17524
17598
  ...renderableObj.transform,
@@ -17526,6 +17600,10 @@ class BasicThreeObjectManager extends manager_Manager {
17526
17600
  translateY: modelAsMercator.y,
17527
17601
  translateZ: modelAsMercator.z
17528
17602
  });
17603
+ if (objData.originalOptions) {
17604
+ objData.originalOptions.lngLat = lngLat;
17605
+ objData.originalOptions.altitude = altitude;
17606
+ }
17529
17607
  }
17530
17608
  updateObjectRotation(id, rotation) {
17531
17609
  const mapThree = this.getMapThree();
@@ -17559,7 +17637,8 @@ class BasicThreeObjectManager extends manager_Manager {
17559
17637
  if (!mapThree) return;
17560
17638
  const objData = this.objects.get(id);
17561
17639
  if (!objData) return void console.warn(`Object with id "${id}" not found`);
17562
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
17640
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
17641
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
17563
17642
  const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * scale;
17564
17643
  const renderableObj = mapThree.getRenderableObject(id);
17565
17644
  if (renderableObj) mapThree.updateRenderableObjectTransform(id, {
@@ -17630,6 +17709,27 @@ class BasicThreeObjectManager extends manager_Manager {
17630
17709
  getObjectIds() {
17631
17710
  return Array.from(this.objects.keys());
17632
17711
  }
17712
+ handleCoordSystemChange(_system) {
17713
+ const mapThree = this.getMapThree();
17714
+ if (!mapThree || 0 === this.objects.size) return;
17715
+ this.objects.forEach((objData, id)=>{
17716
+ if (!objData.originalOptions) return;
17717
+ const { lngLat, altitude, rotation, scale } = objData.originalOptions;
17718
+ mapThree.removeRenderableObject(id);
17719
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
17720
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
17721
+ const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * (scale || 1);
17722
+ mapThree.addRenderableObject(id, objData.mesh, {
17723
+ translateX: modelAsMercator.x,
17724
+ translateY: modelAsMercator.y,
17725
+ translateZ: modelAsMercator.z,
17726
+ rotateX: rotation?.[0] || 0,
17727
+ rotateY: rotation?.[1] || 0,
17728
+ rotateZ: rotation?.[2] || 0,
17729
+ scale: mercatorScale
17730
+ });
17731
+ });
17732
+ }
17633
17733
  destroy() {
17634
17734
  this.clearObjects();
17635
17735
  }
@@ -17679,10 +17779,11 @@ class Curve3DManager extends manager_Manager {
17679
17779
  }
17680
17780
  calculateTransform(points) {
17681
17781
  if (0 === points.length) throw new Error('Cannot calculate transform for empty points');
17682
- const firstPoint = mapbox_gl.MercatorCoordinate.fromLngLat([
17782
+ const transformedFirst = this.mapless?.coordTrans('dataToTile', [
17683
17783
  points[0].lng,
17684
17784
  points[0].lat
17685
- ], points[0].alt);
17785
+ ]);
17786
+ const firstPoint = mapbox_gl.MercatorCoordinate.fromLngLat(transformedFirst, points[0].alt);
17686
17787
  return {
17687
17788
  translateX: firstPoint.x,
17688
17789
  translateY: firstPoint.y,
@@ -17695,10 +17796,11 @@ class Curve3DManager extends manager_Manager {
17695
17796
  points.forEach((point, index)=>{
17696
17797
  if (0 === index) vector3Points.push(new Vector3(0, 0, 0));
17697
17798
  else {
17698
- const currentMercator = mapbox_gl.MercatorCoordinate.fromLngLat([
17799
+ const transformedPoint = this.mapless?.coordTrans('dataToTile', [
17699
17800
  point.lng,
17700
17801
  point.lat
17701
- ], point.alt);
17802
+ ]);
17803
+ const currentMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedPoint, point.alt);
17702
17804
  const dx = currentMercator.x - transform.translateX;
17703
17805
  const dy = currentMercator.y - transform.translateY;
17704
17806
  const dz = currentMercator.z - transform.translateZ;
@@ -17707,6 +17809,33 @@ class Curve3DManager extends manager_Manager {
17707
17809
  });
17708
17810
  return vector3Points;
17709
17811
  }
17812
+ handleCoordSystemChange(_system) {
17813
+ if (this.curves.size > 0 && this.getMapThree()) {
17814
+ const entries = Array.from(this.curves.entries());
17815
+ entries.forEach(([id, curveData])=>{
17816
+ const mapThree = this.getMapThree();
17817
+ if (mapThree) mapThree.removeRenderableObject(id);
17818
+ const transform = this.calculateTransform(curveData.originalPoints);
17819
+ const points = this.convertPoints(curveData.originalPoints, transform);
17820
+ const mesh = this.createMesh({
17821
+ ...curveData,
17822
+ points
17823
+ });
17824
+ if (mapThree) mapThree.addRenderableObject(id, mesh, {
17825
+ translateX: transform.translateX,
17826
+ translateY: transform.translateY,
17827
+ translateZ: transform.translateZ,
17828
+ scale: transform.scale
17829
+ });
17830
+ this.curves.set(id, {
17831
+ ...curveData,
17832
+ points,
17833
+ transform,
17834
+ mesh
17835
+ });
17836
+ });
17837
+ }
17838
+ }
17710
17839
  addCurve(id, config) {
17711
17840
  const mapThree = this.getMapThree();
17712
17841
  if (!mapThree) throw new Error('Three scene not initialized. Call useThree first.');
@@ -17726,7 +17855,8 @@ class Curve3DManager extends manager_Manager {
17726
17855
  points,
17727
17856
  mesh: null,
17728
17857
  transform,
17729
- config: curveConfig
17858
+ config: curveConfig,
17859
+ originalPoints: config.points
17730
17860
  };
17731
17861
  if (points.length >= 2) {
17732
17862
  const mesh = this.createMesh(curveData);
@@ -17759,6 +17889,7 @@ class Curve3DManager extends manager_Manager {
17759
17889
  mapThree.removeRenderableObject(id);
17760
17890
  curveData.transform = this.calculateTransform(config.points);
17761
17891
  curveData.points = this.convertPoints(config.points, curveData.transform);
17892
+ curveData.originalPoints = config.points;
17762
17893
  const mesh = this.createMesh(curveData);
17763
17894
  curveData.mesh = mesh;
17764
17895
  mapThree.addRenderableObject(id, mesh, {
@@ -17816,10 +17947,13 @@ class InstancedModelManager extends manager_Manager {
17816
17947
  customLayerId;
17817
17948
  isInitialized = false;
17818
17949
  instancedMeshes = new Map();
17950
+ instanceDataMap = new Map();
17819
17951
  rotationAngles = new Map();
17820
17952
  autoRotateEnabled = new Map();
17821
17953
  rotationSpeeds = new Map();
17822
- renderCount = 0;
17954
+ clickCallback = null;
17955
+ lastProjectionMatrix = null;
17956
+ originalConfigs = new Map();
17823
17957
  constructor(mapless){
17824
17958
  super(mapless);
17825
17959
  this.map = mapless.map;
@@ -17863,16 +17997,13 @@ class InstancedModelManager extends manager_Manager {
17863
17997
  renderingMode: '3d',
17864
17998
  onAdd: ()=>{
17865
17999
  console.log('InstancedModelManager: Custom layer added');
18000
+ this.setupClickHandler();
17866
18001
  },
17867
18002
  render: (_gl, matrix)=>{
17868
18003
  if (!this.camera || !this.renderer || !this.scene) return;
17869
- this.renderCount++;
17870
- if (this.renderCount % 60 === 0) console.log('InstancedModelManager: Rendering', {
17871
- frame: this.renderCount,
17872
- instanceCount: this.instancedMeshes.size
17873
- });
17874
18004
  this.updateAutoRotate();
17875
18005
  this.camera.projectionMatrix = new Matrix4().fromArray(matrix);
18006
+ this.lastProjectionMatrix = this.camera.projectionMatrix.clone();
17876
18007
  _gl.enable(_gl.DEPTH_TEST);
17877
18008
  this.renderer.resetState();
17878
18009
  this.renderer.render(this.scene, this.camera);
@@ -17881,6 +18012,57 @@ class InstancedModelManager extends manager_Manager {
17881
18012
  };
17882
18013
  this.map.addLayer(customLayer);
17883
18014
  }
18015
+ setupClickHandler() {
18016
+ if (!this.map) return;
18017
+ const canvas = this.map.getCanvas();
18018
+ const handleClick = (e)=>{
18019
+ if (!this.camera || !this.scene || !this.renderer || !this.lastProjectionMatrix) return;
18020
+ const rect = canvas.getBoundingClientRect();
18021
+ const ndcX = (e.clientX - rect.left) / rect.width * 2 - 1;
18022
+ const ndcY = 2 * -((e.clientY - rect.top) / rect.height) + 1;
18023
+ const meshes = Array.from(this.instancedMeshes.entries());
18024
+ let closestHit = null;
18025
+ let minDistance = 1 / 0;
18026
+ for (const [groupId, instancedMesh] of meshes){
18027
+ const inverseProj = this.lastProjectionMatrix.clone().invert();
18028
+ const nearPoint = new Vector4(ndcX, ndcY, -1, 1).applyMatrix4(inverseProj);
18029
+ nearPoint.divideScalar(nearPoint.w);
18030
+ const farPoint = new Vector4(ndcX, ndcY, 1, 1).applyMatrix4(inverseProj);
18031
+ farPoint.divideScalar(farPoint.w);
18032
+ const origin = new Vector3(0, 0, 0);
18033
+ const direction = new Vector3(farPoint.x - nearPoint.x, farPoint.y - nearPoint.y, farPoint.z - nearPoint.z).normalize();
18034
+ const raycaster = new Raycaster(origin, direction);
18035
+ const intersects = raycaster.intersectObject(instancedMesh, false);
18036
+ if (intersects.length > 0 && intersects[0].distance < minDistance) {
18037
+ const intersection = intersects[0];
18038
+ const instanceId = intersection.instanceId;
18039
+ if (void 0 !== instanceId) {
18040
+ minDistance = intersection.distance;
18041
+ closestHit = {
18042
+ groupId,
18043
+ instanceIndex: instanceId,
18044
+ point: intersection.point,
18045
+ distance: intersection.distance
18046
+ };
18047
+ }
18048
+ }
18049
+ }
18050
+ if (closestHit && this.clickCallback) {
18051
+ const instanceData = this.instanceDataMap.get(closestHit.groupId)?.[closestHit.instanceIndex];
18052
+ if (instanceData) this.clickCallback({
18053
+ id: closestHit.groupId,
18054
+ instanceIndex: closestHit.instanceIndex,
18055
+ point: closestHit.point,
18056
+ lngLat: instanceData.lngLat,
18057
+ altitude: instanceData.altitude
18058
+ });
18059
+ }
18060
+ };
18061
+ canvas.addEventListener('click', handleClick);
18062
+ }
18063
+ onClick(callback) {
18064
+ this.clickCallback = callback;
18065
+ }
17884
18066
  updateAutoRotate() {
17885
18067
  this.autoRotateEnabled.forEach((enabled, id)=>{
17886
18068
  if (!enabled) return;
@@ -17906,9 +18088,9 @@ class InstancedModelManager extends manager_Manager {
17906
18088
  for(let i = 0; i < config.count; i++){
17907
18089
  const lngOffset = (Math.random() - 0.5) * config.spread * 2;
17908
18090
  const latOffset = (Math.random() - 0.5) * config.spread * 2;
17909
- const altitude = 100 * Math.random() + 50;
18091
+ const altitude = 500 * Math.random();
17910
18092
  const rotation = Math.random() * Math.PI * 2;
17911
- const scaleVariation = 0.8 + 0.4 * Math.random();
18093
+ const scaleVariation = 1 + 2 * Math.random();
17912
18094
  instances.push({
17913
18095
  lngLat: [
17914
18096
  config.center[0] + lngOffset,
@@ -17921,25 +18103,55 @@ class InstancedModelManager extends manager_Manager {
17921
18103
  }
17922
18104
  return instances;
17923
18105
  }
18106
+ handleCoordSystemChange(_system) {
18107
+ if (!this.scene || !this.map || 0 === this.originalConfigs.size) return;
18108
+ this.originalConfigs.forEach((config, id)=>{
18109
+ this.remove(id);
18110
+ this.load(id, config).catch((error)=>{
18111
+ console.error(`Failed to reload instanced model "${id}" after coord system change:`, error);
18112
+ });
18113
+ });
18114
+ }
17924
18115
  async load(id, config) {
17925
18116
  this.initThree();
17926
18117
  if (!this.scene || !this.map) throw new Error('Three.js scene not initialized');
17927
18118
  this.remove(id);
17928
- const dracoLoader = new DRACOLoader();
17929
- dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
17930
18119
  const loader = new GLTFLoader();
17931
- loader.setDRACOLoader(dracoLoader);
17932
18120
  try {
17933
18121
  console.log('InstancedModel: Loading model', config.url);
17934
18122
  const gltf = await new Promise((resolve, reject)=>{
17935
18123
  loader.load(config.url, resolve, void 0, reject);
17936
18124
  });
17937
18125
  const gltfScene = gltf.scene;
17938
- let meshToUse = null;
18126
+ const meshes = [];
17939
18127
  gltfScene.traverse((object)=>{
17940
- if (object instanceof Mesh && !meshToUse) meshToUse = object;
18128
+ if (object instanceof Mesh) meshes.push(object);
18129
+ });
18130
+ if (0 === meshes.length) throw new Error('No mesh found in model');
18131
+ console.log('InstancedModel: Found meshes', {
18132
+ count: meshes.length,
18133
+ details: meshes.map((m, i)=>({
18134
+ index: i,
18135
+ vertices: m.geometry.attributes.position?.count,
18136
+ hasMaterial: !!m.material,
18137
+ materialArray: Array.isArray(m.material)
18138
+ }))
17941
18139
  });
17942
- if (!meshToUse) throw new Error('No mesh found in model');
18140
+ let meshToUse;
18141
+ if (1 === meshes.length) meshToUse = meshes[0];
18142
+ else {
18143
+ const geometries = meshes.map((mesh)=>{
18144
+ const geometry = mesh.geometry.clone();
18145
+ geometry.applyMatrix4(mesh.matrixWorld);
18146
+ return geometry;
18147
+ });
18148
+ const geometry = mergeGeometries(geometries, false);
18149
+ if (geometry) meshToUse = new Mesh(geometry, meshes[0].material);
18150
+ else {
18151
+ console.warn('Failed to merge geometries, falling back to first mesh');
18152
+ meshToUse = meshes[0];
18153
+ }
18154
+ }
17943
18155
  const mesh = meshToUse;
17944
18156
  const materialToUse = Array.isArray(mesh.material) ? mesh.material[0] : mesh.material;
17945
18157
  const instancedMesh = new InstancedMesh(mesh.geometry.clone(), materialToUse.clone(), config.count);
@@ -17948,7 +18160,8 @@ class InstancedModelManager extends manager_Manager {
17948
18160
  if ('side' in instancedMesh.material) instancedMesh.material.side = DoubleSide;
17949
18161
  const instances = this.generateInstances(config);
17950
18162
  const angles = new Float32Array(config.count);
17951
- const meterInMercator = mapbox_gl.MercatorCoordinate.fromLngLat(config.center, 0).meterInMercatorCoordinateUnits();
18163
+ const transformedCenter = this.mapless?.coordTrans('dataToTile', config.center);
18164
+ const meterInMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedCenter, 0).meterInMercatorCoordinateUnits();
17952
18165
  console.log('InstancedModel: Creating instances', {
17953
18166
  instanceCount: config.count,
17954
18167
  center: config.center,
@@ -17959,7 +18172,8 @@ class InstancedModelManager extends manager_Manager {
17959
18172
  });
17960
18173
  const dummy = new Object3D();
17961
18174
  instances.forEach((instance, i)=>{
17962
- const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(instance.lngLat, instance.altitude);
18175
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', instance.lngLat);
18176
+ const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, instance.altitude);
17963
18177
  dummy.position.set(mercator.x, mercator.y, mercator.z);
17964
18178
  dummy.rotation.set(0, 0, instance.rotation);
17965
18179
  const scale = meterInMercator * config.scale * instance.scale;
@@ -17971,9 +18185,11 @@ class InstancedModelManager extends manager_Manager {
17971
18185
  instancedMesh.instanceMatrix.needsUpdate = true;
17972
18186
  this.scene.add(instancedMesh);
17973
18187
  this.instancedMeshes.set(id, instancedMesh);
18188
+ this.instanceDataMap.set(id, instances);
17974
18189
  this.rotationAngles.set(id, angles);
17975
18190
  this.autoRotateEnabled.set(id, config.autoRotate || false);
17976
18191
  this.rotationSpeeds.set(id, config.rotationSpeed || 0.01);
18192
+ this.originalConfigs.set(id, config);
17977
18193
  console.log(`InstancedModel "${id}" loaded with ${config.count} instances`);
17978
18194
  } catch (error) {
17979
18195
  console.error(`Failed to load instanced model "${id}":`, error);
@@ -17990,7 +18206,8 @@ class InstancedModelManager extends manager_Manager {
17990
18206
  updateInstance(id, index, lngLat, altitude) {
17991
18207
  const instancedMesh = this.instancedMeshes.get(id);
17992
18208
  if (!instancedMesh) return;
17993
- const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
18209
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
18210
+ const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
17994
18211
  const dummy = new Object3D();
17995
18212
  instancedMesh.getMatrixAt(index, dummy.matrix);
17996
18213
  dummy.matrix.decompose(dummy.position, dummy.quaternion, dummy.scale);
@@ -17998,6 +18215,11 @@ class InstancedModelManager extends manager_Manager {
17998
18215
  dummy.updateMatrix();
17999
18216
  instancedMesh.setMatrixAt(index, dummy.matrix);
18000
18217
  instancedMesh.instanceMatrix.needsUpdate = true;
18218
+ const instances = this.instanceDataMap.get(id);
18219
+ if (instances && instances[index]) {
18220
+ instances[index].lngLat = lngLat;
18221
+ instances[index].altitude = altitude;
18222
+ }
18001
18223
  }
18002
18224
  setInstanceVisible(id, visible) {
18003
18225
  const instancedMesh = this.instancedMeshes.get(id);
@@ -18019,13 +18241,14 @@ class InstancedModelManager extends manager_Manager {
18019
18241
  remove(id) {
18020
18242
  const instancedMesh = this.instancedMeshes.get(id);
18021
18243
  if (!instancedMesh) return;
18022
- if (this.scene) this.scene.remove(instancedMesh);
18244
+ this.scene?.remove(instancedMesh);
18023
18245
  instancedMesh.geometry.dispose();
18024
18246
  if (Array.isArray(instancedMesh.material)) instancedMesh.material.forEach((m)=>{
18025
18247
  m.dispose();
18026
18248
  });
18027
18249
  else instancedMesh.material.dispose();
18028
18250
  this.instancedMeshes.delete(id);
18251
+ this.instanceDataMap.delete(id);
18029
18252
  this.rotationAngles.delete(id);
18030
18253
  this.autoRotateEnabled.delete(id);
18031
18254
  this.rotationSpeeds.delete(id);
@@ -18057,6 +18280,7 @@ class InstancedModelManager extends manager_Manager {
18057
18280
  this.scene = null;
18058
18281
  this.camera = null;
18059
18282
  this.isInitialized = false;
18283
+ this.originalConfigs.clear();
18060
18284
  }
18061
18285
  }
18062
18286
  const instancedModel = InstancedModelManager;
@@ -18127,10 +18351,11 @@ class Line2Manager extends manager_Manager {
18127
18351
  }
18128
18352
  calculateTransform(points) {
18129
18353
  if (0 === points.length) throw new Error('Cannot calculate transform for empty points');
18130
- const firstPoint = mapbox_gl.MercatorCoordinate.fromLngLat([
18354
+ const transformedFirst = this.mapless?.coordTrans('dataToTile', [
18131
18355
  points[0].lng,
18132
18356
  points[0].lat
18133
- ], points[0].alt);
18357
+ ]);
18358
+ const firstPoint = mapbox_gl.MercatorCoordinate.fromLngLat(transformedFirst, points[0].alt);
18134
18359
  return {
18135
18360
  translateX: firstPoint.x,
18136
18361
  translateY: firstPoint.y,
@@ -18143,10 +18368,11 @@ class Line2Manager extends manager_Manager {
18143
18368
  points.forEach((point, index)=>{
18144
18369
  if (0 === index) positions.push(0, 0, 0);
18145
18370
  else {
18146
- const currentMercator = mapbox_gl.MercatorCoordinate.fromLngLat([
18371
+ const transformedPoint = this.mapless?.coordTrans('dataToTile', [
18147
18372
  point.lng,
18148
18373
  point.lat
18149
- ], point.alt);
18374
+ ]);
18375
+ const currentMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedPoint, point.alt);
18150
18376
  const dx = currentMercator.x - transform.translateX;
18151
18377
  const dy = currentMercator.y - transform.translateY;
18152
18378
  const dz = currentMercator.z - transform.translateZ;
@@ -18155,6 +18381,27 @@ class Line2Manager extends manager_Manager {
18155
18381
  });
18156
18382
  return positions;
18157
18383
  }
18384
+ handleCoordSystemChange(_system) {
18385
+ const mapThree = this.getMapThree();
18386
+ if (!mapThree || 0 === this.lines.size) return;
18387
+ this.lines.forEach((lineData, id)=>{
18388
+ mapThree.removeRenderableObject(id);
18389
+ lineData.transform = this.calculateTransform(lineData.points);
18390
+ const positions = this.convertPoints(lineData.points, lineData.transform);
18391
+ lineData.geometry.setPositions(positions);
18392
+ lineData.geometry.computeBoundingSphere();
18393
+ mapThree.addRenderableObject(id, lineData.line2, {
18394
+ translateX: lineData.transform.translateX,
18395
+ translateY: lineData.transform.translateY,
18396
+ translateZ: lineData.transform.translateZ,
18397
+ scale: lineData.transform.scale
18398
+ });
18399
+ });
18400
+ }
18401
+ onStyleChanged = (_tag)=>{
18402
+ const mapThree = this.getMapThree();
18403
+ mapThree?.onStyleChanged();
18404
+ };
18158
18405
  createMaterial(config) {
18159
18406
  const colorNumber = 'string' == typeof config.color ? new Color(config.color).getHex() : 'number' == typeof config.color ? config.color : new Color(config.color).getHex();
18160
18407
  const material = new LineMaterial({
@@ -18439,6 +18686,7 @@ class ModelManager extends manager_Manager {
18439
18686
  prefabs = new Map();
18440
18687
  mixers = new Map();
18441
18688
  clock = new Clock();
18689
+ modelConfigs = new Map();
18442
18690
  constructor(mapless){
18443
18691
  super(mapless);
18444
18692
  this.map = mapless.map;
@@ -18500,7 +18748,8 @@ class ModelManager extends manager_Manager {
18500
18748
  });
18501
18749
  this.prefabs.set(modelId, model);
18502
18750
  }
18503
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
18751
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
18752
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
18504
18753
  const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * scale;
18505
18754
  mapThree.addRenderableObject(modelId, model, {
18506
18755
  translateX: modelAsMercator.x,
@@ -18511,6 +18760,13 @@ class ModelManager extends manager_Manager {
18511
18760
  rotateZ: rotation[2],
18512
18761
  scale: mercatorScale
18513
18762
  });
18763
+ this.modelConfigs.set(modelId, {
18764
+ url,
18765
+ lngLat,
18766
+ altitude,
18767
+ rotation,
18768
+ scale
18769
+ });
18514
18770
  console.log('Model loaded:', {
18515
18771
  id: modelId,
18516
18772
  transform: {
@@ -18598,7 +18854,8 @@ class ModelManager extends manager_Manager {
18598
18854
  }
18599
18855
  });
18600
18856
  }
18601
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
18857
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
18858
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
18602
18859
  const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * scale;
18603
18860
  if (groupId) {
18604
18861
  const group = mapThree.getGroup(groupId);
@@ -18613,6 +18870,7 @@ class ModelManager extends manager_Manager {
18613
18870
  rotateZ: rotation[2],
18614
18871
  scale: mercatorScale
18615
18872
  });
18873
+ this.modelConfigs.set(id, config);
18616
18874
  console.log('Model added:', {
18617
18875
  id,
18618
18876
  transform: {
@@ -18630,7 +18888,8 @@ class ModelManager extends manager_Manager {
18630
18888
  updateModelPosition(id, lngLat, altitude = 0) {
18631
18889
  const mapThree = this.getMapThree();
18632
18890
  if (!mapThree) return;
18633
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
18891
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
18892
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
18634
18893
  const renderableObj = mapThree.getRenderableObject(id);
18635
18894
  if (renderableObj) mapThree.updateRenderableObjectTransform(id, {
18636
18895
  ...renderableObj.transform,
@@ -18638,6 +18897,11 @@ class ModelManager extends manager_Manager {
18638
18897
  translateY: modelAsMercator.y,
18639
18898
  translateZ: modelAsMercator.z
18640
18899
  });
18900
+ const config = this.modelConfigs.get(id);
18901
+ if (config) {
18902
+ config.lngLat = lngLat;
18903
+ config.altitude = altitude;
18904
+ }
18641
18905
  }
18642
18906
  updateModelRotation(id, rotation) {
18643
18907
  const mapThree = this.getMapThree();
@@ -18685,6 +18949,7 @@ class ModelManager extends manager_Manager {
18685
18949
  if (!mapThree) return;
18686
18950
  mapThree.removeRenderableObject(id);
18687
18951
  this.stopAnimation(id);
18952
+ this.modelConfigs.delete(id);
18688
18953
  }
18689
18954
  clearModels() {
18690
18955
  const mapThree = this.getMapThree();
@@ -18697,6 +18962,24 @@ class ModelManager extends manager_Manager {
18697
18962
  mixer.stopAllAction();
18698
18963
  });
18699
18964
  this.mixers.clear();
18965
+ this.modelConfigs.clear();
18966
+ }
18967
+ handleCoordSystemChange(_system) {
18968
+ const mapThree = this.getMapThree();
18969
+ if (!mapThree || 0 === this.modelConfigs.size) return;
18970
+ this.modelConfigs.forEach((config, id)=>{
18971
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', config.lngLat);
18972
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, config.altitude || 0);
18973
+ const mercatorScale = modelAsMercator.meterInMercatorCoordinateUnits() * (config.scale || 1);
18974
+ const renderableObj = mapThree.getRenderableObject(id);
18975
+ if (renderableObj) mapThree.updateRenderableObjectTransform(id, {
18976
+ ...renderableObj.transform,
18977
+ translateX: modelAsMercator.x,
18978
+ translateY: modelAsMercator.y,
18979
+ translateZ: modelAsMercator.z,
18980
+ scale: mercatorScale
18981
+ });
18982
+ });
18700
18983
  }
18701
18984
  getModel(id) {
18702
18985
  const mapThree = this.getMapThree();
@@ -18754,6 +19037,7 @@ class ThreeManager extends manager_Manager {
18754
19037
  boxHelper = null;
18755
19038
  isSelected = false;
18756
19039
  clickCleanup = null;
19040
+ originalModelConfig = null;
18757
19041
  constructor(mapless){
18758
19042
  super(mapless);
18759
19043
  this.map = mapless.map;
@@ -18799,7 +19083,8 @@ class ThreeManager extends manager_Manager {
18799
19083
  this.baseRotation = [
18800
19084
  ...rotation
18801
19085
  ];
18802
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
19086
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
19087
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
18803
19088
  this.modelTransform = {
18804
19089
  translateX: modelAsMercator.x,
18805
19090
  translateY: modelAsMercator.y,
@@ -18821,6 +19106,14 @@ class ThreeManager extends manager_Manager {
18821
19106
  action.play();
18822
19107
  this.currentAction = action;
18823
19108
  }
19109
+ this.originalModelConfig = {
19110
+ url,
19111
+ lngLat,
19112
+ altitude,
19113
+ rotation,
19114
+ scale,
19115
+ color
19116
+ };
18824
19117
  const animationNames = this.animations.map((anim)=>anim.name);
18825
19118
  resolve({
18826
19119
  model: this.model,
@@ -18863,11 +19156,16 @@ class ThreeManager extends manager_Manager {
18863
19156
  updatePosition(lngLat, altitude = 0) {
18864
19157
  const mapThree = this.getMapThree();
18865
19158
  if (!mapThree || !this.model) return;
18866
- const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
19159
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
19160
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
18867
19161
  this.modelTransform.translateX = modelAsMercator.x;
18868
19162
  this.modelTransform.translateY = modelAsMercator.y;
18869
19163
  this.modelTransform.translateZ = modelAsMercator.z;
18870
19164
  this.modelTransform.scale = modelAsMercator.meterInMercatorCoordinateUnits() * this.userScale;
19165
+ if (this.originalModelConfig) {
19166
+ this.originalModelConfig.lngLat = lngLat;
19167
+ this.originalModelConfig.altitude = altitude;
19168
+ }
18871
19169
  this._buildFullTransformMatrix(this.currentOrientation.heading, this.currentOrientation.pitch, this.currentOrientation.roll);
18872
19170
  }
18873
19171
  _applyBaseRotation() {
@@ -19029,6 +19327,7 @@ class ThreeManager extends manager_Manager {
19029
19327
  this.model = null;
19030
19328
  this.animations = [];
19031
19329
  this.currentAction = null;
19330
+ this.originalModelConfig = null;
19032
19331
  if (this.mixer) {
19033
19332
  this.mixer.stopAllAction();
19034
19333
  this.mixer = null;
@@ -19037,6 +19336,24 @@ class ThreeManager extends manager_Manager {
19037
19336
  this.updateAnimation();
19038
19337
  });
19039
19338
  }
19339
+ handleCoordSystemChange(_system) {
19340
+ if (!this.originalModelConfig) return;
19341
+ const mapThree = this.getMapThree();
19342
+ if (!mapThree || !this.model) return;
19343
+ const { lngLat, altitude } = this.originalModelConfig;
19344
+ const transformedLngLat = this.mapless?.coordTrans('dataToTile', lngLat);
19345
+ const modelAsMercator = mapbox_gl.MercatorCoordinate.fromLngLat(transformedLngLat, altitude);
19346
+ this.modelTransform.translateX = modelAsMercator.x;
19347
+ this.modelTransform.translateY = modelAsMercator.y;
19348
+ this.modelTransform.translateZ = modelAsMercator.z;
19349
+ this.modelTransform.scale = modelAsMercator.meterInMercatorCoordinateUnits() * this.userScale;
19350
+ this._buildFullTransformMatrix(this.currentOrientation.heading, this.currentOrientation.pitch, this.currentOrientation.roll);
19351
+ mapThree.updateRenderableObjectTransform(this.modelId, this.modelTransform);
19352
+ }
19353
+ onStyleChanged = (_tag)=>{
19354
+ const mapThree = this.getMapThree();
19355
+ mapThree?.onStyleChanged();
19356
+ };
19040
19357
  destroy() {
19041
19358
  this.dispose();
19042
19359
  }