@mappedin/blue-dot 6.0.1-beta.59 → 6.0.1-beta.60

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.
@@ -32,7 +32,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
32
32
  var define_process_default;
33
33
  var init_define_process = __esm({
34
34
  "<define:process>"() {
35
- define_process_default = { env: { npm_package_version: "6.0.1-beta.59" } };
35
+ define_process_default = { env: { npm_package_version: "6.0.1-beta.60" } };
36
36
  }
37
37
  });
38
38
 
@@ -1557,4 +1557,4 @@ export {
1557
1557
  init_define_process,
1558
1558
  BlueDot
1559
1559
  };
1560
- //# sourceMappingURL=chunk-EEQMR2QG.js.map
1560
+ //# sourceMappingURL=chunk-RONFZDXM.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["<define:process>", "../../../../node_modules/.pnpm/simplify-js@1.2.4/node_modules/simplify-js/simplify.js", "../../src/blue-dot.ts", "../../../packages/common/Mappedin.Logger.ts", "../../../packages/common/pubsub.ts", "../../../packages/common/utils.ts", "../../../../node_modules/.pnpm/jwt-decode@4.0.0/node_modules/jwt-decode/build/esm/index.js", "../../../packages/common/constants.ts", "../../../packages/common/math-utils.ts", "../../../packages/common/array-utils.ts", "../../src/constants.ts", "../../src/model-manager.ts", "../../src/models/accuracy-ring.gltf", "../../src/models/blue-dot.gltf", "../../src/models/heading-cone.gltf", "../../src/utils.ts", "../../src/schemas.ts", "../../src/state-machine.ts"],
4
- "sourcesContent": ["{\"env\":{\"npm_package_version\":\"6.0.1-beta.59\"}}", "/*\n (c) 2017, Vladimir Agafonkin\n Simplify.js, a high-performance JS polyline simplification library\n mourner.github.io/simplify-js\n*/\n\n(function () { 'use strict';\n\n// to suit your point format, run search/replace for '.x' and '.y';\n// for 3D version, see 3d branch (configurability would draw significant performance overhead)\n\n// square distance between 2 points\nfunction getSqDist(p1, p2) {\n\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y;\n\n return dx * dx + dy * dy;\n}\n\n// square distance from a point to a segment\nfunction getSqSegDist(p, p1, p2) {\n\n var x = p1.x,\n y = p1.y,\n dx = p2.x - x,\n dy = p2.y - y;\n\n if (dx !== 0 || dy !== 0) {\n\n var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);\n\n if (t > 1) {\n x = p2.x;\n y = p2.y;\n\n } else if (t > 0) {\n x += dx * t;\n y += dy * t;\n }\n }\n\n dx = p.x - x;\n dy = p.y - y;\n\n return dx * dx + dy * dy;\n}\n// rest of the code doesn't care about point format\n\n// basic distance-based simplification\nfunction simplifyRadialDist(points, sqTolerance) {\n\n var prevPoint = points[0],\n newPoints = [prevPoint],\n point;\n\n for (var i = 1, len = points.length; i < len; i++) {\n point = points[i];\n\n if (getSqDist(point, prevPoint) > sqTolerance) {\n newPoints.push(point);\n prevPoint = point;\n }\n }\n\n if (prevPoint !== point) newPoints.push(point);\n\n return newPoints;\n}\n\nfunction simplifyDPStep(points, first, last, sqTolerance, simplified) {\n var maxSqDist = sqTolerance,\n index;\n\n for (var i = first + 1; i < last; i++) {\n var sqDist = getSqSegDist(points[i], points[first], points[last]);\n\n if (sqDist > maxSqDist) {\n index = i;\n maxSqDist = sqDist;\n }\n }\n\n if (maxSqDist > sqTolerance) {\n if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);\n simplified.push(points[index]);\n if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);\n }\n}\n\n// simplification using Ramer-Douglas-Peucker algorithm\nfunction simplifyDouglasPeucker(points, sqTolerance) {\n var last = points.length - 1;\n\n var simplified = [points[0]];\n simplifyDPStep(points, 0, last, sqTolerance, simplified);\n simplified.push(points[last]);\n\n return simplified;\n}\n\n// both algorithms combined for awesome performance\nfunction simplify(points, tolerance, highestQuality) {\n\n if (points.length <= 2) return points;\n\n var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;\n\n points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);\n points = simplifyDouglasPeucker(points, sqTolerance);\n\n return points;\n}\n\n// export as AMD module / Node module / browser or worker variable\nif (typeof define === 'function' && define.amd) define(function() { return simplify; });\nelse if (typeof module !== 'undefined') {\n module.exports = simplify;\n module.exports.default = simplify;\n} else if (typeof self !== 'undefined') self.simplify = simplify;\nelse window.simplify = simplify;\n\n})();\n", "import type {\n\tFloor,\n\tMapData,\n\tMapView,\n\tModel,\n\tTCameraAnimationOptions,\n\tTCameraTarget,\n\tTEvents,\n} from '@mappedin/mappedin-js';\nimport { ANIMATION_TWEENS, Coordinate } from '@mappedin/mappedin-js';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { getForwardBearing } from '@packages/internal/common/utils';\nimport type { Tween } from '@tweenjs/tween.js';\nimport simplify from 'simplify-js';\nimport z from 'zod';\nimport { DEFAULT_BLUEDOT_OPTIONS, POSITION_ANIMATION_DURATION } from './constants';\nimport { BlueDotModelManager } from './model-manager';\nimport { geolocationPositionSchema, positionSchema } from './schemas';\nimport { stateMachine } from './state-machine';\nimport type {\n\tBlueDotAction,\n\tBlueDotEventPayloads,\n\tBlueDotState,\n\tBlueDotPositionProcessor,\n\tBlueDotPositionUpdate,\n\tBlueDotPositionUpdateWithFloor,\n\tBlueDotStatus,\n\tBlueDotUpdateOptions,\n\tFollowCameraOptions,\n\tFollowMode,\n\tGeolocationPositionExtended,\n\tParsedBlueDotPosition,\n\tBlueDotUpdateState,\n} from './types';\nimport {\n\tdeepMergeState,\n\teaseOutCubic,\n\tfindBlueDotOnPath,\n\tgetPositionWithOverrides,\n\tisWithinPanBounds,\n\tshouldShowHeadingCone,\n} from './utils';\nimport type { ReadonlyDeep } from 'type-fest';\n\n/**\n * Show a Blue Dot indicating the device's position on the map.\n *\n * @example\n * ```ts\n * import { show3dMap } from '@mappedin/mappedin-js';\n * import { BlueDot } from '@mappedin/blue-dot';\n *\n * const mapView = await show3dMap(...);\n *\n * // Enable BlueDot\n * new BlueDot(mapView).enable();\n *\n * // Option 1: Listen for position updates from the device\n * mapView.BlueDot.on('position-update', (position) => {\n * console.log('User position:', position);\n * });\n *\n * // Option 2: Update position manually\n * new BlueDot(mapView).update({ latitude, longitude, accuracy, floorOrFloorId });\n *\n * ```\n */\nexport class BlueDot implements MapViewExtension<BlueDotState> {\n\t#pubsub = new PubSub<BlueDotEventPayloads>();\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#watcherId?: number;\n\t/**\n\t * The latest position received from the device's geolocation API.\n\t */\n\t#currentGeolocation?: ParsedBlueDotPosition;\n\t/** The latest position manually set by the user. */\n\t#overridePosition?: BlueDotPositionUpdateWithFloor;\n\t/** The latest actual position of the Blue Dot. */\n\t#lastPosition?: ParsedBlueDotPosition;\n\t#timer?: NodeJS.Timeout;\n\t#positionAnimation?: Tween;\n\t#options: BlueDotState = DEFAULT_BLUEDOT_OPTIONS;\n\t#cachedCoordinate?: Coordinate;\n\t#status: BlueDotStatus = 'disabled';\n\t#following = false;\n\t#blueDotModel: BlueDotModelManager;\n\t#currentFloor?: Floor;\n\t#lastFloorAltitude?: number;\n\t#floorTransitionStartTime?: number;\n\t#floorTransitionStartAltitude?: number;\n\t#floorTransitionDuration = 1000;\n\t/**\n\t * Create a new {@link BlueDot} instance.\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#mapView = mapView;\n\t\tthis.#mapData = mapView.getMapData();\n\t\tthis.#mapView.on('pre-render', this.#syncVerticalOffset);\n\t\tthis.#mapView.on('click', this.#handleClick);\n\t\tthis.#mapView.on('hover', this.#handleHover);\n\t\tthis.#blueDotModel = new BlueDotModelManager(mapView, this);\n\t}\n\n\t/**\n\t * Get the Model for the BlueDot core element.\n\t */\n\tget dotModel(): Model | undefined {\n\t\treturn this.#blueDotModel.dot;\n\t}\n\n\t/**\n\t * Get the Model for the accuracy ring.\n\t */\n\tget accuracyRingModel(): Model | undefined {\n\t\treturn this.#blueDotModel.accuracyRing;\n\t}\n\n\t/**\n\t * Get the Model for the heading cone.\n\t */\n\tget headingConeModel(): Model | undefined {\n\t\treturn this.#blueDotModel.headingCone;\n\t}\n\n\t/**\n\t * Whether the BlueDot is currently enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#status !== 'disabled';\n\t}\n\n\t/**\n\t * The current state of the BlueDot. Can be 'hidden', 'active', 'inactive', or 'disabled'.\n\t * Listen for state changes using the 'status-change' event.\n\t *\n\t * @example\n\t * mapView.BlueDot.on('status-change', ({ status }) => {\n\t * if (status === 'active') {\n\t * // BlueDot is visible and tracking\n\t * }\n\t * });\n\t */\n\tget status(): BlueDotStatus {\n\t\treturn this.#status;\n\t}\n\n\t/**\n\t * Whether the BlueDot is currently following the user (camera follow mode).\n\t */\n\tget isFollowing(): boolean {\n\t\treturn this.#following;\n\t}\n\n\t/**\n\t * The direction the user is facing in degrees from north clockwise.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading\n\t */\n\tget heading(): GeolocationPosition['coords']['heading'] | undefined {\n\t\treturn this.#lastPosition?.heading;\n\t}\n\n\t/**\n\t * The accuracy of the current position in metres.\n\t */\n\tget accuracy(): GeolocationPosition['coords']['accuracy'] | undefined {\n\t\treturn this.#lastPosition?.accuracy;\n\t}\n\n\t/**\n\t * The coordinate of the current position.\n\t */\n\tget coordinate(): Coordinate | undefined {\n\t\tif (this.#lastPosition == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (\n\t\t\tthis.#cachedCoordinate == null ||\n\t\t\tthis.floor?.id !== this.#cachedCoordinate.floorId ||\n\t\t\tthis.#lastPosition.latitude !== this.#cachedCoordinate.latitude ||\n\t\t\tthis.#lastPosition.longitude !== this.#cachedCoordinate.longitude\n\t\t) {\n\t\t\tthis.#cachedCoordinate = new Coordinate({\n\t\t\t\tlatitude: this.#lastPosition.latitude,\n\t\t\t\tlongitude: this.#lastPosition.longitude,\n\t\t\t\tfloorId: this.floor?.id,\n\t\t\t});\n\t\t}\n\n\t\treturn this.#cachedCoordinate;\n\t}\n\n\tgetState = (): ReadonlyDeep<BlueDotState> => {\n\t\treturn { ...this.#options };\n\t};\n\n\t/**\n\t * The floor the Blue Dot is currently on. If undefined, the Blue Dot will appear on every floor.\n\t */\n\tget floor(): Floor | undefined {\n\t\treturn this.#lastPosition?.floor;\n\t}\n\n\t/**\n\t * Enable the Blue Dot. It will be hidden until a position is received either from the browser or by calling {@link BlueDot.update}.\n\t * @param options - The options to setup the Blue Dot (see {@link BlueDotOptions}).\n\t *\n\t * @example Enable with default options\n\t * mapView.BlueDot.enable();\n\t *\n\t * @example Enable with custom color and accuracy ring\n\t * mapView.BlueDot.enable({ color: '#00ff00', accuracyRing: { color: '#00ff00', opacity: 0.2 } });\n\t *\n\t * @see See the [BlueDot Guide](https://developer.mappedin.com/web-sdk/blue-dot) for more information.\n\t */\n\tenable = (options?: BlueDotUpdateState) => {\n\t\tthis.#options = deepMergeState(this.#options, options);\n\t\tthis.#transitionAction('enable');\n\n\t\t// Handle initial state\n\t\tif (this.#options.initialState === 'inactive') {\n\t\t\tthis.#transitionAction('initialize');\n\t\t}\n\n\t\tthis.watchDevicePosition(this.#options.watchDevicePosition);\n\t};\n\t/**\n\t * Disable the Blue Dot. It will be hidden and no longer update.\n\t */\n\tdisable = () => {\n\t\tthis.#blueDotModel.remove();\n\t\tif (this.#timer) {\n\t\t\tclearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tif (this.#following) {\n\t\t\tthis.#cancelFollow();\n\t\t}\n\t\tthis.watchDevicePosition(false);\n\t\tthis.#lastPosition = undefined;\n\t\tthis.#overridePosition = undefined;\n\t\tthis.#currentFloor = undefined;\n\t\tthis.#transitionAction('disable');\n\t\tthis.#mapView.off('user-interaction-start', this.#cancelFollow);\n\t\tthis.#mapView.off('navigation-active-path-change', this.#pathChangeHandler);\n\t};\n\n\t/**\n\t * Subscribe to a BlueDot event.\n\t * @param eventName The name of the event to listen for.\n\t * @param fn The function to call when the event is emitted.\n\t */\n\ton: PubSub<BlueDotEventPayloads>['on'] = (eventName, fn) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a BlueDot event.\n\t * @param eventName The name of the event to unsubscribe from.\n\t * @param fn The function to unsubscribe from the event.\n\t */\n\toff: PubSub<BlueDotEventPayloads>['off'] = (eventName, fn) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Update the BlueDot state after it has been enabled.\n\t * This allows overriding previously set values like colors, and other options.\n\t * @param options - The options to update\n\t *\n\t * @example Update color and accuracy ring\n\t * mapView.BlueDot.updateState({\n\t * color: '#ff0000',\n\t * accuracyRing: { color: '#ff0000', opacity: 0.5 }\n\t * });\n\t */\n\tupdateState = (options: BlueDotUpdateState) => {\n\t\tconst oldWatchDevicePosition = this.#options.watchDevicePosition;\n\t\tthis.#options = deepMergeState(this.#options, options);\n\n\t\tthis.#blueDotModel.updateAppearance();\n\n\t\tif (options.watchDevicePosition != null && options.watchDevicePosition !== oldWatchDevicePosition) {\n\t\t\tthis.watchDevicePosition(options.watchDevicePosition);\n\t\t}\n\n\t\t// Reset timer if timeout option was updated and BlueDot is active\n\t\tif (options.timeout != null && this.#status === 'active') {\n\t\t\tthis.#resetActiveTimer();\n\t\t}\n\t};\n\n\t#resetActiveTimer = () => {\n\t\tif (this.#timer) {\n\t\t\tclearTimeout(this.#timer);\n\t\t}\n\t\tif (typeof this.#options.timeout === 'number' && this.#options.timeout < Infinity) {\n\t\t\tthis.#timer = setTimeout(() => {\n\t\t\t\tif (this.#options.debug) {\n\t\t\t\t\tLogger.log(`BlueDot: Position timed out after ${this.#options.timeout}ms`);\n\t\t\t\t}\n\t\t\t\tthis.#transitionAction('timeout');\n\t\t\t\t// this.#core.render();\n\t\t\t}, this.#options.timeout);\n\t\t}\n\t};\n\n\t/**\n\t * Enable or disable the devices's geolocation listener to automatically position the Blue Dot.\n\t * If enabled, the device will request permission to access the user's precise location.\n\t * @param watch - Whether to enable or disable the listener.\n\t */\n\twatchDevicePosition = (watch: boolean) => {\n\t\tif (this.#watcherId) {\n\t\t\tnavigator.geolocation.clearWatch(this.#watcherId);\n\t\t\tthis.#watcherId = undefined;\n\t\t}\n\n\t\tif (this.#currentGeolocation) {\n\t\t\tthis.#currentGeolocation = undefined;\n\t\t}\n\n\t\tif (watch) {\n\t\t\tif (this.#status === 'disabled') {\n\t\t\t\tLogger.warn('BlueDot must be enabled before watching browser position.');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.#watcherId = navigator.geolocation.watchPosition(this.onPositionUpdate, this.onPositionError, {\n\t\t\t\tenableHighAccuracy: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t#setPosition = (update: BlueDotPositionUpdateWithFloor | undefined, options?: BlueDotUpdateOptions) => {\n\t\tlet parsed: ParsedBlueDotPosition | undefined;\n\t\ttry {\n\t\t\tparsed = positionSchema.parse(getPositionWithOverrides(update, this.#overridePosition));\n\t\t} catch (error) {\n\t\t\tthis.#transitionAction('error');\n\t\t\tLogger.error('BlueDot: Position parse failed', error instanceof z.ZodError ? error.message : String(error));\n\n\t\t\treturn;\n\t\t}\n\t\tif (this.#options.debug) {\n\t\t\tLogger.log('BlueDot: Parsed position', parsed);\n\t\t}\n\n\t\t// Check if position is within pan bounds\n\t\tif (this.#options.preventOutOfBounds) {\n\t\t\tconst { radius, center } = this.#mapView.Camera.bounds;\n\t\t\tif (radius != null && isFinite(radius) && center != null) {\n\t\t\t\tconst within = isWithinPanBounds(\n\t\t\t\t\t{ longitude: parsed.longitude, latitude: parsed.latitude },\n\t\t\t\t\t{ radius, center },\n\t\t\t\t);\n\t\t\t\tif (!within) {\n\t\t\t\t\tLogger.warn(\n\t\t\t\t\t\t`BlueDot: Position [${parsed.longitude}, ${parsed.latitude}] is outside map bounds. Position update will be discarded.`,\n\t\t\t\t\t);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if the position accuracy passes the threshold\n\t\tif (!this.#isAccurateEnough(parsed.accuracy)) {\n\t\t\tLogger.log(\n\t\t\t\t`BlueDot: Dropping position update with accuracy ${parsed.accuracy}m (exceeds threshold ${\n\t\t\t\t\tthis.#options.accuracyThreshold\n\t\t\t\t}m)`,\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options?.silent) {\n\t\t\t// Only transition state if not silent\n\t\t\tthis.#transitionAction('position-update');\n\t\t} else {\n\t\t\tthis.#blueDotModel.updateAppearance();\n\t\t}\n\n\t\t// Check if geometry should be updated after state transition\n\t\tif (!this.#shouldUpdateGeometry()) {\n\t\t\tLogger.warn(\n\t\t\t\t`BlueDot: Cannot update position because BlueDot state is '${this.#status}'. BlueDot must be enabled first.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#applyPosition(parsed, options);\n\t};\n\n\t#applyPosition = (position: ParsedBlueDotPosition, options?: BlueDotUpdateOptions) => {\n\t\tthis.#lastPosition = position;\n\t\t// Handle side effects based on options\n\t\tif (!options?.silent) {\n\t\t\tthis.#resetActiveTimer();\n\n\t\t\tthis.#getAnalyticsIfEnabled().updateState({\n\t\t\t\tuserPosition: {\n\t\t\t\t\tbluedotTimestamp: Date.now(),\n\t\t\t\t\tlatitude: position.latitude,\n\t\t\t\t\tlongitude: position.longitude,\n\t\t\t\t\tfloorLevel: position.floor?.elevation,\n\t\t\t\t\taccuracy: position.accuracy,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tlet startPosition: [number, number, number];\n\t\tlet startWorldAltitude = 0;\n\t\tif (!this.dotModel) {\n\t\t\tstartPosition = [position.longitude, position.latitude, 0];\n\t\t\tstartWorldAltitude = position.floor ? this.#mapView.getState(position.floor)?.altitude ?? 0 : 0;\n\t\t\tthis.#lastFloorAltitude = startWorldAltitude;\n\t\t\tthis.#currentFloor = position.floor;\n\t\t\tthis.#blueDotModel.add(position);\n\t\t} else {\n\t\t\tconst coordinate = this.#blueDotModel.getPosition();\n\t\t\tstartPosition = [coordinate?.longitude ?? 0, coordinate?.latitude ?? 0, coordinate?.verticalOffset ?? 0];\n\t\t}\n\n\t\t// Stop any existing animation before calculating positions\n\t\tif (this.#positionAnimation) {\n\t\t\tthis.#positionAnimation.stop();\n\t\t\tthis.#positionAnimation = undefined;\n\t\t}\n\n\t\t// Handle floor transitions with smooth interpolation (no fixed target tweening)\n\t\tconst isFloorChange = this.#currentFloor?.id !== position.floor?.id;\n\n\t\tif (isFloorChange) {\n\t\t\t// Start floor transition - record the current altitude and time\n\t\t\tthis.#floorTransitionStartTime = Date.now();\n\t\t\tthis.#floorTransitionStartAltitude = this.#lastFloorAltitude ?? 0;\n\t\t\tthis.#currentFloor = position.floor;\n\t\t}\n\n\t\t// Only animate lat/lng, altitude is handled separately\n\t\tconst to: [number, number] = [position.longitude, position.latitude];\n\n\t\tconst setGeometryPosition = (newPos: [number, number]) => {\n\t\t\t// Altitude is handled entirely by pre-render sync, just use current cached value\n\t\t\tconst currentAltitude = this.#lastFloorAltitude ?? 0;\n\t\t\tthis.#blueDotModel.setPosition(\n\t\t\t\tnew Coordinate({\n\t\t\t\t\tlatitude: newPos[1],\n\t\t\t\t\tlongitude: newPos[0],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.#blueDotModel.setAltitude(currentAltitude);\n\t\t};\n\n\t\t// Handle animation based on options\n\t\tif (options?.animate === false) {\n\t\t\t// Set position immediately without animation\n\t\t\tsetGeometryPosition(to);\n\t\t\tthis.#updateAccuracyRing();\n\t\t\tthis.#updateHeadingCone();\n\t\t} else {\n\t\t\t// Use animation for position updates (lat/lng only)\n\t\t\tconst startLatLng: [number, number] = [startPosition[0], startPosition[1]];\n\t\t\tthis.#positionAnimation = this.#mapView\n\t\t\t\t.tween({ position: startLatLng })\n\t\t\t\t.to({ position: to }, POSITION_ANIMATION_DURATION)\n\t\t\t\t.easing(ANIMATION_TWEENS['ease-out'])\n\t\t\t\t.onUpdate(({ position }) => {\n\t\t\t\t\t// Track current animated position (lat/lng only)\n\t\t\t\t\tsetGeometryPosition(position as [number, number]);\n\t\t\t\t})\n\t\t\t\t.onStart(() => {\n\t\t\t\t\tthis.#updateAccuracyRing();\n\t\t\t\t\tthis.#updateHeadingCone();\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t}\n\n\t\t// Publish position updates unless silent\n\t\tif (!options?.silent) {\n\t\t\tthis.#pubsub.publish('position-update', {\n\t\t\t\tfloor: this.floor,\n\t\t\t\theading: this.heading,\n\t\t\t\taccuracy: this.accuracy,\n\t\t\t\tcoordinate: this.coordinate!,\n\t\t\t});\n\t\t}\n\t};\n\n\t#updateAccuracyRing = () => {\n\t\tif (this.#status === 'active') {\n\t\t\tthis.#blueDotModel.setAccuracy(this.accuracy);\n\t\t} else {\n\t\t\tthis.#blueDotModel.setAccuracy(undefined);\n\t\t}\n\t};\n\n\t#updateHeadingCone = () => {\n\t\tconst shouldShow = shouldShowHeadingCone(this.#status, this.heading, this.#options.heading.displayWhenInactive);\n\t\tif (this.heading != null && shouldShow) {\n\t\t\tthis.#blueDotModel.setHeading(this.heading);\n\t\t} else {\n\t\t\tthis.#blueDotModel.setHeading(undefined);\n\t\t}\n\t};\n\n\t#shouldUpdateGeometry = (): boolean => {\n\t\treturn this.#status !== 'hidden' && this.#status !== 'disabled';\n\t};\n\n\t/**\n\t * Manually override some position properties of the Blue Dot.\n\t * Accepts a full GeolocationPosition object or a partial {@link BlueDotPositionUpdate} object.\n\t * @example Manually set the accuracy and heading\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 10, heading: 90 });\n\t * ```\n\t * @example Reset accuracy and heading to device values\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 'device', heading: 'device' });\n\t * ```\n\t */\n\tupdate = (\n\t\tposition: GeolocationPositionExtended | BlueDotPositionUpdate | undefined,\n\t\toptions?: BlueDotUpdateOptions,\n\t) => {\n\t\tif (position == null) {\n\t\t\tthis.#overridePosition = undefined;\n\t\t} else if ('coords' in position) {\n\t\t\tthis.#overridePosition = Object.assign({}, this.#overridePosition, {\n\t\t\t\tlatitude: position.coords.latitude,\n\t\t\t\tlongitude: position.coords.longitude,\n\t\t\t\taccuracy: position.coords.accuracy,\n\t\t\t\theading: position.coords.heading,\n\t\t\t\tfloor: this.#getFloorByFloorLevel(position.coords.floorLevel),\n\t\t\t\ttimestamp: position.timestamp,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.#overridePosition = Object.assign({}, this.#overridePosition, position);\n\t\t\tif ('floorOrFloorId' in position) {\n\t\t\t\tthis.#overridePosition.floor =\n\t\t\t\t\ttypeof position.floorOrFloorId === 'string' && position.floorOrFloorId !== 'device'\n\t\t\t\t\t\t? this.#getFloorByFloorId(position.floorOrFloorId)\n\t\t\t\t\t\t: position.floorOrFloorId;\n\t\t\t}\n\t\t}\n\t\tconst hasPosition = this.#overridePosition?.latitude != null && this.#overridePosition?.longitude != null;\n\t\tif (hasPosition || this.#currentGeolocation != null) {\n\t\t\tthis.#setPosition(this.#currentGeolocation, options);\n\t\t}\n\t};\n\n\t#getFloorByFloorId = (floorId: string) => {\n\t\treturn this.#mapData.getById('floor', floorId);\n\t};\n\n\t#getFloorByFloorLevel = (floorLevel: GeolocationPositionExtended['coords']['floorLevel']) => {\n\t\tif (floorLevel == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this.#mapView.currentFloorStack.floors\n\t\t\t.sort((a, b) => a.elevation - b.elevation)\n\t\t\t.find(f => f.elevation === floorLevel);\n\t};\n\n\t#simplifiedDirections?: number[][];\n\t#positionProcessor?: BlueDotPositionProcessor;\n\t#getSimplifiedDirections = () => {\n\t\tif (this.#simplifiedDirections == null && this.#mapView.Navigation.activeDirections != null) {\n\t\t\tconst coordinates = Array.isArray(this.#mapView.Navigation.activeDirections)\n\t\t\t\t? this.#mapView.Navigation.activeDirections.flatMap(d => d.coordinates)\n\t\t\t\t: this.#mapView.Navigation.activeDirections.coordinates;\n\t\t\tconst coordinatesOnMap = coordinates.filter(c => c.floorId === this.#mapView.currentFloor.id);\n\t\t\t// simplify the path to reduce the number of points to check, and avoid bearing jitter\n\t\t\tthis.#simplifiedDirections = simplify(\n\t\t\t\tcoordinatesOnMap.map(c => ({ x: c.longitude, y: c.latitude })),\n\t\t\t\t0.00001,\n\t\t\t).map(p => [p.x, p.y]);\n\t\t}\n\n\t\treturn this.#simplifiedDirections;\n\t};\n\t#cancelFollow = () => {\n\t\tif (this.#mapView.Camera.isAnimating) {\n\t\t\tthis.#mapView.Camera.cancelAnimation();\n\t\t}\n\t\tif (this.#followHandler) {\n\t\t\tthis.off('position-update', this.#followHandler);\n\t\t\tthis.#followHandler = undefined;\n\t\t}\n\t\tthis.#following = false;\n\t\tthis.#simplifiedDirections = undefined;\n\t\tthis.#mapView.off('user-interaction-start', this.#cancelFollow);\n\t\tthis.#mapView.off('navigation-active-path-change', this.#pathChangeHandler);\n\t\tthis.#pubsub.publish('follow-change', { following: false });\n\t};\n\t#pathChangeHandler = () => {\n\t\tthis.#simplifiedDirections = undefined;\n\t};\n\t#followHandler?: (event: BlueDotEventPayloads['position-update']) => void;\n\t/**\n\t * Set the camera to follow the BlueDot in various modes. User interaction will cancel following automatically.\n\t * @param mode The follow mode ('position-only', 'position-and-heading', 'position-and-path-direction', or false to disable).\n\t * @param cameraOptions Optional camera options (zoom, pitch, etc.).\n\t *\n\t * @example\n\t * mapView.BlueDot.follow('position-and-heading', { zoomLevel: 21, pitch: 45 });\n\t */\n\tfollow = (mode: FollowMode, cameraOptions?: FollowCameraOptions) => {\n\t\tif (mode === false) {\n\t\t\tthis.#cancelFollow();\n\n\t\t\treturn;\n\t\t}\n\n\t\t// bearing is only available in position-only mode\n\t\tif (mode !== 'position-only' && cameraOptions?.bearing != null) {\n\t\t\tLogger.warn(\n\t\t\t\t`BlueDot: Camera bearing option will be ignored in follow mode '${mode}'. To control the bearing manually, use mode 'position-only'.`,\n\t\t\t);\n\t\t}\n\n\t\tconst cameraTargetWithDefaults: TCameraTarget = {\n\t\t\tzoomLevel: cameraOptions?.zoomLevel ?? 21,\n\t\t\tbearing: mode === 'position-only' ? cameraOptions?.bearing : undefined,\n\t\t\tpitch: cameraOptions?.pitch ?? 45,\n\t\t};\n\t\tconst cameraOptionsWithDefaults: TCameraAnimationOptions = {\n\t\t\tduration: cameraOptions?.duration ?? POSITION_ANIMATION_DURATION,\n\t\t\teasing: cameraOptions?.easing ?? 'ease-in-out',\n\t\t};\n\n\t\tif (this.#following) {\n\t\t\t// already following, just updating the handler\n\t\t\tif (this.#followHandler) {\n\t\t\t\tthis.off('position-update', this.#followHandler);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.#following = true;\n\t\t\tthis.#mapView.on('user-interaction-start', this.#cancelFollow);\n\t\t\tthis.#mapView.on('navigation-active-path-change', this.#pathChangeHandler);\n\t\t}\n\n\t\tthis.#followHandler = (event: BlueDotEventPayloads['position-update']) => {\n\t\t\tconst { coordinate, heading, floor } = event;\n\t\t\tcameraTargetWithDefaults.center = coordinate;\n\n\t\t\tif (floor != null && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\tthis.#mapView.setFloor(floor.id);\n\t\t\t\tthis.#simplifiedDirections = undefined;\n\t\t\t}\n\n\t\t\tif (mode === 'position-and-heading') {\n\t\t\t\tcameraTargetWithDefaults.bearing = heading ?? undefined;\n\t\t\t} else if (mode === 'position-and-path-direction') {\n\t\t\t\tconst directions = this.#getSimplifiedDirections();\n\t\t\t\tif (directions != null) {\n\t\t\t\t\tconst intersection = findBlueDotOnPath(directions, [coordinate.longitude, coordinate.latitude]);\n\t\t\t\t\tif (intersection != null) {\n\t\t\t\t\t\tconst segment = directions[intersection.segmentIndex];\n\t\t\t\t\t\tconst endSegment = directions[intersection.segmentIndex + 1];\n\t\t\t\t\t\tcameraTargetWithDefaults.bearing = getForwardBearing(segment, endSegment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.#mapView.Camera.animateTo(cameraTargetWithDefaults, cameraOptionsWithDefaults);\n\t\t};\n\t\tthis.on('position-update', this.#followHandler);\n\t\tthis.#pubsub.publish('follow-change', { following: true, mode });\n\t};\n\n\t/**\n\t * Set a position processor callback that allows intercepting and modifying device/geolocation position updates before they are applied.\n\t *\n\t * **Note**: This processor only applies to automatic position updates from device geolocation.\n\t * Manual position updates via `update()` method bypass the processor and are applied directly.\n\t *\n\t * @param processor - A callback function that receives current state and incoming update. Return undefined to discard the update, or return a modified update object.\n\t *\n\t * @example Discard inaccurate positions\n\t * ```ts\n\t * blueDot.setPositionProcessor((current, incoming) => {\n\t * if (incoming.accuracy && incoming.accuracy > 50) {\n\t * return undefined; // Discard update\n\t * }\n\t * return incoming; // Accept update\n\t * });\n\t * ```\n\t *\n\t * @example Modify incoming positions\n\t * ```ts\n\t * blueDot.setPositionProcessor((current, incoming) => {\n\t * // Apply custom smoothing or validation logic\n\t * return {\n\t * ...incoming,\n\t * accuracy: Math.min(incoming.accuracy || 100, 10) // Cap accuracy\n\t * };\n\t * });\n\t * ```\n\t */\n\tsetPositionProcessor(processor?: BlueDotPositionProcessor) {\n\t\tthis.#positionProcessor = processor;\n\t}\n\n\t/**\n\t * Checks if the current accuracy is acceptable for updating the BlueDot position.\n\t * @param accuracy The accuracy value to check\n\t * @returns true if the accuracy is acceptable, false if it should be dropped\n\t */\n\t#isAccurateEnough = (accuracy: number | undefined): boolean => {\n\t\tif (accuracy == null) {\n\t\t\t// We cannot infer much from the lack of accuracy data, so we consider it accurate enough\n\t\t\treturn this.#status !== 'disabled';\n\t\t}\n\n\t\treturn accuracy <= this.#options.accuracyThreshold;\n\t};\n\n\t/**\n\t * Process incoming position update through the position processor callback if set.\n\t * @param incoming The incoming position update\n\t * @returns The processed position update or undefined if discarded\n\t */\n\t#processIncomingPosition = (incoming: BlueDotPositionUpdateWithFloor): BlueDotPositionUpdateWithFloor | undefined => {\n\t\t// Build current state from last position\n\t\tconst currentState: BlueDotPositionUpdateWithFloor = {\n\t\t\tlatitude: this.#lastPosition?.latitude,\n\t\t\tlongitude: this.#lastPosition?.longitude,\n\t\t\taccuracy: this.#lastPosition?.accuracy,\n\t\t\theading: this.#lastPosition?.heading,\n\t\t\tfloor: this.#lastPosition?.floor,\n\t\t\ttimestamp: this.#lastPosition?.timestamp,\n\t\t};\n\n\t\ttry {\n\t\t\treturn this.#positionProcessor!(currentState, incoming);\n\t\t} catch (error) {\n\t\t\tLogger.error(\n\t\t\t\t'BlueDot: Position processor callback threw an error',\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t);\n\t\t\t// Fall back to original position on error\n\t\t\treturn incoming;\n\t\t}\n\t};\n\n\tdestroy = () => {\n\t\tthis.disable();\n\t\tthis.#blueDotModel.destroy();\n\t\tthis.#mapView.off('pre-render', this.#syncVerticalOffset);\n\t\tthis.#mapView.off('click', this.#handleClick);\n\t\tthis.#mapView.off('hover', this.#handleHover);\n\t\tthis.#pubsub.destroy();\n\t};\n\n\t#transitionAction = (action: BlueDotAction) => {\n\t\tconst nextStatus = stateMachine[this.#status].actions[action];\n\t\tif (nextStatus == null) {\n\t\t\tLogger.warn(`BlueDot: Invalid state transition from ${this.#status} to ${nextStatus} using ${action}`);\n\t\t\treturn;\n\t\t}\n\t\tif (nextStatus === this.#status) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.#options.debug) {\n\t\t\tLogger.log(`BlueDot: Transitioning from ${this.#status} to ${nextStatus} using ${action}`);\n\t\t}\n\t\tthis.#status = nextStatus;\n\t\tthis.#blueDotModel.updateAppearance();\n\t\tthis.#pubsub.publish('status-change', {\n\t\t\tstatus: nextStatus,\n\t\t\taction,\n\t\t});\n\t};\n\n\t/**\n\t * Synchronizes BlueDot vertical offset with current floor altitude on every frame.\n\t * Handles smooth floor transitions and real-time altitude tracking.\n\t */\n\t#syncVerticalOffset = () => {\n\t\tif (!this.dotModel || !this.#lastPosition || this.#status === 'hidden' || this.#status === 'disabled') {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the current target floor altitude (always up-to-date)\n\t\tconst targetFloorAltitude = this.#lastPosition.floor\n\t\t\t? this.#mapView.getState(this.#lastPosition.floor)?.altitude ?? 0\n\t\t\t: this.#mapView.getState(this.#mapView.currentFloor)?.altitude ?? 0;\n\n\t\tlet currentAltitude = targetFloorAltitude;\n\n\t\t// Handle smooth floor transitions\n\t\tif (this.#floorTransitionStartTime != null && this.#floorTransitionStartAltitude != null) {\n\t\t\tconst elapsed = Date.now() - this.#floorTransitionStartTime;\n\t\t\tconst progress = Math.min(elapsed / this.#floorTransitionDuration, 1);\n\n\t\t\tif (progress < 1) {\n\t\t\t\t// Still transitioning - interpolate between start altitude and current target\n\t\t\t\tconst easeProgress = easeOutCubic(progress);\n\t\t\t\tcurrentAltitude =\n\t\t\t\t\tthis.#floorTransitionStartAltitude +\n\t\t\t\t\t(targetFloorAltitude - this.#floorTransitionStartAltitude) * easeProgress;\n\t\t\t} else {\n\t\t\t\t// Transition complete - clear transition state\n\t\t\t\tthis.#floorTransitionStartTime = undefined;\n\t\t\t\tthis.#floorTransitionStartAltitude = undefined;\n\t\t\t}\n\t\t}\n\n\t\t// Only update if altitude has changed to avoid unnecessary updates\n\t\tif (this.#lastFloorAltitude !== currentAltitude) {\n\t\t\tthis.#lastFloorAltitude = currentAltitude;\n\t\t\tthis.#blueDotModel.setAltitude(currentAltitude);\n\t\t}\n\t};\n\n\tprivate onPositionUpdate = (position: GeolocationPositionExtended) => {\n\t\tif (this.isEnabled === false) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tgeolocationPositionSchema.parse(position);\n\t\t} catch (error) {\n\t\t\tthis.#transitionAction('error');\n\t\t\tLogger.error(\n\t\t\t\t'BlueDot: Browser sent invalid position',\n\t\t\t\terror instanceof z.ZodError ? error.message : String(error),\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#currentGeolocation = {\n\t\t\tlatitude: position.coords?.latitude,\n\t\t\tlongitude: position.coords?.longitude,\n\t\t\taccuracy: position.coords?.accuracy,\n\t\t\theading: position.coords?.heading,\n\t\t\tfloor: this.#getFloorByFloorLevel(position.coords?.floorLevel),\n\t\t\ttimestamp: position.timestamp,\n\t\t\t// TODO: can we use these in the future ?\n\t\t\t// altitude: position.coords?.altitude,\n\t\t\t// altitudeAccuracy: position.coords?.altitudeAccuracy,\n\t\t\t// speed: position.coords?.speed,\n\t\t};\n\n\t\t// Process the position through processor if defined\n\t\tlet finalPosition = this.#currentGeolocation;\n\t\tif (this.#positionProcessor) {\n\t\t\tconst processedPosition = this.#processIncomingPosition(this.#currentGeolocation);\n\t\t\tif (processedPosition === undefined) {\n\t\t\t\tif (this.#options.debug) {\n\t\t\t\t\tLogger.log('BlueDot: Position update discarded by position processor');\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinalPosition = processedPosition as ParsedBlueDotPosition;\n\t\t}\n\n\t\tthis.#setPosition(finalPosition);\n\t};\n\n\tprivate onPositionError = (error: GeolocationPositionError) => {\n\t\tthis.#transitionAction('error');\n\n\t\tswitch (error.code) {\n\t\t\tcase error.PERMISSION_DENIED:\n\t\t\t\tLogger.error('Geolocation permission denied by the user.', error);\n\t\t\t\tthis.#getAnalyticsIfEnabled().sendWatchPositionDenied();\n\t\t\t\tbreak;\n\t\t\tcase error.POSITION_UNAVAILABLE:\n\t\t\t\tLogger.error('Geolocation position unavailable.', error);\n\t\t\t\tbreak;\n\t\t\tcase error.TIMEOUT:\n\t\t\t\tLogger.error('Geolocation request timed out.', error);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tLogger.error('An unknown geolocation error occurred.', error);\n\t\t\t\tbreak;\n\t\t}\n\t\tthis.#pubsub.publish('error', error);\n\t};\n\n\t#getAnalyticsIfEnabled = () => {\n\t\t// Don't log analytics events if preventOutOfBounds is disabled.\n\t\t// We don't want to log analytics of people within their homes viewing a map.\n\t\treturn !this.#options.preventOutOfBounds\n\t\t\t? { sendWatchPositionDenied: () => {}, updateState: () => {} }\n\t\t\t: this.#mapData.internal.Analytics;\n\t};\n\n\t#handleClickOrHover = (type: 'click' | 'hover') => (event: TEvents['click'] | TEvents['hover']) => {\n\t\tif (event.models == null || event.models.length === 0 || this.dotModel == null) {\n\t\t\treturn;\n\t\t}\n\t\tconst dotModel = event.models.find(m => m.id === this.dotModel?.id);\n\t\tif (dotModel == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#pubsub.publish(type, {\n\t\t\tcoordinate: event.coordinate,\n\t\t});\n\t};\n\n\t#handleClick = this.#handleClickOrHover('click');\n\t#handleHover = this.#handleClickOrHover('hover');\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { JwtPayload } from 'jwt-decode';\nimport { jwtDecode } from 'jwt-decode';\nimport { EARTH_RADIUS_M } from './constants';\nimport { Box2 } from 'three';\nimport type { Box3 } from 'three';\n\nexport function findMapWithElevationClosestToZero<T extends { elevation?: number }>(maps: T[]): T | undefined {\n\tif (maps.length === 0) return;\n\tlet closestMap: T | undefined;\n\tfor (let map of maps) {\n\t\tif (typeof map.elevation !== 'number') {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!closestMap) {\n\t\t\tclosestMap = map;\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof closestMap.elevation !== 'number') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Math.abs(map.elevation) === Math.abs(closestMap.elevation)) {\n\t\t\t// In case we have no 0 value, we want to favour positive values\n\t\t\tclosestMap = map.elevation > closestMap.elevation ? map : closestMap;\n\t\t} else {\n\t\t\tclosestMap = Math.abs(map.elevation) < Math.abs(closestMap.elevation) ? map : closestMap;\n\t\t}\n\t}\n\n\treturn closestMap;\n}\n\n/**\n * Omit properites from object\n */\nexport function omit<T extends Record<string, any>, K extends keyof T>(obj: T, keysToOmit: K[]): Omit<T, K> {\n\tconst result = {} as Omit<T, K>;\n\tconst toOmit = new Set(keysToOmit);\n\tlet key: string;\n\tfor (key in obj) {\n\t\tif (!toOmit.has(key as K)) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function decodeAccessToken(accessToken: string) {\n\tconst decoded: JwtPayload & { capabilities: Record<string, any> } = jwtDecode(accessToken);\n\n\tif (decoded.sub == null) {\n\t\tthrow new Error('Access token is missing sub claim.');\n\t}\n\n\treturn {\n\t\tsub: decoded.sub,\n\t\taud: typeof decoded.aud === 'string' ? [decoded.aud] : decoded.aud ?? [],\n\t\tcapabilities: decoded.capabilities ?? {},\n\t};\n}\n\nexport function toRadians(degrees: number): number {\n\treturn degrees * (Math.PI / 180);\n}\n\nexport function toDegrees(radians: number): number {\n\treturn radians * (180 / Math.PI);\n}\n\nexport function round(value: number, decimals: number): number {\n\tconst factor = Math.pow(10, decimals);\n\n\treturn (Math.sign(value) * Math.round(Math.abs(value) * factor)) / factor;\n}\n\nexport function euclideanModulo(value: number, modulus: number): number {\n\treturn ((value % modulus) + modulus) % modulus;\n}\n\n/**\n * Position from our SDKs may be tuple of longitude and latitude optionally followed by altitude.\n */\ntype Position = [number, number] | [number, number, number?] | number[];\n\n/**\n * Calculates the approximate distance between two geographic coordinates on Earth's surface.\n *\n * This function uses the equirectangular approximation method to compute the distance, which simplifies\n * the math and speeds up calculations, but is less accurate over long distances compared to other methods\n * like the haversine formula.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point1 - The second point's longitude and latitude as [longitude, latitude].\n * @return The approximate distance between the two points in meters.\n */\nexport function haversineDistance([lon1, lat1]: Position, [lon2, lat2]: Position): number {\n\tconst dLat = toRadians(lat2 - lat1);\n\tconst dLon = toRadians(lon2 - lon1);\n\n\tconst startLat = toRadians(lat1);\n\tconst destLat = toRadians(lat2);\n\n\tconst a =\n\t\tMath.sin(dLat / 2) * Math.sin(dLat / 2) +\n\t\tMath.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(startLat) * Math.cos(destLat);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n\treturn EARTH_RADIUS_M * c;\n}\n\n/**\n * Calculates the bearing clockwise from North between two geographic coordinates on Earth's surface.\n * 0 is North, 90 is East, 180 is South, 270 is West.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The forward bearing in degrees from point1 to point2, measured clockwise from true North.\n */\nexport function getForwardBearing([lon1, lat1]: Position, [lon2, lat2]: Position): number {\n\tconst startLat = toRadians(lat1);\n\tconst startLon = toRadians(lon1);\n\tconst destLat = toRadians(lat2);\n\tconst destLon = toRadians(lon2);\n\n\tconst dLon = destLon - startLon;\n\n\tconst y = Math.sin(dLon) * Math.cos(destLat);\n\tconst x = Math.cos(startLat) * Math.sin(destLat) - Math.sin(startLat) * Math.cos(destLat) * Math.cos(dLon);\n\n\t// normalize to 0-360\n\treturn toDegrees((Math.atan2(y, x) + Math.PI * 2) % (Math.PI * 2));\n}\n\n/**\n *\n * Normalizes the start and end rotations to the range 0 to 2 PI and ensures the shortest path for rotation.\n *\n * @param startRotation - The start rotation in radians\n * @param targetRotation - The target rotation in radians\n * @returns Start and end rotations for the tween.\n */\nexport function shortestTweenRotation(startRotation: number, targetRotation: number) {\n\tconst startRotationMod2Pi = euclideanModulo(startRotation, Math.PI * 2);\n\tconst targetRotationMod2Pi = euclideanModulo(targetRotation, Math.PI * 2);\n\tconst delta = targetRotationMod2Pi - startRotationMod2Pi;\n\n\t// If delta > Math.PI rotate 2*PI clockwise\n\t// If delta < -Math.PI rotate 2*PI counterclockwise\n\t// Otherwise delta is already the shortest path\n\tconst endRotation = targetRotationMod2Pi + (delta > Math.PI ? -Math.PI * 2 : delta < -Math.PI ? Math.PI * 2 : 0);\n\n\treturn { start: startRotationMod2Pi, end: endRotation };\n}\n\nexport function isFiniteBox(box: Box2 | Box3) {\n\tif (box instanceof Box2) {\n\t\treturn (\n\t\t\tNumber.isFinite(box.min.x) &&\n\t\t\tNumber.isFinite(box.min.y) &&\n\t\t\tNumber.isFinite(box.max.x) &&\n\t\t\tNumber.isFinite(box.max.y)\n\t\t);\n\t}\n\n\treturn (\n\t\tNumber.isFinite(box.min.x) &&\n\t\tNumber.isFinite(box.min.y) &&\n\t\tNumber.isFinite(box.max.x) &&\n\t\tNumber.isFinite(box.max.y) &&\n\t\tNumber.isFinite(box.min.z) &&\n\t\tNumber.isFinite(box.max.z)\n\t);\n}\n\n// Re-export from separate files to avoid bundling three.js when not needed\nexport { clampWithWarning } from './math-utils';\nexport { arraysEqual } from './array-utils';\n\nexport function isBrowser(): boolean {\n\treturn typeof window !== 'undefined' && window !== null;\n}\n\n/**\n * Calculates the simple Euclidean distance between two geographic coordinates.\n *\n * This treats longitude and latitude as Cartesian coordinates on a flat plane.\n * It's the fastest distance calculation but least accurate for geographic data.\n * Best used for relative distance comparisons rather than actual measurements.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The Euclidean distance between the two points in meters.\n */\nexport function euclideanDistance(point1: Position, point2: Position): number {\n\tconst [lon1, lat1] = point1;\n\tconst [lon2, lat2] = point2;\n\n\tconst dx = toRadians(lon2 - lon1);\n\tconst dy = toRadians(lat2 - lat1);\n\n\treturn Math.sqrt(dx * dx + dy * dy) * EARTH_RADIUS_M;\n}\n\n/**\n * Calculates the approximate distance between two geographic coordinates on Earth's surface.\n *\n * This function uses the equirectangular approximation method to compute the distance, which simplifies\n * the math and speeds up calculations, but is less accurate over long distances compared to other methods\n * like the haversine formula.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The approximate distance between the two points in meters.\n */\nexport function equirectangularDistance(point1: Position, point2: Position): number {\n\tconst [lon1, lat1] = point1.map(deg => toRadians(deg));\n\tconst [lon2, lat2] = point2.map(deg => toRadians(deg));\n\n\tconst deltaLat = lat2 - lat1;\n\tconst deltaLon = lon2 - lon1;\n\n\tconst x = deltaLon * Math.cos((lat1 + lat2) / 2);\n\tconst y = deltaLat;\n\n\treturn Math.sqrt(x * x + y * y) * EARTH_RADIUS_M;\n}\n", "export class InvalidTokenError extends Error {\n}\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\nfunction b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }));\n}\nfunction base64UrlDecode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n try {\n return b64DecodeUnicode(output);\n }\n catch (err) {\n return atob(output);\n }\n}\nexport function jwtDecode(token, options) {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n options || (options = {});\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);\n }\n let decoded;\n try {\n decoded = base64UrlDecode(part);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);\n }\n try {\n return JSON.parse(decoded);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);\n }\n}\n", "export const EARTH_RADIUS_M = 6371008.8;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "import type { BlueDotState } from './types';\n\nexport const POSITION_ANIMATION_DURATION = 1000;\nexport const SCALE_ANIMATION_DURATION = 150;\nexport const ROTATION_ANIMATION_DURATION = 150;\nexport const MIN_BLUEDOT_RADIUS = 0.35;\nexport const BLUEDOT_RADIUS = 10;\nexport const BASE_COLOR = '#2266ff';\nexport const INACTIVE_COLOR = '#808080';\nexport const HEADING_CONE_OPACITY = 0.7;\nexport const ACCURACY_RING_OPACITY = 0.3;\nexport const DEFAULT_BLUEDOT_OPTIONS: BlueDotState = {\n\tradius: BLUEDOT_RADIUS,\n\tcolor: BASE_COLOR,\n\tinactiveColor: INACTIVE_COLOR,\n\theading: {\n\t\tcolor: BASE_COLOR,\n\t\topacity: HEADING_CONE_OPACITY,\n\t\tdisplayWhenInactive: false,\n\t},\n\taccuracyRing: {\n\t\tcolor: BASE_COLOR,\n\t\topacity: ACCURACY_RING_OPACITY,\n\t},\n\ttimeout: 30000,\n\twatchDevicePosition: true,\n\tdebug: false,\n\taccuracyThreshold: 50,\n\tinitialState: 'hidden',\n\tpreventOutOfBounds: true,\n};\n", "import type { MapView, Model, TEvents, TModelUpdateState } from '@mappedin/mappedin-js';\nimport { Coordinate } from '@mappedin/mappedin-js';\nimport { shortestTweenRotation, toDegrees, toRadians } from '@packages/internal/common/utils';\nimport type { Tween } from '@tweenjs/tween.js';\nimport { ROTATION_ANIMATION_DURATION, SCALE_ANIMATION_DURATION } from './constants';\nimport accuracyRingModel from './models/accuracy-ring.gltf';\nimport blueDotModel from './models/blue-dot.gltf';\nimport headingConeModel from './models/heading-cone.gltf';\nimport type { BlueDot } from './blue-dot';\nimport type { GeolocationPositionExtended, ParsedBlueDotPosition } from './types';\nimport { shouldShowAccuracyRing, computeBlueDotScale, shouldShowHeadingCone } from './utils';\n\nexport class BlueDotModelManager {\n\t#mapView: MapView;\n\t#blueDot: BlueDot;\n\t#scale = 1;\n\t#cachedZoomLevel?: number;\n\n\t// animations\n\t#scaleAnimation?: Tween;\n\t#rotationAnimation?: Tween;\n\n\t// models\n\tdot?: Model;\n\taccuracyRing?: Model;\n\theadingCone?: Model;\n\n\tconstructor(mapView: MapView, BlueDot: BlueDot) {\n\t\tthis.#mapView = mapView;\n\t\tthis.#blueDot = BlueDot;\n\t\tthis.#mapView.on('camera-change', this.#updateScale);\n\t}\n\n\tadd(position: ParsedBlueDotPosition) {\n\t\tthis.remove();\n\t\tthis.#updateScale({ zoomLevel: this.#mapView.Camera.zoomLevel });\n\t\t// Order of adding models matters for rendering order\n\t\tconst coordinate = new Coordinate({\n\t\t\tlatitude: position.latitude,\n\t\t\tlongitude: position.longitude,\n\t\t});\n\t\tthis.accuracyRing = this.#mapView.Models.add(coordinate, accuracyRingModel, {\n\t\t\tvisible: false,\n\t\t\tscale: position.accuracy ?? 0,\n\t\t\trotation: [0, 0, 0],\n\t\t\tcolor: this.options.accuracyRing.color,\n\t\t\topacity: this.options.accuracyRing.opacity,\n\t\t\tvisibleThroughGeometry: true,\n\t\t});\n\t\tthis.headingCone = this.#mapView.Models.add(coordinate, headingConeModel, {\n\t\t\tvisible: false,\n\t\t\tscale: this.#scale,\n\t\t\trotation: [0, 0, 0],\n\t\t\tcolor: this.#blueDot.status === 'inactive' ? this.options.inactiveColor : this.options.heading.color,\n\t\t\topacity: this.options.heading.opacity,\n\t\t\tvisibleThroughGeometry: true,\n\t\t});\n\t\tthis.dot = this.#mapView.Models.add(coordinate, blueDotModel, {\n\t\t\tvisible: false,\n\t\t\tscale: this.#scale,\n\t\t\trotation: [0, 0, 0],\n\t\t\tinteractive: true,\n\t\t\tvisibleThroughGeometry: true,\n\t\t\tmaterial: {\n\t\t\t\tInner: {\n\t\t\t\t\tcolor: this.#blueDot.status === 'inactive' ? this.options.inactiveColor : this.options.color,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\tget options() {\n\t\treturn this.#blueDot.getState();\n\t}\n\n\tgetPosition(): Coordinate | undefined {\n\t\tif (this.dot == null) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.#mapView.getState(this.dot).position;\n\t}\n\n\tsetPosition(value: Coordinate) {\n\t\tif (this.dot == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.dot) {\n\t\t\tthis.#mapView.updateState(this.dot, { visible: true, position: value });\n\t\t}\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, { position: value });\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.updateState(this.headingCone, { position: value });\n\t\t}\n\t}\n\n\t#accuracy: GeolocationPositionExtended['coords']['accuracy'] | undefined;\n\tsetAccuracy(value: GeolocationPositionExtended['coords']['accuracy'] | undefined) {\n\t\tif (this.accuracyRing == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#accuracy = value;\n\t\tconst accuracyRingState = this.#mapView.getState(this.accuracyRing);\n\t\tif (accuracyRingState == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (value != null) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\tvisible: shouldShowAccuracyRing(this.#blueDot.status, this.#accuracy),\n\t\t\t});\n\t\t\tif (this.#scaleAnimation) {\n\t\t\t\tthis.#scaleAnimation.stop();\n\t\t\t}\n\t\t\tthis.#mapView\n\t\t\t\t.tween({ scale: accuracyRingState.scale[0] })\n\t\t\t\t.to({ scale: value / 2 }, SCALE_ANIMATION_DURATION)\n\t\t\t\t.onUpdate(({ scale }) => {\n\t\t\t\t\tif (this.accuracyRing == null) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tscale: [scale, scale, 1],\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t} else {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\tvisible: false,\n\t\t\t});\n\t\t}\n\t}\n\n\t#heading: GeolocationPositionExtended['coords']['heading'] | undefined;\n\tsetHeading(value: GeolocationPositionExtended['coords']['heading'] | undefined) {\n\t\tif (this.headingCone == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#heading = value;\n\t\tconst headingConeState = this.#mapView.getState(this.headingCone);\n\t\tif (headingConeState == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (value != null) {\n\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\tvisible: shouldShowHeadingCone(this.#blueDot.status, this.#heading, this.options.heading.displayWhenInactive),\n\t\t\t});\n\t\t\tif (this.#rotationAnimation) {\n\t\t\t\tthis.#rotationAnimation.stop();\n\t\t\t}\n\n\t\t\tconst currentZRad = headingConeState.rotation[2] != null ? toRadians(headingConeState.rotation[2]) : 0;\n\t\t\tconst targetZRad = -toRadians(value);\n\t\t\tconst { start, end } = shortestTweenRotation(currentZRad, targetZRad);\n\t\t\tthis.#rotationAnimation = this.#mapView\n\t\t\t\t.tween({ rotation: toDegrees(start) })\n\t\t\t\t.to({ rotation: toDegrees(end) }, ROTATION_ANIMATION_DURATION)\n\t\t\t\t.onUpdate(({ rotation }) => {\n\t\t\t\t\tif (this.headingCone == null) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\t// updateState expects degrees; preserve base X/Y and apply absolute Z in degrees\n\t\t\t\t\t\trotation: [0, 0, rotation],\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t} else {\n\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\tvisible: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tsetAltitude(value: number | undefined) {\n\t\tif (this.dot == null) {\n\t\t\treturn;\n\t\t}\n\t\tconst update: TModelUpdateState = {\n\t\t\tverticalOffset: value,\n\t\t};\n\t\tthis.#mapView.updateState(this.dot, update);\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, update);\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.updateState(this.headingCone, update);\n\t\t}\n\t}\n\n\t/**\n\t * Updates appearance of the BlueDot models based on a given status.\n\t */\n\tupdateAppearance() {\n\t\tswitch (this.#blueDot.status) {\n\t\t\tcase 'hidden':\n\t\t\tcase 'disabled':\n\t\t\t\tif (this.dot) {\n\t\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.accuracyRing) {\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.headingCone) {\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'active':\n\t\t\tcase 'inactive':\n\t\t\t\tif (this.dot) {\n\t\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\t\tvisible: true,\n\t\t\t\t\t\tmaterial: {\n\t\t\t\t\t\t\tInner: {\n\t\t\t\t\t\t\t\tcolor: this.#blueDot.status === 'active' ? this.options.color : this.options.inactiveColor,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.accuracyRing) {\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tvisible: shouldShowAccuracyRing(this.#blueDot.status, this.#accuracy),\n\t\t\t\t\t\t// Is there a use case where we ever want an inactive color accuracy ring?\n\t\t\t\t\t\t// color: state === 'active' ? this.#options.accuracyRing.color : this.#options.inactiveColor,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.headingCone) {\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\tvisible: shouldShowHeadingCone(\n\t\t\t\t\t\t\tthis.#blueDot.status,\n\t\t\t\t\t\t\tthis.#heading,\n\t\t\t\t\t\t\tthis.options.heading.displayWhenInactive,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcolor: this.#blueDot.status === 'active' ? this.options.heading.color : this.options.inactiveColor,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tremove() {\n\t\tif (this.dot) {\n\t\t\tthis.#mapView.Models.remove(this.dot);\n\t\t\tthis.dot = undefined;\n\t\t}\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.Models.remove(this.accuracyRing);\n\t\t\tthis.accuracyRing = undefined;\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.Models.remove(this.headingCone);\n\t\t\tthis.headingCone = undefined;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.remove();\n\t\tthis.#mapView.off('camera-change', this.#updateScale);\n\t}\n\n\t#updateScale = ({ zoomLevel }: Pick<TEvents['camera-change'], 'zoomLevel'>) => {\n\t\t// We only want to update the scale if the zoom level of the camera changes.\n\t\t// Our camera can change zoom levels by a tiny fraction even when a pan or rotation action is performed,\n\t\t// so we round the zoom level to 5 decimals to avoid unnecessary updates.\n\t\tconst currentZoomLevel = Math.round(zoomLevel * 100000);\n\t\tif (currentZoomLevel !== this.#cachedZoomLevel) {\n\t\t\tthis.#cachedZoomLevel = currentZoomLevel;\n\t\t\tconst metersPerPixel = this.#mapView.getMetersPerPixel();\n\t\t\t// Compute scale from desired pixel radius and meters-per-pixel\n\t\t\tthis.#scale = computeBlueDotScale(this.options.radius, metersPerPixel);\n\t\t\tif (this.dot) {\n\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\tscale: [this.#scale, this.#scale, this.#scale],\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (this.headingCone) {\n\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\tscale: [this.#scale, this.#scale, 1],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[0]}],\"scene\":0,\"nodes\":[{\"mesh\":0}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2352,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":4704,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":6272,\"byteLength\":768,\"target\":34963}],\"buffers\":[{\"byteLength\":7040,\"uri\":\"data:application/octet-stream;base64,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AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgD8AAAA9AACAPwAAgD0AAIA/AADAPQAAgD8AAAA+AACAPwAAID4AAIA/AABAPgAAgD8AAGA+AACAPwAAgD4AAIA/AACQPgAAgD8AAKA+AACAPwAAsD4AAIA/AADAPgAAgD8AANA+AACAPwAA4D4AAIA/AADwPgAAgD8AAAA/AACAPwAACD8AAIA/AAAQPwAAgD8AABg/AACAPwAAID8AAIA/AAAoPwAAgD8AADA/AACAPwAAOD8AAIA/AABAPwAAgD8AAEg/AACAPwAAUD8AAIA/AABYPwAAgD8AAGA/AACAPwAAaD8AAIA/AABwPwAAgD8AAHg/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAA9AAAAAAAAgD0AAAAAAADAPQAAAAAAAAA+AAAAAAAAID4AAAAAAABAPgAAAAAAAGA+AAAAAAAAgD4AAAAAAACQPgAAAAAAAKA+AAAAAAAAsD4AAAAAAADAPgAAAAAAANA+AAAAAAAA4D4AAAAAAADwPgAAAAAAAAA/AAAAAAAACD8AAAAAAAAQPwAAAAAAABg/AAAAAAAAID8AAAAAAAAoPwAAAAAAADA/AAAAAAAAOD8AAAAAAABAPwAAAAAAAEg/AAAAAAAAUD8AAAAAAABYPwAAAAAAAGA/AAAAAAAAaD8AAAAAAABwPwAAAAAAAHg/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAgD8AAAA/X4p9P7j4GD+vQXY/xfswP5ltaj/tHEc/eoJaP3qCWj/tHEc/mW1qP8X7MD+vQXY/uPgYP1+KfT8AAAA/AACAP5AOzj5fin0/dQiePq9Bdj9MjGM+mW1qPxr2FT56glo/O5OsPe0cRz8M5Rs9xfswPzBoHTy4+Bg/AAAAAAAAAD8waB08kA7OPgzlGz11CJ4+O5OsPUyMYz4a9hU+GvYVPkyMYz47k6w9dQiePgzlGz2QDs4+MGgdPAAAAD8AAAAAuPgYPzBoHTzF+zA/DOUbPe0cRz87k6w9eoJaPxr2FT6ZbWo/TIxjPq9Bdj91CJ4+X4p9P5AOzj4AAIA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAIA/AAAAP1+KfT+QDs4+r0F2P3UInj6ZbWo/TIxjPnqCWj8a9hU+7RxHPzuTrD3F+zA/DOUbPbj4GD8waB08AAAAPwAAAACQDs4+MGgdPHUInj4M5Rs9TIxjPjuTrD0a9hU+GvYVPjuTrD1MjGM+DOUbPXUInj4waB08kA7OPgAAAAAAAAA/MGgdPLj4GD8M5Rs9xfswPzuTrD3tHEc/GvYVPnqCWj9MjGM+mW1qP3UInj6vQXY/kA7OPl+KfT8AAAA/AACAP7j4GD9fin0/xfswP69Bdj/tHEc/mW1qP3qCWj96glo/mW1qP+0cRz+vQXY/xfswP1+KfT+4+Bg/AACAPwAAAD8AACEAAQAhACIAAQABACIAAgAiACMAAgACACMAAwAjACQAAwADACQABAAkACUABAAEACUABQAlACYABQAFACYABgAmACcABgAGACcABwAnACgABwAHACgACAAoACkACAAIACkACQApACoACQAJACoACgAqACsACgAKACsACwArACwACwALACwADAAsAC0ADAAMAC0ADQAtAC4ADQANAC4ADgAuAC8ADgAOAC8ADwAvADAADwAPADAAEAAwADEAEAAQADEAEQAxADIAEQARADIAEgAyADMAEgASADMAEwAzADQAEwATADQAFAA0ADUAFAAUADUAFQA1ADYAFQAVADYAFgA2ADcAFgAWADcAFwA3ADgAFwAXADgAGAA4ADkAGAAYADkAGQA5ADoAGQAZADoAGgA6ADsAGgAaADsAGwA7ADwAGwAbADwAHAA8AD0AHAAcAD0AHQA9AD4AHQAdAD4AHgA+AD8AHgAeAD8AHwA/AEAAHwAfAEAAIABAAEEAIABiAGMAQgBjAGQAQwBkAGUARABlAGYARQBmAGcARgBnAGgARwBoAGkASABpAGoASQBqAGsASgBrAGwASwBsAG0ATABtAG4ATQBuAG8ATgBvAHAATwBwAHEAUABxAHIAUQByAHMAUgBzAHQAUwB0AHUAVAB1AHYAVQB2AHcAVgB3AHgAVwB4AHkAWAB5AHoAWQB6AHsAWgB7AHwAWwB8AH0AXAB9AH4AXQB+AH8AXgB/AIAAXwCAAIEAYACBAIIAYQCkAKMAgwClAKQAhACmAKUAhQCnAKYAhgCoAKcAhwCpAKgAiACqAKkAiQCrAKoAigCsAKsAiwCtAKwAjACuAK0AjQCvAK4AjgCwAK8AjwCxALAAkACyALEAkQCzALIAkgC0ALMAkwC1ALQAlAC2ALUAlQC3ALYAlgC4ALcAlwC5ALgAmAC6ALkAmQC7ALoAmgC8ALsAmwC9ALwAnAC+AL0AnQC/AL4AngDAAL8AnwDBAMAAoADCAMEAoQDDAMIAogA=\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":196,\"max\":[1,1,0.02500000037252903],\"min\":[-1,-1,-0.02500000037252903],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":2,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":3,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"AccuracyRing\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"NORMAL\":1,\"TEXCOORD_0\":2},\"indices\":3,\"material\":0}]}]}", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[2]}],\"scene\":0,\"nodes\":[{\"mesh\":0},{\"mesh\":1},{\"children\":[0,1]}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2352,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":4704,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":6272,\"byteLength\":768,\"target\":34963},{\"buffer\":0,\"byteOffset\":7040,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":9392,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":11744,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":13312,\"byteLength\":768,\"target\":34963}],\"buffers\":[{\"byteLength\":14080,\"uri\":\"data:application/octet-stream;base64,AAAAADMzs74pXI89O9eLPbnBr74pXI89XCcJPimPpb4pXI89yx1HPtb/lL4pXI89VG19PlRtfb4pXI891v+UPssdR74pXI89KY+lPlwnCb4pXI89ucGvPjvXi70pXI89MzOzPmH6e6MpXI89ucGvPjvXiz0pXI89KY+lPlwnCT4pXI891v+UPssdRz4pXI89VG19PlRtfT4pXI89yx1HPtb/lD4pXI89XCcJPimPpT4pXI89O9eLPbnBrz4pXI89RatFJDMzsz4pXI89O9eLvbnBrz4pXI89XCcJvimPpT4pXI89yx1Hvtb/lD4pXI89VG19vlRtfT4pXI891v+UvssdRz4pXI89KY+lvlwnCT4pXI89ucGvvjvXiz0pXI89MzOzvvkrpiQpXI89ucGvvjvXi70pXI89KY+lvlwnCb4pXI891v+UvssdR74pXI89VG19vlRtfb4pXI89yx1Hvtb/lL4pXI89XCcJvimPpb4pXI89O9eLvbnBr74pXI89RavFpDMzs74pXI89AAAAADMzs74E1yOvO9eLPbnBr74E1yOvXCcJPimPpb4F1yOvyx1HPtb/lL4G1yOvVG19PlRtfb4G1yOv1v+UPssdR74H1yOvKY+lPlwnCb4I1yOvucGvPjvXi70J1yOvMzOzPq2sBqQK1yOvucGvPjvXiz0L1yOvKY+lPlwnCT4M1yOv1v+UPssdRz4N1yOvVG19PlRtfT4O1yOvyx1HPtb/lD4O1yOvXCcJPimPpT4P1yOvO9eLPbnBrz4Q1yOvRatFJDMzsz4Q1yOvO9eLvbnBrz4Q1yOvXCcJvimPpT4P1yOvyx1Hvtb/lD4O1yOvVG19vlRtfT4O1yOv1v+UvssdRz4N1yOvKY+lvlwnCT4M1yOvucGvvjvXiz0L1yOvMzOzvu9UgiQK1yOvucGvvjvXi70J1yOvKY+lvlwnCb4I1yOv1v+UvssdR74H1yOvVG19vlRtfb4G1yOvyx1Hvtb/lL4G1yOvXCcJvimPpb4F1yOvO9eLvbnBr74E1yOvRavFpDMzs74E1yOvAAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAADMzs74pXI89O9eLPbnBr74pXI89XCcJPimPpb4pXI89yx1HPtb/lL4pXI89VG19PlRtfb4pXI891v+UPssdR74pXI89KY+lPlwnCb4pXI89ucGvPjvXi70pXI89MzOzPmH6e6MpXI89ucGvPjvXiz0pXI89KY+lPlwnCT4pXI891v+UPssdRz4pXI89VG19PlRtfT4pXI89yx1HPtb/lD4pXI89XCcJPimPpT4pXI89O9eLPbnBrz4pXI89RatFJDMzsz4pXI89O9eLvbnBrz4pXI89XCcJvimPpT4pXI89yx1Hvtb/lD4pXI89VG19vlRtfT4pXI891v+UvssdRz4pXI89KY+lvlwnCT4pXI89ucGvvjvXiz0pXI89MzOzvvkrpiQpXI89ucGvvjvXi70pXI89KY+lvlwnCb4pXI891v+UvssdR74pXI89VG19vlRtfb4pXI89yx1Hvtb/lL4pXI89XCcJvimPpb4pXI89O9eLvbnBr74pXI89RavFpDMzs74pXI89AAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOv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AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgD8AAAA9AACAPwAAgD0AAIA/AADAPQAAgD8AAAA+AACAPwAAID4AAIA/AABAPgAAgD8AAGA+AACAPwAAgD4AAIA/AACQPgAAgD8AAKA+AACAPwAAsD4AAIA/AADAPgAAgD8AANA+AACAPwAA4D4AAIA/AADwPgAAgD8AAAA/AACAPwAACD8AAIA/AAAQPwAAgD8AABg/AACAPwAAID8AAIA/AAAoPwAAgD8AADA/AACAPwAAOD8AAIA/AABAPwAAgD8AAEg/AACAPwAAUD8AAIA/AABYPwAAgD8AAGA/AACAPwAAaD8AAIA/AABwPwAAgD8AAHg/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAA9AAAAAAAAgD0AAAAAAADAPQAAAAAAAAA+AAAAAAAAID4AAAAAAABAPgAAAAAAAGA+AAAAAAAAgD4AAAAAAACQPgAAAAAAAKA+AAAAAAAAsD4AAAAAAADAPgAAAAAAANA+AAAAAAAA4D4AAAAAAADwPgAAAAAAAAA/AAAAAAAACD8AAAAAAAAQPwAAAAAAABg/AAAAAAAAID8AAAAAAAAoPwAAAAAAADA/AAAAAAAAOD8AAAAAAABAPwAAAAAAAEg/AAAAAAAAUD8AAAAAAABYPwAAAAAAAGA/AAAAAAAAaD8AAAAAAABwPwAAAAAAAHg/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/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CtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAAKVyPvpqZmT3Fvl89+pqMvpqZmT0scts9h3KEvpqZmT0ISx8+I2ZuvpqZmT3dvUo+3b1KvpqZmT0jZm4+CEsfvpqZmT2HcoQ+LHLbvZqZmT36mow+xb5fvZqZmT0pXI8+LeWTo5qZmT36mow+xb5fPZqZmT2HcoQ+LHLbPZqZmT0jZm4+CEsfPpqZmT3dvUo+3b1KPpqZmT0ISx8+I2ZuPpqZmT0scts9h3KEPpqZmT3Fvl89+pqMPpqZmT2eIh4kKVyPPpqZmT3Fvl+9+pqMPpqZmT0sctu9h3KEPpqZmT0ISx++I2ZuPpqZmT3dvUq+3b1KPpqZmT0jZm6+CEsfPpqZmT2HcoS+LHLbPZqZmT36moy+xb5fPZqZmT0pXI++pVJyJJqZmT36moy+xb5fvZqZmT2HcoS+LHLbvZqZmT0jZm6+CEsfvpqZmT3dvUq+3b1KvpqZmT0ISx++I2ZuvpqZmT0sctu9h3KEvpqZmT3Fvl+9+pqMvpqZmT2eIp6kKVyPvpqZmT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAA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AACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAA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MQAQABAAMQARADEAMgARABEAMgASADIAMwASABIAMwATADMANAATABMANAAUADQANQAUABQANQAVADUANgAVABUANgAWADYANwAWABYANwAXADcAOAAXABcAOAAYADgAOQAYABgAOQAZADkAOgAZABkAOgAaADoAOwAaABoAOwAbADsAPAAbABsAPAAcADwAPQAcABwAPQAdAD0APgAdAB0APgAeAD4APwAeAB4APwAfAD8AQAAfAB8AQAAgAEAAQQAgAGIAYwBCAGMAZABDAGQAZQBEAGUAZgBFAGYAZwBGAGcAaABHAGgAaQBIAGkAagBJAGoAawBKAGsAbABLAGwAbQBMAG0AbgBNAG4AbwBOAG8AcABPAHAAcQBQAHEAcgBRAHIAcwBSAHMAdABTAHQAdQBUAHUAdgBVAHYAdwBWAHcAeABXAHgAeQBYAHkAegBZAHoAewBaAHsAfABbAHwAfQBcAH0AfgBdAH4AfwBeAH8AgABfAIAAgQBgAIEAggBhAKQAowCDAKUApACEAKYApQCFAKcApgCGAKgApwCHAKkAqACIAKoAqQCJAKsAqgCKAKwAqwCLAK0ArACMAK4ArQCNAK8ArgCOALAArwCPALEAsACQALIAsQCRALMAsgCSALQAswCTALUAtACUALYAtQCVALcAtgCWALgAtwCXALkAuACYALoAuQCZALsAugCaALwAuwCbAL0AvACcAL4AvQCdAL8AvgCeAMAAvwCfAMEAwACgAMIAwQChAMMAwgCiAA==\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":196,\"max\":[0.3499999940395355,0.3499999940395355,0.07000000029802322],\"min\":[-0.3499999940395355,-0.3499999940395355,-1.4901169187453434e-10],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":2,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":3,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"},{\"bufferView\":4,\"componentType\":5126,\"count\":196,\"max\":[0.2800000011920929,0.2800000011920929,0.07500000298023224],\"min\":[-0.2800000011920929,-0.2800000011920929,0.06499999761581421],\"type\":\"VEC3\"},{\"bufferView\":5,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":6,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":7,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.913098651791473,0.913098651791473,0.913098651791473,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"Border\"},{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"Inner\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"NORMAL\":1,\"TEXCOORD_0\":2},\"indices\":3,\"material\":0}]},{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":4,\"NORMAL\":5,\"TEXCOORD_0\":6},\"indices\":7,\"material\":1}]}]}", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[0]}],\"scene\":0,\"nodes\":[{\"mesh\":0}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2880,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2880,\"byteLength\":1920,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":4800,\"byteLength\":2880,\"target\":34962,\"byteStride\":12}],\"buffers\":[{\"byteLength\":7680,\"uri\":\"data:application/octet-stream;base64,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AACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/ARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAACAXzAgviTZfL8AAACAXzAgviTZfL8AAACAcHHovgEZZL8AAAAAcHHovgEZZL8AAAAAcHHovgEZZL8AAAAAcHHovgEZZL8AAACAcHHovgEZZL8AAACAcHHovgEZZL8AAACA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAACA8wQ1v/MENb8AAACA8wQ1v/MENb8AAACAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAACAARlkv3Bx6L4AAACAARlkv3Bx6L4AAACAJNl8v18wIL4AAAAAJNl8v18wIL4AAAAAJNl8v18wIL4AAAAAJNl8v18wIL4AAACAJNl8v18wIL4AAACAJNl8v18wIL4AAACAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAACA6kZ3v++DhL4AAACA6kZ3v++DhL4AAACAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAA\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":240,\"max\":[0.572234570980072,1.4460784196853638,0.10000000149011612],\"min\":[-0.7123466730117798,0,0],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":240,\"max\":[0,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":2,\"componentType\":5126,\"count\":240,\"max\":[0.9876883029937744,0.9996573328971863,1],\"min\":[-0.9876883029937744,-0.9876883029937744,-1],\"type\":\"VEC3\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1,\"baseColorTexture\":{\"index\":0,\"texCoord\":0}},\"alphaMode\":\"BLEND\",\"name\":\"HeadingCone\"}],\"textures\":[{\"sampler\":0,\"source\":0}],\"samplers\":[{\"magFilter\":9729,\"minFilter\":9729,\"wrapS\":33071,\"wrapT\":33071}],\"images\":[{\"mimeType\":\"image/png\",\"uri\":\"data:image/png;base64,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\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"TEXCOORD_0\":1,\"NORMAL\":2},\"material\":0}]}]}", "import { haversineDistance } from '@packages/internal/common/utils';\nimport type {\n\tBlueDotPositionUpdateWithFloor,\n\tBlueDotState,\n\tBlueDotStatus,\n\tBlueDotUpdateState,\n\tGeolocationPositionExtended,\n} from './types';\nimport { MIN_BLUEDOT_RADIUS } from './constants';\n\nexport function deepMergeState(existing: BlueDotState, update?: BlueDotUpdateState): BlueDotState {\n\tif (update == null) {\n\t\treturn existing;\n\t}\n\n\tconst result: BlueDotState = { ...existing };\n\n\tfor (const key in update) {\n\t\tconst value = update[key as keyof BlueDotUpdateState];\n\t\tif (value !== undefined && key !== 'accuracyRing' && key !== 'heading') {\n\t\t\t(result as any)[key] = value;\n\t\t}\n\t}\n\n\tif (update.accuracyRing != null) {\n\t\tresult.accuracyRing = { ...existing.accuracyRing };\n\t\tfor (const key in update.accuracyRing) {\n\t\t\tconst value = update.accuracyRing[key as keyof typeof update.accuracyRing];\n\t\t\tif (value !== undefined) {\n\t\t\t\t(result.accuracyRing as any)[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (update.heading != null) {\n\t\tresult.heading = { ...existing.heading };\n\t\tfor (const key in update.heading) {\n\t\t\tconst value = update.heading[key as keyof typeof update.heading];\n\t\t\tif (value !== undefined) {\n\t\t\t\t(result.heading as any)[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Finds the intersection of a geographic line segment and a point.\n *\n * @param start - The start coordinate of the line segment.\n * @param end - The end coordinate of the line segment.\n * @param position - The position to check for intersection with the line segment.\n */\nexport function getPointLineIntersection(\n\t[startLongitude, startLatitude]: number[],\n\t[endLongitude, endLatitude]: number[],\n\t[positionLongitude, positionLatitude]: number[],\n) {\n\tconst dx = endLongitude - startLongitude;\n\tconst dy = endLatitude - startLatitude;\n\tconst segmentLengthSquared = dx ** 2 + dy ** 2;\n\n\tif (segmentLengthSquared === 0) {\n\t\t// the segment is a point, so no intersection\n\t\treturn;\n\t}\n\n\t// calculate the proportion along the segment (0 to 1) that the position is closest to\n\tconst proportion =\n\t\t((positionLongitude - startLongitude) * dx + (positionLatitude - startLatitude) * dy) / segmentLengthSquared;\n\n\t// project the intersection point onto the segment\n\tlet intersection: [number, number];\n\tif (proportion <= 0) {\n\t\tintersection = [startLongitude, startLatitude];\n\t} else if (proportion >= 1) {\n\t\tintersection = [endLongitude, endLatitude];\n\t} else {\n\t\tintersection = [startLongitude + proportion * dx, startLatitude + proportion * dy];\n\t}\n\n\t// calculate the distance from the position to the intersection\n\tconst distance = haversineDistance([positionLongitude, positionLatitude], intersection);\n\n\treturn {\n\t\tproportion: Math.max(0, Math.min(1, proportion)),\n\t\tintersection,\n\t\tdistance,\n\t};\n}\n\n/**\n * Finds the nearest segment of two coordinates on a path which the BlueDot position is closest to.\n *\n * @param pathCoordinates - The coordinates of the path to check.\n * @param position - The position of the BlueDot.\n */\nexport function findBlueDotOnPath(pathCoordinates: number[][], position: number[]) {\n\tif (pathCoordinates == null || pathCoordinates.length < 2) {\n\t\treturn;\n\t}\n\n\t// smallest distance found so far\n\tlet minDistance = Number.MAX_SAFE_INTEGER;\n\t// lon/lat of the intersection point\n\tlet nearestIntersection: [number, number] | undefined;\n\t// index of the first coordinate of the segment\n\tlet nearestSegmentIndex = 0;\n\t// how far along the segment the BlueDot is\n\tlet nearestProportion = 0;\n\n\t// check each segment of the path -- path should be simplified ahead of time\n\tfor (let i = 0; i < pathCoordinates.length - 1; i++) {\n\t\tconst start = pathCoordinates[i];\n\t\tconst end = pathCoordinates[i + 1];\n\n\t\tconst pointOnLine = getPointLineIntersection(start, end, position);\n\n\t\tif (pointOnLine == null) continue;\n\n\t\tif (pointOnLine.distance < minDistance) {\n\t\t\tminDistance = pointOnLine.distance;\n\t\t\tnearestIntersection = pointOnLine.intersection;\n\t\t\tnearestSegmentIndex = i;\n\t\t\tnearestProportion = pointOnLine.proportion;\n\t\t}\n\t}\n\n\tif (!nearestIntersection) {\n\t\treturn;\n\t}\n\n\treturn {\n\t\tintersection: nearestIntersection,\n\t\tdistance: minDistance,\n\t\tsegmentIndex: nearestSegmentIndex,\n\t\tproportion: nearestProportion,\n\t};\n}\n\nexport function getPositionWithOverrides(\n\tupdate: BlueDotPositionUpdateWithFloor | undefined,\n\toverrides: BlueDotPositionUpdateWithFloor | undefined,\n) {\n\tif (overrides == null) {\n\t\treturn update;\n\t}\n\n\tconst position: BlueDotPositionUpdateWithFloor = {\n\t\tlatitude: update?.latitude,\n\t\tlongitude: update?.longitude,\n\t\taccuracy: update?.accuracy,\n\t\tfloor: update?.floor,\n\t\theading: update?.heading,\n\t\ttimestamp: update?.timestamp,\n\t};\n\tif ('latitude' in overrides) {\n\t\tposition.latitude =\n\t\t\toverrides?.latitude == null || overrides.latitude === 'device' ? update?.latitude : overrides.latitude;\n\t}\n\tif ('longitude' in overrides) {\n\t\tposition.longitude =\n\t\t\toverrides.longitude == null || overrides.longitude === 'device' ? update?.longitude : overrides.longitude;\n\t}\n\tif ('accuracy' in overrides) {\n\t\tposition.accuracy = overrides.accuracy === 'device' ? update?.accuracy : overrides.accuracy;\n\t}\n\tif ('floor' in overrides) {\n\t\tposition.floor = overrides.floor === 'device' ? update?.floor : overrides.floor;\n\t}\n\tif ('heading' in overrides) {\n\t\tposition.heading = overrides.heading === 'device' ? update?.heading : overrides.heading;\n\t}\n\tif ('timestamp' in overrides) {\n\t\tposition.timestamp = overrides.timestamp;\n\t}\n\n\treturn position;\n}\n\n/**\n * Compute whether a position is within circular pan bounds.\n * @param positionLongitude The longitude to test\n * @param positionLatitude The latitude to test\n * @param radius The radius in meters\n * @param center The center coordinate\n * @returns True if within bounds, false otherwise\n */\nexport function isWithinPanBounds(\n\t{ longitude: positionLongitude, latitude: positionLatitude }: { longitude: number; latitude: number },\n\t{ radius, center }: { radius: number; center: { longitude: number; latitude: number } },\n): boolean {\n\tconst distance = haversineDistance([positionLongitude, positionLatitude], [center.longitude, center.latitude]);\n\n\treturn distance <= radius;\n}\n\n/**\n * Compute BlueDot model scale from desired pixel radius and current meters-per-pixel.\n * Ensures a minimum on-map size using MIN_BLUEDOT_RADIUS.\n * @param radius Desired BlueDot radius in pixels\n * @param metersPerPixel Current meters-per-pixel value\n */\nexport function computeBlueDotScale(radius: number, metersPerPixel: number): number {\n\tconst scale = radius / (MIN_BLUEDOT_RADIUS / metersPerPixel);\n\n\treturn Math.max(scale, 1);\n}\n\n/**\n * Ease-out cubic function used for smooth transitions.\n * @example\n * ```ts\n * const eased = easeOutCubic(0.5);\n * ```\n */\nexport function easeOutCubic(t: number): number {\n\treturn 1 - Math.pow(1 - t, 3);\n}\n\n/**\n * Interpolate altitude between a start altitude and target altitude using time-based easing.\n * @param now Current timestamp (ms)\n * @param startTime Transition start timestamp (ms)\n * @param duration Transition duration (ms)\n * @param startAltitude Altitude at the start of the transition\n * @param targetAltitude Current target altitude to reach\n * @returns The interpolated altitude and completion flag\n */\nexport function interpolateAltitude(\n\tnow: number,\n\tstartTime: number | undefined,\n\tduration: number,\n\tstartAltitude: number | undefined,\n\ttargetAltitude: number,\n): { altitude: number; done: boolean } {\n\tif (startTime == null || startAltitude == null) {\n\t\treturn { altitude: targetAltitude, done: true };\n\t}\n\n\tconst elapsed = now - startTime;\n\tconst progress = Math.min(elapsed / duration, 1);\n\n\tif (progress < 1) {\n\t\tconst eased = easeOutCubic(progress);\n\t\tconst altitude = startAltitude + (targetAltitude - startAltitude) * eased;\n\n\t\treturn { altitude, done: false };\n\t}\n\n\treturn { altitude: targetAltitude, done: true };\n}\n\nexport function shouldShowHeadingCone(\n\tstate: BlueDotStatus,\n\theading: GeolocationPositionExtended['coords']['heading'] | undefined,\n\tdisplayWhenInactive: boolean,\n) {\n\treturn heading != null && (state === 'active' || (state === 'inactive' && displayWhenInactive));\n}\n\nexport function shouldShowAccuracyRing(\n\tstate: BlueDotStatus,\n\taccuracy: GeolocationPositionExtended['coords']['accuracy'] | undefined,\n): boolean {\n\treturn state === 'active' && accuracy != null;\n}\n", "import z from 'zod';\n\nexport const geolocationPositionSchema = z.object({\n\tcoords: z.object({\n\t\tlatitude: z.number(),\n\t\tlongitude: z.number(),\n\t\taccuracy: z.number(),\n\t\taltitude: z.number().optional().nullable(),\n\t\taltitudeAccuracy: z.number().optional().nullable(),\n\t\theading: z.number().optional().nullable(),\n\t\tspeed: z.number().optional().nullable(),\n\t\tfloorLevel: z.number().optional().nullable(),\n\t}),\n\ttimestamp: z.number(),\n});\n\nexport const positionSchema = z.object({\n\tlatitude: z.number(),\n\tlongitude: z.number(),\n\tfloor: z.any().optional(),\n\taccuracy: z.number().optional(),\n\theading: z.number().optional().nullable(), // heading can be nullable due to the Geolocation API\n\ttimestamp: z.number().optional(),\n});\n", "import type { StateMachine } from './types';\n\nexport const stateMachine: StateMachine = {\n\thidden: {\n\t\tactions: {\n\t\t\tenable: 'hidden',\n\t\t\terror: 'hidden',\n\t\t\t'position-update': 'active',\n\t\t\tinitialize: 'inactive',\n\t\t\tdisable: 'disabled',\n\t\t\ttimeout: 'hidden',\n\t\t},\n\t},\n\tactive: {\n\t\tactions: {\n\t\t\tenable: 'active',\n\t\t\tdisable: 'disabled',\n\t\t\t'position-update': 'active',\n\t\t\terror: 'inactive',\n\t\t\ttimeout: 'inactive',\n\t\t},\n\t},\n\tinactive: {\n\t\tactions: {\n\t\t\tenable: 'inactive',\n\t\t\tdisable: 'disabled',\n\t\t\t'position-update': 'active',\n\t\t\terror: 'inactive',\n\t\t\ttimeout: 'inactive',\n\t\t},\n\t},\n\tdisabled: {\n\t\tactions: {\n\t\t\tenable: 'hidden',\n\t\t\tdisable: 'disabled',\n\t\t},\n\t},\n};\n"],
4
+ "sourcesContent": ["{\"env\":{\"npm_package_version\":\"6.0.1-beta.60\"}}", "/*\n (c) 2017, Vladimir Agafonkin\n Simplify.js, a high-performance JS polyline simplification library\n mourner.github.io/simplify-js\n*/\n\n(function () { 'use strict';\n\n// to suit your point format, run search/replace for '.x' and '.y';\n// for 3D version, see 3d branch (configurability would draw significant performance overhead)\n\n// square distance between 2 points\nfunction getSqDist(p1, p2) {\n\n var dx = p1.x - p2.x,\n dy = p1.y - p2.y;\n\n return dx * dx + dy * dy;\n}\n\n// square distance from a point to a segment\nfunction getSqSegDist(p, p1, p2) {\n\n var x = p1.x,\n y = p1.y,\n dx = p2.x - x,\n dy = p2.y - y;\n\n if (dx !== 0 || dy !== 0) {\n\n var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);\n\n if (t > 1) {\n x = p2.x;\n y = p2.y;\n\n } else if (t > 0) {\n x += dx * t;\n y += dy * t;\n }\n }\n\n dx = p.x - x;\n dy = p.y - y;\n\n return dx * dx + dy * dy;\n}\n// rest of the code doesn't care about point format\n\n// basic distance-based simplification\nfunction simplifyRadialDist(points, sqTolerance) {\n\n var prevPoint = points[0],\n newPoints = [prevPoint],\n point;\n\n for (var i = 1, len = points.length; i < len; i++) {\n point = points[i];\n\n if (getSqDist(point, prevPoint) > sqTolerance) {\n newPoints.push(point);\n prevPoint = point;\n }\n }\n\n if (prevPoint !== point) newPoints.push(point);\n\n return newPoints;\n}\n\nfunction simplifyDPStep(points, first, last, sqTolerance, simplified) {\n var maxSqDist = sqTolerance,\n index;\n\n for (var i = first + 1; i < last; i++) {\n var sqDist = getSqSegDist(points[i], points[first], points[last]);\n\n if (sqDist > maxSqDist) {\n index = i;\n maxSqDist = sqDist;\n }\n }\n\n if (maxSqDist > sqTolerance) {\n if (index - first > 1) simplifyDPStep(points, first, index, sqTolerance, simplified);\n simplified.push(points[index]);\n if (last - index > 1) simplifyDPStep(points, index, last, sqTolerance, simplified);\n }\n}\n\n// simplification using Ramer-Douglas-Peucker algorithm\nfunction simplifyDouglasPeucker(points, sqTolerance) {\n var last = points.length - 1;\n\n var simplified = [points[0]];\n simplifyDPStep(points, 0, last, sqTolerance, simplified);\n simplified.push(points[last]);\n\n return simplified;\n}\n\n// both algorithms combined for awesome performance\nfunction simplify(points, tolerance, highestQuality) {\n\n if (points.length <= 2) return points;\n\n var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;\n\n points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);\n points = simplifyDouglasPeucker(points, sqTolerance);\n\n return points;\n}\n\n// export as AMD module / Node module / browser or worker variable\nif (typeof define === 'function' && define.amd) define(function() { return simplify; });\nelse if (typeof module !== 'undefined') {\n module.exports = simplify;\n module.exports.default = simplify;\n} else if (typeof self !== 'undefined') self.simplify = simplify;\nelse window.simplify = simplify;\n\n})();\n", "import type {\n\tFloor,\n\tMapData,\n\tMapView,\n\tModel,\n\tTCameraAnimationOptions,\n\tTCameraTarget,\n\tTEvents,\n} from '@mappedin/mappedin-js';\nimport { ANIMATION_TWEENS, Coordinate } from '@mappedin/mappedin-js';\nimport Logger from '@packages/internal/common/Mappedin.Logger';\nimport type { MapViewExtension } from '@packages/internal/common/extensions';\nimport { PubSub } from '@packages/internal/common/pubsub';\nimport { getForwardBearing } from '@packages/internal/common/utils';\nimport type { Tween } from '@tweenjs/tween.js';\nimport simplify from 'simplify-js';\nimport z from 'zod';\nimport { DEFAULT_BLUEDOT_OPTIONS, POSITION_ANIMATION_DURATION } from './constants';\nimport { BlueDotModelManager } from './model-manager';\nimport { geolocationPositionSchema, positionSchema } from './schemas';\nimport { stateMachine } from './state-machine';\nimport type {\n\tBlueDotAction,\n\tBlueDotEventPayloads,\n\tBlueDotState,\n\tBlueDotPositionProcessor,\n\tBlueDotPositionUpdate,\n\tBlueDotPositionUpdateWithFloor,\n\tBlueDotStatus,\n\tBlueDotUpdateOptions,\n\tFollowCameraOptions,\n\tFollowMode,\n\tGeolocationPositionExtended,\n\tParsedBlueDotPosition,\n\tBlueDotUpdateState,\n} from './types';\nimport {\n\tdeepMergeState,\n\teaseOutCubic,\n\tfindBlueDotOnPath,\n\tgetPositionWithOverrides,\n\tisWithinPanBounds,\n\tshouldShowHeadingCone,\n} from './utils';\nimport type { ReadonlyDeep } from 'type-fest';\n\n/**\n * Show a Blue Dot indicating the device's position on the map.\n *\n * @example\n * ```ts\n * import { show3dMap } from '@mappedin/mappedin-js';\n * import { BlueDot } from '@mappedin/blue-dot';\n *\n * const mapView = await show3dMap(...);\n *\n * // Enable BlueDot\n * new BlueDot(mapView).enable();\n *\n * // Option 1: Listen for position updates from the device\n * mapView.BlueDot.on('position-update', (position) => {\n * console.log('User position:', position);\n * });\n *\n * // Option 2: Update position manually\n * new BlueDot(mapView).update({ latitude, longitude, accuracy, floorOrFloorId });\n *\n * ```\n */\nexport class BlueDot implements MapViewExtension<BlueDotState> {\n\t#pubsub = new PubSub<BlueDotEventPayloads>();\n\t#mapView: MapView;\n\t#mapData: MapData;\n\t#watcherId?: number;\n\t/**\n\t * The latest position received from the device's geolocation API.\n\t */\n\t#currentGeolocation?: ParsedBlueDotPosition;\n\t/** The latest position manually set by the user. */\n\t#overridePosition?: BlueDotPositionUpdateWithFloor;\n\t/** The latest actual position of the Blue Dot. */\n\t#lastPosition?: ParsedBlueDotPosition;\n\t#timer?: NodeJS.Timeout;\n\t#positionAnimation?: Tween;\n\t#options: BlueDotState = DEFAULT_BLUEDOT_OPTIONS;\n\t#cachedCoordinate?: Coordinate;\n\t#status: BlueDotStatus = 'disabled';\n\t#following = false;\n\t#blueDotModel: BlueDotModelManager;\n\t#currentFloor?: Floor;\n\t#lastFloorAltitude?: number;\n\t#floorTransitionStartTime?: number;\n\t#floorTransitionStartAltitude?: number;\n\t#floorTransitionDuration = 1000;\n\t/**\n\t * Create a new {@link BlueDot} instance.\n\t */\n\tconstructor(mapView: MapView) {\n\t\tthis.#mapView = mapView;\n\t\tthis.#mapData = mapView.getMapData();\n\t\tthis.#mapView.on('pre-render', this.#syncVerticalOffset);\n\t\tthis.#mapView.on('click', this.#handleClick);\n\t\tthis.#mapView.on('hover', this.#handleHover);\n\t\tthis.#blueDotModel = new BlueDotModelManager(mapView, this);\n\t}\n\n\t/**\n\t * Get the Model for the BlueDot core element.\n\t */\n\tget dotModel(): Model | undefined {\n\t\treturn this.#blueDotModel.dot;\n\t}\n\n\t/**\n\t * Get the Model for the accuracy ring.\n\t */\n\tget accuracyRingModel(): Model | undefined {\n\t\treturn this.#blueDotModel.accuracyRing;\n\t}\n\n\t/**\n\t * Get the Model for the heading cone.\n\t */\n\tget headingConeModel(): Model | undefined {\n\t\treturn this.#blueDotModel.headingCone;\n\t}\n\n\t/**\n\t * Whether the BlueDot is currently enabled.\n\t */\n\tget isEnabled(): boolean {\n\t\treturn this.#status !== 'disabled';\n\t}\n\n\t/**\n\t * The current state of the BlueDot. Can be 'hidden', 'active', 'inactive', or 'disabled'.\n\t * Listen for state changes using the 'status-change' event.\n\t *\n\t * @example\n\t * mapView.BlueDot.on('status-change', ({ status }) => {\n\t * if (status === 'active') {\n\t * // BlueDot is visible and tracking\n\t * }\n\t * });\n\t */\n\tget status(): BlueDotStatus {\n\t\treturn this.#status;\n\t}\n\n\t/**\n\t * Whether the BlueDot is currently following the user (camera follow mode).\n\t */\n\tget isFollowing(): boolean {\n\t\treturn this.#following;\n\t}\n\n\t/**\n\t * The direction the user is facing in degrees from north clockwise.\n\t * @see https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates/heading\n\t */\n\tget heading(): GeolocationPosition['coords']['heading'] | undefined {\n\t\treturn this.#lastPosition?.heading;\n\t}\n\n\t/**\n\t * The accuracy of the current position in metres.\n\t */\n\tget accuracy(): GeolocationPosition['coords']['accuracy'] | undefined {\n\t\treturn this.#lastPosition?.accuracy;\n\t}\n\n\t/**\n\t * The coordinate of the current position.\n\t */\n\tget coordinate(): Coordinate | undefined {\n\t\tif (this.#lastPosition == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (\n\t\t\tthis.#cachedCoordinate == null ||\n\t\t\tthis.floor?.id !== this.#cachedCoordinate.floorId ||\n\t\t\tthis.#lastPosition.latitude !== this.#cachedCoordinate.latitude ||\n\t\t\tthis.#lastPosition.longitude !== this.#cachedCoordinate.longitude\n\t\t) {\n\t\t\tthis.#cachedCoordinate = new Coordinate({\n\t\t\t\tlatitude: this.#lastPosition.latitude,\n\t\t\t\tlongitude: this.#lastPosition.longitude,\n\t\t\t\tfloorId: this.floor?.id,\n\t\t\t});\n\t\t}\n\n\t\treturn this.#cachedCoordinate;\n\t}\n\n\tgetState = (): ReadonlyDeep<BlueDotState> => {\n\t\treturn { ...this.#options };\n\t};\n\n\t/**\n\t * The floor the Blue Dot is currently on. If undefined, the Blue Dot will appear on every floor.\n\t */\n\tget floor(): Floor | undefined {\n\t\treturn this.#lastPosition?.floor;\n\t}\n\n\t/**\n\t * Enable the Blue Dot. It will be hidden until a position is received either from the browser or by calling {@link BlueDot.update}.\n\t * @param options - The options to setup the Blue Dot (see {@link BlueDotOptions}).\n\t *\n\t * @example Enable with default options\n\t * mapView.BlueDot.enable();\n\t *\n\t * @example Enable with custom color and accuracy ring\n\t * mapView.BlueDot.enable({ color: '#00ff00', accuracyRing: { color: '#00ff00', opacity: 0.2 } });\n\t *\n\t * @see See the [BlueDot Guide](https://developer.mappedin.com/web-sdk/blue-dot) for more information.\n\t */\n\tenable = (options?: BlueDotUpdateState) => {\n\t\tthis.#options = deepMergeState(this.#options, options);\n\t\tthis.#transitionAction('enable');\n\n\t\t// Handle initial state\n\t\tif (this.#options.initialState === 'inactive') {\n\t\t\tthis.#transitionAction('initialize');\n\t\t}\n\n\t\tthis.watchDevicePosition(this.#options.watchDevicePosition);\n\t};\n\t/**\n\t * Disable the Blue Dot. It will be hidden and no longer update.\n\t */\n\tdisable = () => {\n\t\tthis.#blueDotModel.remove();\n\t\tif (this.#timer) {\n\t\t\tclearTimeout(this.#timer);\n\t\t\tthis.#timer = undefined;\n\t\t}\n\t\tif (this.#following) {\n\t\t\tthis.#cancelFollow();\n\t\t}\n\t\tthis.watchDevicePosition(false);\n\t\tthis.#lastPosition = undefined;\n\t\tthis.#overridePosition = undefined;\n\t\tthis.#currentFloor = undefined;\n\t\tthis.#transitionAction('disable');\n\t\tthis.#mapView.off('user-interaction-start', this.#cancelFollow);\n\t\tthis.#mapView.off('navigation-active-path-change', this.#pathChangeHandler);\n\t};\n\n\t/**\n\t * Subscribe to a BlueDot event.\n\t * @param eventName The name of the event to listen for.\n\t * @param fn The function to call when the event is emitted.\n\t */\n\ton: PubSub<BlueDotEventPayloads>['on'] = (eventName, fn) => {\n\t\tthis.#pubsub.on(eventName, fn);\n\t};\n\n\t/**\n\t * Unsubscribe from a BlueDot event.\n\t * @param eventName The name of the event to unsubscribe from.\n\t * @param fn The function to unsubscribe from the event.\n\t */\n\toff: PubSub<BlueDotEventPayloads>['off'] = (eventName, fn) => {\n\t\tthis.#pubsub.off(eventName, fn);\n\t};\n\n\t/**\n\t * Update the BlueDot state after it has been enabled.\n\t * This allows overriding previously set values like colors, and other options.\n\t * @param options - The options to update\n\t *\n\t * @example Update color and accuracy ring\n\t * mapView.BlueDot.updateState({\n\t * color: '#ff0000',\n\t * accuracyRing: { color: '#ff0000', opacity: 0.5 }\n\t * });\n\t */\n\tupdateState = (options: BlueDotUpdateState) => {\n\t\tconst oldWatchDevicePosition = this.#options.watchDevicePosition;\n\t\tthis.#options = deepMergeState(this.#options, options);\n\n\t\tthis.#blueDotModel.updateAppearance();\n\n\t\tif (options.watchDevicePosition != null && options.watchDevicePosition !== oldWatchDevicePosition) {\n\t\t\tthis.watchDevicePosition(options.watchDevicePosition);\n\t\t}\n\n\t\t// Reset timer if timeout option was updated and BlueDot is active\n\t\tif (options.timeout != null && this.#status === 'active') {\n\t\t\tthis.#resetActiveTimer();\n\t\t}\n\t};\n\n\t#resetActiveTimer = () => {\n\t\tif (this.#timer) {\n\t\t\tclearTimeout(this.#timer);\n\t\t}\n\t\tif (typeof this.#options.timeout === 'number' && this.#options.timeout < Infinity) {\n\t\t\tthis.#timer = setTimeout(() => {\n\t\t\t\tif (this.#options.debug) {\n\t\t\t\t\tLogger.log(`BlueDot: Position timed out after ${this.#options.timeout}ms`);\n\t\t\t\t}\n\t\t\t\tthis.#transitionAction('timeout');\n\t\t\t\t// this.#core.render();\n\t\t\t}, this.#options.timeout);\n\t\t}\n\t};\n\n\t/**\n\t * Enable or disable the devices's geolocation listener to automatically position the Blue Dot.\n\t * If enabled, the device will request permission to access the user's precise location.\n\t * @param watch - Whether to enable or disable the listener.\n\t */\n\twatchDevicePosition = (watch: boolean) => {\n\t\tif (this.#watcherId) {\n\t\t\tnavigator.geolocation.clearWatch(this.#watcherId);\n\t\t\tthis.#watcherId = undefined;\n\t\t}\n\n\t\tif (this.#currentGeolocation) {\n\t\t\tthis.#currentGeolocation = undefined;\n\t\t}\n\n\t\tif (watch) {\n\t\t\tif (this.#status === 'disabled') {\n\t\t\t\tLogger.warn('BlueDot must be enabled before watching browser position.');\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.#watcherId = navigator.geolocation.watchPosition(this.onPositionUpdate, this.onPositionError, {\n\t\t\t\tenableHighAccuracy: true,\n\t\t\t});\n\t\t}\n\t};\n\n\t#setPosition = (update: BlueDotPositionUpdateWithFloor | undefined, options?: BlueDotUpdateOptions) => {\n\t\tlet parsed: ParsedBlueDotPosition | undefined;\n\t\ttry {\n\t\t\tparsed = positionSchema.parse(getPositionWithOverrides(update, this.#overridePosition));\n\t\t} catch (error) {\n\t\t\tthis.#transitionAction('error');\n\t\t\tLogger.error('BlueDot: Position parse failed', error instanceof z.ZodError ? error.message : String(error));\n\n\t\t\treturn;\n\t\t}\n\t\tif (this.#options.debug) {\n\t\t\tLogger.log('BlueDot: Parsed position', parsed);\n\t\t}\n\n\t\t// Check if position is within pan bounds\n\t\tif (this.#options.preventOutOfBounds) {\n\t\t\tconst { radius, center } = this.#mapView.Camera.bounds;\n\t\t\tif (radius != null && isFinite(radius) && center != null) {\n\t\t\t\tconst within = isWithinPanBounds(\n\t\t\t\t\t{ longitude: parsed.longitude, latitude: parsed.latitude },\n\t\t\t\t\t{ radius, center },\n\t\t\t\t);\n\t\t\t\tif (!within) {\n\t\t\t\t\tLogger.warn(\n\t\t\t\t\t\t`BlueDot: Position [${parsed.longitude}, ${parsed.latitude}] is outside map bounds. Position update will be discarded.`,\n\t\t\t\t\t);\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if the position accuracy passes the threshold\n\t\tif (!this.#isAccurateEnough(parsed.accuracy)) {\n\t\t\tLogger.log(\n\t\t\t\t`BlueDot: Dropping position update with accuracy ${parsed.accuracy}m (exceeds threshold ${\n\t\t\t\t\tthis.#options.accuracyThreshold\n\t\t\t\t}m)`,\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tif (!options?.silent) {\n\t\t\t// Only transition state if not silent\n\t\t\tthis.#transitionAction('position-update');\n\t\t} else {\n\t\t\tthis.#blueDotModel.updateAppearance();\n\t\t}\n\n\t\t// Check if geometry should be updated after state transition\n\t\tif (!this.#shouldUpdateGeometry()) {\n\t\t\tLogger.warn(\n\t\t\t\t`BlueDot: Cannot update position because BlueDot state is '${this.#status}'. BlueDot must be enabled first.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#applyPosition(parsed, options);\n\t};\n\n\t#applyPosition = (position: ParsedBlueDotPosition, options?: BlueDotUpdateOptions) => {\n\t\tthis.#lastPosition = position;\n\t\t// Handle side effects based on options\n\t\tif (!options?.silent) {\n\t\t\tthis.#resetActiveTimer();\n\n\t\t\tthis.#getAnalyticsIfEnabled().updateState({\n\t\t\t\tuserPosition: {\n\t\t\t\t\tbluedotTimestamp: Date.now(),\n\t\t\t\t\tlatitude: position.latitude,\n\t\t\t\t\tlongitude: position.longitude,\n\t\t\t\t\tfloorLevel: position.floor?.elevation,\n\t\t\t\t\taccuracy: position.accuracy,\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\tlet startPosition: [number, number, number];\n\t\tlet startWorldAltitude = 0;\n\t\tif (!this.dotModel) {\n\t\t\tstartPosition = [position.longitude, position.latitude, 0];\n\t\t\tstartWorldAltitude = position.floor ? this.#mapView.getState(position.floor)?.altitude ?? 0 : 0;\n\t\t\tthis.#lastFloorAltitude = startWorldAltitude;\n\t\t\tthis.#currentFloor = position.floor;\n\t\t\tthis.#blueDotModel.add(position);\n\t\t} else {\n\t\t\tconst coordinate = this.#blueDotModel.getPosition();\n\t\t\tstartPosition = [coordinate?.longitude ?? 0, coordinate?.latitude ?? 0, coordinate?.verticalOffset ?? 0];\n\t\t}\n\n\t\t// Stop any existing animation before calculating positions\n\t\tif (this.#positionAnimation) {\n\t\t\tthis.#positionAnimation.stop();\n\t\t\tthis.#positionAnimation = undefined;\n\t\t}\n\n\t\t// Handle floor transitions with smooth interpolation (no fixed target tweening)\n\t\tconst isFloorChange = this.#currentFloor?.id !== position.floor?.id;\n\n\t\tif (isFloorChange) {\n\t\t\t// Start floor transition - record the current altitude and time\n\t\t\tthis.#floorTransitionStartTime = Date.now();\n\t\t\tthis.#floorTransitionStartAltitude = this.#lastFloorAltitude ?? 0;\n\t\t\tthis.#currentFloor = position.floor;\n\t\t}\n\n\t\t// Only animate lat/lng, altitude is handled separately\n\t\tconst to: [number, number] = [position.longitude, position.latitude];\n\n\t\tconst setGeometryPosition = (newPos: [number, number]) => {\n\t\t\t// Altitude is handled entirely by pre-render sync, just use current cached value\n\t\t\tconst currentAltitude = this.#lastFloorAltitude ?? 0;\n\t\t\tthis.#blueDotModel.setPosition(\n\t\t\t\tnew Coordinate({\n\t\t\t\t\tlatitude: newPos[1],\n\t\t\t\t\tlongitude: newPos[0],\n\t\t\t\t}),\n\t\t\t);\n\t\t\tthis.#blueDotModel.setAltitude(currentAltitude);\n\t\t};\n\n\t\t// Handle animation based on options\n\t\tif (options?.animate === false) {\n\t\t\t// Set position immediately without animation\n\t\t\tsetGeometryPosition(to);\n\t\t\tthis.#updateAccuracyRing();\n\t\t\tthis.#updateHeadingCone();\n\t\t} else {\n\t\t\t// Use animation for position updates (lat/lng only)\n\t\t\tconst startLatLng: [number, number] = [startPosition[0], startPosition[1]];\n\t\t\tthis.#positionAnimation = this.#mapView\n\t\t\t\t.tween({ position: startLatLng })\n\t\t\t\t.to({ position: to }, POSITION_ANIMATION_DURATION)\n\t\t\t\t.easing(ANIMATION_TWEENS['ease-out'])\n\t\t\t\t.onUpdate(({ position }) => {\n\t\t\t\t\t// Track current animated position (lat/lng only)\n\t\t\t\t\tsetGeometryPosition(position as [number, number]);\n\t\t\t\t})\n\t\t\t\t.onStart(() => {\n\t\t\t\t\tthis.#updateAccuracyRing();\n\t\t\t\t\tthis.#updateHeadingCone();\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t}\n\n\t\t// Publish position updates unless silent\n\t\tif (!options?.silent) {\n\t\t\tthis.#pubsub.publish('position-update', {\n\t\t\t\tfloor: this.floor,\n\t\t\t\theading: this.heading,\n\t\t\t\taccuracy: this.accuracy,\n\t\t\t\tcoordinate: this.coordinate!,\n\t\t\t});\n\t\t}\n\t};\n\n\t#updateAccuracyRing = () => {\n\t\tif (this.#status === 'active') {\n\t\t\tthis.#blueDotModel.setAccuracy(this.accuracy);\n\t\t} else {\n\t\t\tthis.#blueDotModel.setAccuracy(undefined);\n\t\t}\n\t};\n\n\t#updateHeadingCone = () => {\n\t\tconst shouldShow = shouldShowHeadingCone(this.#status, this.heading, this.#options.heading.displayWhenInactive);\n\t\tif (this.heading != null && shouldShow) {\n\t\t\tthis.#blueDotModel.setHeading(this.heading);\n\t\t} else {\n\t\t\tthis.#blueDotModel.setHeading(undefined);\n\t\t}\n\t};\n\n\t#shouldUpdateGeometry = (): boolean => {\n\t\treturn this.#status !== 'hidden' && this.#status !== 'disabled';\n\t};\n\n\t/**\n\t * Manually override some position properties of the Blue Dot.\n\t * Accepts a full GeolocationPosition object or a partial {@link BlueDotPositionUpdate} object.\n\t * @example Manually set the accuracy and heading\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 10, heading: 90 });\n\t * ```\n\t * @example Reset accuracy and heading to device values\n\t * ```ts\n\t * api.BlueDot.update({ accuracy: 'device', heading: 'device' });\n\t * ```\n\t */\n\tupdate = (\n\t\tposition: GeolocationPositionExtended | BlueDotPositionUpdate | undefined,\n\t\toptions?: BlueDotUpdateOptions,\n\t) => {\n\t\tif (position == null) {\n\t\t\tthis.#overridePosition = undefined;\n\t\t} else if ('coords' in position) {\n\t\t\tthis.#overridePosition = Object.assign({}, this.#overridePosition, {\n\t\t\t\tlatitude: position.coords.latitude,\n\t\t\t\tlongitude: position.coords.longitude,\n\t\t\t\taccuracy: position.coords.accuracy,\n\t\t\t\theading: position.coords.heading,\n\t\t\t\tfloor: this.#getFloorByFloorLevel(position.coords.floorLevel),\n\t\t\t\ttimestamp: position.timestamp,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.#overridePosition = Object.assign({}, this.#overridePosition, position);\n\t\t\tif ('floorOrFloorId' in position) {\n\t\t\t\tthis.#overridePosition.floor =\n\t\t\t\t\ttypeof position.floorOrFloorId === 'string' && position.floorOrFloorId !== 'device'\n\t\t\t\t\t\t? this.#getFloorByFloorId(position.floorOrFloorId)\n\t\t\t\t\t\t: position.floorOrFloorId;\n\t\t\t}\n\t\t}\n\t\tconst hasPosition = this.#overridePosition?.latitude != null && this.#overridePosition?.longitude != null;\n\t\tif (hasPosition || this.#currentGeolocation != null) {\n\t\t\tthis.#setPosition(this.#currentGeolocation, options);\n\t\t}\n\t};\n\n\t#getFloorByFloorId = (floorId: string) => {\n\t\treturn this.#mapData.getById('floor', floorId);\n\t};\n\n\t#getFloorByFloorLevel = (floorLevel: GeolocationPositionExtended['coords']['floorLevel']) => {\n\t\tif (floorLevel == null) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn this.#mapView.currentFloorStack.floors\n\t\t\t.sort((a, b) => a.elevation - b.elevation)\n\t\t\t.find(f => f.elevation === floorLevel);\n\t};\n\n\t#simplifiedDirections?: number[][];\n\t#positionProcessor?: BlueDotPositionProcessor;\n\t#getSimplifiedDirections = () => {\n\t\tif (this.#simplifiedDirections == null && this.#mapView.Navigation.activeDirections != null) {\n\t\t\tconst coordinates = Array.isArray(this.#mapView.Navigation.activeDirections)\n\t\t\t\t? this.#mapView.Navigation.activeDirections.flatMap(d => d.coordinates)\n\t\t\t\t: this.#mapView.Navigation.activeDirections.coordinates;\n\t\t\tconst coordinatesOnMap = coordinates.filter(c => c.floorId === this.#mapView.currentFloor.id);\n\t\t\t// simplify the path to reduce the number of points to check, and avoid bearing jitter\n\t\t\tthis.#simplifiedDirections = simplify(\n\t\t\t\tcoordinatesOnMap.map(c => ({ x: c.longitude, y: c.latitude })),\n\t\t\t\t0.00001,\n\t\t\t).map(p => [p.x, p.y]);\n\t\t}\n\n\t\treturn this.#simplifiedDirections;\n\t};\n\t#cancelFollow = () => {\n\t\tif (this.#mapView.Camera.isAnimating) {\n\t\t\tthis.#mapView.Camera.cancelAnimation();\n\t\t}\n\t\tif (this.#followHandler) {\n\t\t\tthis.off('position-update', this.#followHandler);\n\t\t\tthis.#followHandler = undefined;\n\t\t}\n\t\tthis.#following = false;\n\t\tthis.#simplifiedDirections = undefined;\n\t\tthis.#mapView.off('user-interaction-start', this.#cancelFollow);\n\t\tthis.#mapView.off('navigation-active-path-change', this.#pathChangeHandler);\n\t\tthis.#pubsub.publish('follow-change', { following: false });\n\t};\n\t#pathChangeHandler = () => {\n\t\tthis.#simplifiedDirections = undefined;\n\t};\n\t#followHandler?: (event: BlueDotEventPayloads['position-update']) => void;\n\t/**\n\t * Set the camera to follow the BlueDot in various modes. User interaction will cancel following automatically.\n\t * @param mode The follow mode ('position-only', 'position-and-heading', 'position-and-path-direction', or false to disable).\n\t * @param cameraOptions Optional camera options (zoom, pitch, etc.).\n\t *\n\t * @example\n\t * mapView.BlueDot.follow('position-and-heading', { zoomLevel: 21, pitch: 45 });\n\t */\n\tfollow = (mode: FollowMode, cameraOptions?: FollowCameraOptions) => {\n\t\tif (mode === false) {\n\t\t\tthis.#cancelFollow();\n\n\t\t\treturn;\n\t\t}\n\n\t\t// bearing is only available in position-only mode\n\t\tif (mode !== 'position-only' && cameraOptions?.bearing != null) {\n\t\t\tLogger.warn(\n\t\t\t\t`BlueDot: Camera bearing option will be ignored in follow mode '${mode}'. To control the bearing manually, use mode 'position-only'.`,\n\t\t\t);\n\t\t}\n\n\t\tconst cameraTargetWithDefaults: TCameraTarget = {\n\t\t\tzoomLevel: cameraOptions?.zoomLevel ?? 21,\n\t\t\tbearing: mode === 'position-only' ? cameraOptions?.bearing : undefined,\n\t\t\tpitch: cameraOptions?.pitch ?? 45,\n\t\t};\n\t\tconst cameraOptionsWithDefaults: TCameraAnimationOptions = {\n\t\t\tduration: cameraOptions?.duration ?? POSITION_ANIMATION_DURATION,\n\t\t\teasing: cameraOptions?.easing ?? 'ease-in-out',\n\t\t};\n\n\t\tif (this.#following) {\n\t\t\t// already following, just updating the handler\n\t\t\tif (this.#followHandler) {\n\t\t\t\tthis.off('position-update', this.#followHandler);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.#following = true;\n\t\t\tthis.#mapView.on('user-interaction-start', this.#cancelFollow);\n\t\t\tthis.#mapView.on('navigation-active-path-change', this.#pathChangeHandler);\n\t\t}\n\n\t\tthis.#followHandler = (event: BlueDotEventPayloads['position-update']) => {\n\t\t\tconst { coordinate, heading, floor } = event;\n\t\t\tcameraTargetWithDefaults.center = coordinate;\n\n\t\t\tif (floor != null && floor.id !== this.#mapView.currentFloor.id) {\n\t\t\t\tthis.#mapView.setFloor(floor.id);\n\t\t\t\tthis.#simplifiedDirections = undefined;\n\t\t\t}\n\n\t\t\tif (mode === 'position-and-heading') {\n\t\t\t\tcameraTargetWithDefaults.bearing = heading ?? undefined;\n\t\t\t} else if (mode === 'position-and-path-direction') {\n\t\t\t\tconst directions = this.#getSimplifiedDirections();\n\t\t\t\tif (directions != null) {\n\t\t\t\t\tconst intersection = findBlueDotOnPath(directions, [coordinate.longitude, coordinate.latitude]);\n\t\t\t\t\tif (intersection != null) {\n\t\t\t\t\t\tconst segment = directions[intersection.segmentIndex];\n\t\t\t\t\t\tconst endSegment = directions[intersection.segmentIndex + 1];\n\t\t\t\t\t\tcameraTargetWithDefaults.bearing = getForwardBearing(segment, endSegment);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.#mapView.Camera.animateTo(cameraTargetWithDefaults, cameraOptionsWithDefaults);\n\t\t};\n\t\tthis.on('position-update', this.#followHandler);\n\t\tthis.#pubsub.publish('follow-change', { following: true, mode });\n\t};\n\n\t/**\n\t * Set a position processor callback that allows intercepting and modifying device/geolocation position updates before they are applied.\n\t *\n\t * **Note**: This processor only applies to automatic position updates from device geolocation.\n\t * Manual position updates via `update()` method bypass the processor and are applied directly.\n\t *\n\t * @param processor - A callback function that receives current state and incoming update. Return undefined to discard the update, or return a modified update object.\n\t *\n\t * @example Discard inaccurate positions\n\t * ```ts\n\t * blueDot.setPositionProcessor((current, incoming) => {\n\t * if (incoming.accuracy && incoming.accuracy > 50) {\n\t * return undefined; // Discard update\n\t * }\n\t * return incoming; // Accept update\n\t * });\n\t * ```\n\t *\n\t * @example Modify incoming positions\n\t * ```ts\n\t * blueDot.setPositionProcessor((current, incoming) => {\n\t * // Apply custom smoothing or validation logic\n\t * return {\n\t * ...incoming,\n\t * accuracy: Math.min(incoming.accuracy || 100, 10) // Cap accuracy\n\t * };\n\t * });\n\t * ```\n\t */\n\tsetPositionProcessor(processor?: BlueDotPositionProcessor) {\n\t\tthis.#positionProcessor = processor;\n\t}\n\n\t/**\n\t * Checks if the current accuracy is acceptable for updating the BlueDot position.\n\t * @param accuracy The accuracy value to check\n\t * @returns true if the accuracy is acceptable, false if it should be dropped\n\t */\n\t#isAccurateEnough = (accuracy: number | undefined): boolean => {\n\t\tif (accuracy == null) {\n\t\t\t// We cannot infer much from the lack of accuracy data, so we consider it accurate enough\n\t\t\treturn this.#status !== 'disabled';\n\t\t}\n\n\t\treturn accuracy <= this.#options.accuracyThreshold;\n\t};\n\n\t/**\n\t * Process incoming position update through the position processor callback if set.\n\t * @param incoming The incoming position update\n\t * @returns The processed position update or undefined if discarded\n\t */\n\t#processIncomingPosition = (incoming: BlueDotPositionUpdateWithFloor): BlueDotPositionUpdateWithFloor | undefined => {\n\t\t// Build current state from last position\n\t\tconst currentState: BlueDotPositionUpdateWithFloor = {\n\t\t\tlatitude: this.#lastPosition?.latitude,\n\t\t\tlongitude: this.#lastPosition?.longitude,\n\t\t\taccuracy: this.#lastPosition?.accuracy,\n\t\t\theading: this.#lastPosition?.heading,\n\t\t\tfloor: this.#lastPosition?.floor,\n\t\t\ttimestamp: this.#lastPosition?.timestamp,\n\t\t};\n\n\t\ttry {\n\t\t\treturn this.#positionProcessor!(currentState, incoming);\n\t\t} catch (error) {\n\t\t\tLogger.error(\n\t\t\t\t'BlueDot: Position processor callback threw an error',\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t);\n\t\t\t// Fall back to original position on error\n\t\t\treturn incoming;\n\t\t}\n\t};\n\n\tdestroy = () => {\n\t\tthis.disable();\n\t\tthis.#blueDotModel.destroy();\n\t\tthis.#mapView.off('pre-render', this.#syncVerticalOffset);\n\t\tthis.#mapView.off('click', this.#handleClick);\n\t\tthis.#mapView.off('hover', this.#handleHover);\n\t\tthis.#pubsub.destroy();\n\t};\n\n\t#transitionAction = (action: BlueDotAction) => {\n\t\tconst nextStatus = stateMachine[this.#status].actions[action];\n\t\tif (nextStatus == null) {\n\t\t\tLogger.warn(`BlueDot: Invalid state transition from ${this.#status} to ${nextStatus} using ${action}`);\n\t\t\treturn;\n\t\t}\n\t\tif (nextStatus === this.#status) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.#options.debug) {\n\t\t\tLogger.log(`BlueDot: Transitioning from ${this.#status} to ${nextStatus} using ${action}`);\n\t\t}\n\t\tthis.#status = nextStatus;\n\t\tthis.#blueDotModel.updateAppearance();\n\t\tthis.#pubsub.publish('status-change', {\n\t\t\tstatus: nextStatus,\n\t\t\taction,\n\t\t});\n\t};\n\n\t/**\n\t * Synchronizes BlueDot vertical offset with current floor altitude on every frame.\n\t * Handles smooth floor transitions and real-time altitude tracking.\n\t */\n\t#syncVerticalOffset = () => {\n\t\tif (!this.dotModel || !this.#lastPosition || this.#status === 'hidden' || this.#status === 'disabled') {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the current target floor altitude (always up-to-date)\n\t\tconst targetFloorAltitude = this.#lastPosition.floor\n\t\t\t? this.#mapView.getState(this.#lastPosition.floor)?.altitude ?? 0\n\t\t\t: this.#mapView.getState(this.#mapView.currentFloor)?.altitude ?? 0;\n\n\t\tlet currentAltitude = targetFloorAltitude;\n\n\t\t// Handle smooth floor transitions\n\t\tif (this.#floorTransitionStartTime != null && this.#floorTransitionStartAltitude != null) {\n\t\t\tconst elapsed = Date.now() - this.#floorTransitionStartTime;\n\t\t\tconst progress = Math.min(elapsed / this.#floorTransitionDuration, 1);\n\n\t\t\tif (progress < 1) {\n\t\t\t\t// Still transitioning - interpolate between start altitude and current target\n\t\t\t\tconst easeProgress = easeOutCubic(progress);\n\t\t\t\tcurrentAltitude =\n\t\t\t\t\tthis.#floorTransitionStartAltitude +\n\t\t\t\t\t(targetFloorAltitude - this.#floorTransitionStartAltitude) * easeProgress;\n\t\t\t} else {\n\t\t\t\t// Transition complete - clear transition state\n\t\t\t\tthis.#floorTransitionStartTime = undefined;\n\t\t\t\tthis.#floorTransitionStartAltitude = undefined;\n\t\t\t}\n\t\t}\n\n\t\t// Only update if altitude has changed to avoid unnecessary updates\n\t\tif (this.#lastFloorAltitude !== currentAltitude) {\n\t\t\tthis.#lastFloorAltitude = currentAltitude;\n\t\t\tthis.#blueDotModel.setAltitude(currentAltitude);\n\t\t}\n\t};\n\n\tprivate onPositionUpdate = (position: GeolocationPositionExtended) => {\n\t\tif (this.isEnabled === false) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tgeolocationPositionSchema.parse(position);\n\t\t} catch (error) {\n\t\t\tthis.#transitionAction('error');\n\t\t\tLogger.error(\n\t\t\t\t'BlueDot: Browser sent invalid position',\n\t\t\t\terror instanceof z.ZodError ? error.message : String(error),\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#currentGeolocation = {\n\t\t\tlatitude: position.coords?.latitude,\n\t\t\tlongitude: position.coords?.longitude,\n\t\t\taccuracy: position.coords?.accuracy,\n\t\t\theading: position.coords?.heading,\n\t\t\tfloor: this.#getFloorByFloorLevel(position.coords?.floorLevel),\n\t\t\ttimestamp: position.timestamp,\n\t\t\t// TODO: can we use these in the future ?\n\t\t\t// altitude: position.coords?.altitude,\n\t\t\t// altitudeAccuracy: position.coords?.altitudeAccuracy,\n\t\t\t// speed: position.coords?.speed,\n\t\t};\n\n\t\t// Process the position through processor if defined\n\t\tlet finalPosition = this.#currentGeolocation;\n\t\tif (this.#positionProcessor) {\n\t\t\tconst processedPosition = this.#processIncomingPosition(this.#currentGeolocation);\n\t\t\tif (processedPosition === undefined) {\n\t\t\t\tif (this.#options.debug) {\n\t\t\t\t\tLogger.log('BlueDot: Position update discarded by position processor');\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinalPosition = processedPosition as ParsedBlueDotPosition;\n\t\t}\n\n\t\tthis.#setPosition(finalPosition);\n\t};\n\n\tprivate onPositionError = (error: GeolocationPositionError) => {\n\t\tthis.#transitionAction('error');\n\n\t\tswitch (error.code) {\n\t\t\tcase error.PERMISSION_DENIED:\n\t\t\t\tLogger.error('Geolocation permission denied by the user.', error);\n\t\t\t\tthis.#getAnalyticsIfEnabled().sendWatchPositionDenied();\n\t\t\t\tbreak;\n\t\t\tcase error.POSITION_UNAVAILABLE:\n\t\t\t\tLogger.error('Geolocation position unavailable.', error);\n\t\t\t\tbreak;\n\t\t\tcase error.TIMEOUT:\n\t\t\t\tLogger.error('Geolocation request timed out.', error);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tLogger.error('An unknown geolocation error occurred.', error);\n\t\t\t\tbreak;\n\t\t}\n\t\tthis.#pubsub.publish('error', error);\n\t};\n\n\t#getAnalyticsIfEnabled = () => {\n\t\t// Don't log analytics events if preventOutOfBounds is disabled.\n\t\t// We don't want to log analytics of people within their homes viewing a map.\n\t\treturn !this.#options.preventOutOfBounds\n\t\t\t? { sendWatchPositionDenied: () => {}, updateState: () => {} }\n\t\t\t: this.#mapData.internal.Analytics;\n\t};\n\n\t#handleClickOrHover = (type: 'click' | 'hover') => (event: TEvents['click'] | TEvents['hover']) => {\n\t\tif (event.models == null || event.models.length === 0 || this.dotModel == null) {\n\t\t\treturn;\n\t\t}\n\t\tconst dotModel = event.models.find(m => m.id === this.dotModel?.id);\n\t\tif (dotModel == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#pubsub.publish(type, {\n\t\t\tcoordinate: event.coordinate,\n\t\t});\n\t};\n\n\t#handleClick = this.#handleClickOrHover('click');\n\t#handleHover = this.#handleClickOrHover('hover');\n}\n", "/* eslint-disable no-console*/\nexport const MI_DEBUG_KEY = 'mi-debug';\nexport const MI_ERROR_LABEL = '[MappedinJS]';\n\nexport enum E_SDK_LOG_LEVEL {\n\tLOG,\n\tWARN,\n\tERROR,\n\tSILENT,\n}\n\nexport function createLogger(name = '', { prefix = MI_ERROR_LABEL } = {}) {\n\tconst label = `${prefix}${name ? `-${name}` : ''}`;\n\n\tconst rnDebug = (type: 'log' | 'warn' | 'error', args: any[]) => {\n\t\tif (typeof window !== 'undefined' && (window as any).rnDebug) {\n\t\t\tconst processed = args.map(arg => {\n\t\t\t\tif (arg instanceof Error && arg.stack) {\n\t\t\t\t\treturn `${arg.message}\\n${arg.stack}`;\n\t\t\t\t}\n\n\t\t\t\treturn arg;\n\t\t\t});\n\t\t\t(window as any).rnDebug(`${name} ${type}: ${processed.join(' ')}`);\n\t\t}\n\t};\n\n\treturn {\n\t\tlogState: process.env.NODE_ENV === 'test' ? E_SDK_LOG_LEVEL.SILENT : E_SDK_LOG_LEVEL.LOG,\n\n\t\tlog(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.LOG) {\n\t\t\t\tconsole.log(label, ...args);\n\t\t\t\trnDebug('log', args);\n\t\t\t}\n\t\t},\n\n\t\twarn(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.WARN) {\n\t\t\t\tconsole.warn(label, ...args);\n\t\t\t\trnDebug('warn', args);\n\t\t\t}\n\t\t},\n\n\t\terror(...args: any[]) {\n\t\t\tif (this.logState <= E_SDK_LOG_LEVEL.ERROR) {\n\t\t\t\tconsole.error(label, ...args);\n\n\t\t\t\trnDebug('error', args);\n\t\t\t}\n\t\t},\n\n\t\t// It's a bit tricky to prepend [MappedinJs] to assert and time because of how the output is structured in the console, so it is left out for simplicity\n\t\tassert(...args: any[]) {\n\t\t\tconsole.assert(...args);\n\t\t},\n\n\t\ttime(label: string) {\n\t\t\tconsole.time(label);\n\t\t},\n\n\t\ttimeEnd(label: string) {\n\t\t\tconsole.timeEnd(label);\n\t\t},\n\t\tsetLevel(level: E_SDK_LOG_LEVEL) {\n\t\t\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\t\t\tthis.logState = level;\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst Logger = createLogger();\nexport function setLoggerLevel(level: E_SDK_LOG_LEVEL) {\n\tif (E_SDK_LOG_LEVEL.LOG <= level && level <= E_SDK_LOG_LEVEL.SILENT) {\n\t\tLogger.logState = level;\n\t}\n}\n\nexport default Logger;\n", "/**\n * Generic PubSub class implementing the Publish-Subscribe pattern for event handling.\n *\n * @template EVENT_PAYLOAD - The type of the event payload.\n * @template EVENT - The type of the event.\n */\nexport class PubSub<EVENT_PAYLOAD, EVENT extends keyof EVENT_PAYLOAD = keyof EVENT_PAYLOAD> {\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _subscribers: any = {};\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tprivate _destroyed = false;\n\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tpublish<EVENT_NAME extends EVENT>(eventName: EVENT_NAME, data?: EVENT_PAYLOAD[EVENT_NAME]) {\n\t\tif (!this._subscribers || !this._subscribers[eventName] || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._subscribers[eventName]!.forEach(function (fn) {\n\t\t\tif (typeof fn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfn(data);\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe a function to an event.\n\t *\n\t * @param eventName An event name which, when fired, will call the provided\n\t * function.\n\t * @param fn A callback that gets called when the corresponding event is fired. The\n\t * callback will get passed an argument with a type that's one of event payloads.\n\t * @example\n\t * // Subscribe to the 'click' event\n\t * const handler = (event) => {\n\t * const { coordinate } = event;\n\t * const { latitude, longitude } = coordinate;\n\t * \tconsole.log(`Map was clicked at ${latitude}, ${longitude}`);\n\t * };\n\t * map.on('click', handler);\n\t */\n\ton<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._destroyed) {\n\t\t\tthis._subscribers = {};\n\t\t}\n\t\tthis._subscribers[eventName] = this._subscribers[eventName] || [];\n\t\tthis._subscribers[eventName]!.push(fn);\n\t}\n\n\t/**\n\t * Unsubscribe a function previously subscribed with {@link on}\n\t *\n\t * @param eventName An event name to which the provided function was previously\n\t * subscribed.\n\t * @param fn A function that was previously passed to {@link on}. The function must\n\t * have the same reference as the function that was subscribed.\n\t * @example\n\t * // Unsubscribe from the 'click' event\n\t * const handler = (event) => {\n\t * \tconsole.log('Map was clicked', event);\n\t * };\n\t * map.off('click', handler);\n\t */\n\toff<EVENT_NAME extends EVENT>(\n\t\teventName: EVENT_NAME,\n\t\tfn: (\n\t\t\tpayload: EVENT_PAYLOAD[EVENT_NAME] extends {\n\t\t\t\tdata: null;\n\t\t\t}\n\t\t\t\t? EVENT_PAYLOAD[EVENT_NAME]['data']\n\t\t\t\t: EVENT_PAYLOAD[EVENT_NAME],\n\t\t) => void,\n\t) {\n\t\tif (!this._subscribers || this._subscribers[eventName] == null || this._destroyed) {\n\t\t\treturn;\n\t\t}\n\t\tconst itemIdx = this._subscribers[eventName]!.indexOf(fn);\n\n\t\tif (itemIdx !== -1) {\n\t\t\tthis._subscribers[eventName]!.splice(itemIdx, 1);\n\t\t}\n\t}\n\t/**\n\t * @private\n\t * @internal\n\t */\n\tdestroy() {\n\t\tthis._destroyed = true;\n\t\tthis._subscribers = {};\n\t}\n}\n", "import type { JwtPayload } from 'jwt-decode';\nimport { jwtDecode } from 'jwt-decode';\nimport { EARTH_RADIUS_M } from './constants';\nimport { Box2 } from 'three';\nimport type { Box3 } from 'three';\n\nexport function findMapWithElevationClosestToZero<T extends { elevation?: number }>(maps: T[]): T | undefined {\n\tif (maps.length === 0) return;\n\tlet closestMap: T | undefined;\n\tfor (let map of maps) {\n\t\tif (typeof map.elevation !== 'number') {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!closestMap) {\n\t\t\tclosestMap = map;\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof closestMap.elevation !== 'number') {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Math.abs(map.elevation) === Math.abs(closestMap.elevation)) {\n\t\t\t// In case we have no 0 value, we want to favour positive values\n\t\t\tclosestMap = map.elevation > closestMap.elevation ? map : closestMap;\n\t\t} else {\n\t\t\tclosestMap = Math.abs(map.elevation) < Math.abs(closestMap.elevation) ? map : closestMap;\n\t\t}\n\t}\n\n\treturn closestMap;\n}\n\n/**\n * Omit properites from object\n */\nexport function omit<T extends Record<string, any>, K extends keyof T>(obj: T, keysToOmit: K[]): Omit<T, K> {\n\tconst result = {} as Omit<T, K>;\n\tconst toOmit = new Set(keysToOmit);\n\tlet key: string;\n\tfor (key in obj) {\n\t\tif (!toOmit.has(key as K)) {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\n\treturn result;\n}\n\nexport function decodeAccessToken(accessToken: string) {\n\tconst decoded: JwtPayload & { capabilities: Record<string, any> } = jwtDecode(accessToken);\n\n\tif (decoded.sub == null) {\n\t\tthrow new Error('Access token is missing sub claim.');\n\t}\n\n\treturn {\n\t\tsub: decoded.sub,\n\t\taud: typeof decoded.aud === 'string' ? [decoded.aud] : decoded.aud ?? [],\n\t\tcapabilities: decoded.capabilities ?? {},\n\t};\n}\n\nexport function toRadians(degrees: number): number {\n\treturn degrees * (Math.PI / 180);\n}\n\nexport function toDegrees(radians: number): number {\n\treturn radians * (180 / Math.PI);\n}\n\nexport function round(value: number, decimals: number): number {\n\tconst factor = Math.pow(10, decimals);\n\n\treturn (Math.sign(value) * Math.round(Math.abs(value) * factor)) / factor;\n}\n\nexport function euclideanModulo(value: number, modulus: number): number {\n\treturn ((value % modulus) + modulus) % modulus;\n}\n\n/**\n * Position from our SDKs may be tuple of longitude and latitude optionally followed by altitude.\n */\ntype Position = [number, number] | [number, number, number?] | number[];\n\n/**\n * Calculates the approximate distance between two geographic coordinates on Earth's surface.\n *\n * This function uses the equirectangular approximation method to compute the distance, which simplifies\n * the math and speeds up calculations, but is less accurate over long distances compared to other methods\n * like the haversine formula.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point1 - The second point's longitude and latitude as [longitude, latitude].\n * @return The approximate distance between the two points in meters.\n */\nexport function haversineDistance([lon1, lat1]: Position, [lon2, lat2]: Position): number {\n\tconst dLat = toRadians(lat2 - lat1);\n\tconst dLon = toRadians(lon2 - lon1);\n\n\tconst startLat = toRadians(lat1);\n\tconst destLat = toRadians(lat2);\n\n\tconst a =\n\t\tMath.sin(dLat / 2) * Math.sin(dLat / 2) +\n\t\tMath.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(startLat) * Math.cos(destLat);\n\tconst c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n\treturn EARTH_RADIUS_M * c;\n}\n\n/**\n * Calculates the bearing clockwise from North between two geographic coordinates on Earth's surface.\n * 0 is North, 90 is East, 180 is South, 270 is West.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The forward bearing in degrees from point1 to point2, measured clockwise from true North.\n */\nexport function getForwardBearing([lon1, lat1]: Position, [lon2, lat2]: Position): number {\n\tconst startLat = toRadians(lat1);\n\tconst startLon = toRadians(lon1);\n\tconst destLat = toRadians(lat2);\n\tconst destLon = toRadians(lon2);\n\n\tconst dLon = destLon - startLon;\n\n\tconst y = Math.sin(dLon) * Math.cos(destLat);\n\tconst x = Math.cos(startLat) * Math.sin(destLat) - Math.sin(startLat) * Math.cos(destLat) * Math.cos(dLon);\n\n\t// normalize to 0-360\n\treturn toDegrees((Math.atan2(y, x) + Math.PI * 2) % (Math.PI * 2));\n}\n\n/**\n *\n * Normalizes the start and end rotations to the range 0 to 2 PI and ensures the shortest path for rotation.\n *\n * @param startRotation - The start rotation in radians\n * @param targetRotation - The target rotation in radians\n * @returns Start and end rotations for the tween.\n */\nexport function shortestTweenRotation(startRotation: number, targetRotation: number) {\n\tconst startRotationMod2Pi = euclideanModulo(startRotation, Math.PI * 2);\n\tconst targetRotationMod2Pi = euclideanModulo(targetRotation, Math.PI * 2);\n\tconst delta = targetRotationMod2Pi - startRotationMod2Pi;\n\n\t// If delta > Math.PI rotate 2*PI clockwise\n\t// If delta < -Math.PI rotate 2*PI counterclockwise\n\t// Otherwise delta is already the shortest path\n\tconst endRotation = targetRotationMod2Pi + (delta > Math.PI ? -Math.PI * 2 : delta < -Math.PI ? Math.PI * 2 : 0);\n\n\treturn { start: startRotationMod2Pi, end: endRotation };\n}\n\nexport function isFiniteBox(box: Box2 | Box3) {\n\tif (box instanceof Box2) {\n\t\treturn (\n\t\t\tNumber.isFinite(box.min.x) &&\n\t\t\tNumber.isFinite(box.min.y) &&\n\t\t\tNumber.isFinite(box.max.x) &&\n\t\t\tNumber.isFinite(box.max.y)\n\t\t);\n\t}\n\n\treturn (\n\t\tNumber.isFinite(box.min.x) &&\n\t\tNumber.isFinite(box.min.y) &&\n\t\tNumber.isFinite(box.max.x) &&\n\t\tNumber.isFinite(box.max.y) &&\n\t\tNumber.isFinite(box.min.z) &&\n\t\tNumber.isFinite(box.max.z)\n\t);\n}\n\n// Re-export from separate files to avoid bundling three.js when not needed\nexport { clampWithWarning } from './math-utils';\nexport { arraysEqual } from './array-utils';\n\nexport function isBrowser(): boolean {\n\treturn typeof window !== 'undefined' && window !== null;\n}\n\n/**\n * Calculates the simple Euclidean distance between two geographic coordinates.\n *\n * This treats longitude and latitude as Cartesian coordinates on a flat plane.\n * It's the fastest distance calculation but least accurate for geographic data.\n * Best used for relative distance comparisons rather than actual measurements.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The Euclidean distance between the two points in meters.\n */\nexport function euclideanDistance(point1: Position, point2: Position): number {\n\tconst [lon1, lat1] = point1;\n\tconst [lon2, lat2] = point2;\n\n\tconst dx = toRadians(lon2 - lon1);\n\tconst dy = toRadians(lat2 - lat1);\n\n\treturn Math.sqrt(dx * dx + dy * dy) * EARTH_RADIUS_M;\n}\n\n/**\n * Calculates the approximate distance between two geographic coordinates on Earth's surface.\n *\n * This function uses the equirectangular approximation method to compute the distance, which simplifies\n * the math and speeds up calculations, but is less accurate over long distances compared to other methods\n * like the haversine formula.\n *\n * @param point1 - The first point's longitude and latitude as [longitude, latitude].\n * @param point2 - The second point's longitude and latitude as [longitude, latitude].\n * @returns The approximate distance between the two points in meters.\n */\nexport function equirectangularDistance(point1: Position, point2: Position): number {\n\tconst [lon1, lat1] = point1.map(deg => toRadians(deg));\n\tconst [lon2, lat2] = point2.map(deg => toRadians(deg));\n\n\tconst deltaLat = lat2 - lat1;\n\tconst deltaLon = lon2 - lon1;\n\n\tconst x = deltaLon * Math.cos((lat1 + lat2) / 2);\n\tconst y = deltaLat;\n\n\treturn Math.sqrt(x * x + y * y) * EARTH_RADIUS_M;\n}\n", "export class InvalidTokenError extends Error {\n}\nInvalidTokenError.prototype.name = \"InvalidTokenError\";\nfunction b64DecodeUnicode(str) {\n return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {\n let code = p.charCodeAt(0).toString(16).toUpperCase();\n if (code.length < 2) {\n code = \"0\" + code;\n }\n return \"%\" + code;\n }));\n}\nfunction base64UrlDecode(str) {\n let output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\n switch (output.length % 4) {\n case 0:\n break;\n case 2:\n output += \"==\";\n break;\n case 3:\n output += \"=\";\n break;\n default:\n throw new Error(\"base64 string is not of the correct length\");\n }\n try {\n return b64DecodeUnicode(output);\n }\n catch (err) {\n return atob(output);\n }\n}\nexport function jwtDecode(token, options) {\n if (typeof token !== \"string\") {\n throw new InvalidTokenError(\"Invalid token specified: must be a string\");\n }\n options || (options = {});\n const pos = options.header === true ? 0 : 1;\n const part = token.split(\".\")[pos];\n if (typeof part !== \"string\") {\n throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);\n }\n let decoded;\n try {\n decoded = base64UrlDecode(part);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);\n }\n try {\n return JSON.parse(decoded);\n }\n catch (e) {\n throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);\n }\n}\n", "export const EARTH_RADIUS_M = 6371008.8;\n", "import Logger from './Mappedin.Logger';\n\n/**\n * Clamp a number between lower and upper bounds with a warning\n */\nexport function clampWithWarning(x: number, lower: number, upper: number, warning: string) {\n\tif (x < lower || x > upper) {\n\t\tLogger.warn(warning);\n\t}\n\n\treturn Math.min(upper, Math.max(lower, x));\n}\n", "/**\n * Compare two arrays for equality\n */\nexport function arraysEqual(arr1: any[] | null | undefined, arr2: any[] | null | undefined) {\n\tif (arr1 == null || arr2 == null) {\n\t\treturn arr1 === arr2;\n\t}\n\n\tif (arr1.length !== arr2.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arr1.length; i++) {\n\t\tif (arr1[i] !== arr2[i]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n", "import type { BlueDotState } from './types';\n\nexport const POSITION_ANIMATION_DURATION = 1000;\nexport const SCALE_ANIMATION_DURATION = 150;\nexport const ROTATION_ANIMATION_DURATION = 150;\nexport const MIN_BLUEDOT_RADIUS = 0.35;\nexport const BLUEDOT_RADIUS = 10;\nexport const BASE_COLOR = '#2266ff';\nexport const INACTIVE_COLOR = '#808080';\nexport const HEADING_CONE_OPACITY = 0.7;\nexport const ACCURACY_RING_OPACITY = 0.3;\nexport const DEFAULT_BLUEDOT_OPTIONS: BlueDotState = {\n\tradius: BLUEDOT_RADIUS,\n\tcolor: BASE_COLOR,\n\tinactiveColor: INACTIVE_COLOR,\n\theading: {\n\t\tcolor: BASE_COLOR,\n\t\topacity: HEADING_CONE_OPACITY,\n\t\tdisplayWhenInactive: false,\n\t},\n\taccuracyRing: {\n\t\tcolor: BASE_COLOR,\n\t\topacity: ACCURACY_RING_OPACITY,\n\t},\n\ttimeout: 30000,\n\twatchDevicePosition: true,\n\tdebug: false,\n\taccuracyThreshold: 50,\n\tinitialState: 'hidden',\n\tpreventOutOfBounds: true,\n};\n", "import type { MapView, Model, TEvents, TModelUpdateState } from '@mappedin/mappedin-js';\nimport { Coordinate } from '@mappedin/mappedin-js';\nimport { shortestTweenRotation, toDegrees, toRadians } from '@packages/internal/common/utils';\nimport type { Tween } from '@tweenjs/tween.js';\nimport { ROTATION_ANIMATION_DURATION, SCALE_ANIMATION_DURATION } from './constants';\nimport accuracyRingModel from './models/accuracy-ring.gltf';\nimport blueDotModel from './models/blue-dot.gltf';\nimport headingConeModel from './models/heading-cone.gltf';\nimport type { BlueDot } from './blue-dot';\nimport type { GeolocationPositionExtended, ParsedBlueDotPosition } from './types';\nimport { shouldShowAccuracyRing, computeBlueDotScale, shouldShowHeadingCone } from './utils';\n\nexport class BlueDotModelManager {\n\t#mapView: MapView;\n\t#blueDot: BlueDot;\n\t#scale = 1;\n\t#cachedZoomLevel?: number;\n\n\t// animations\n\t#scaleAnimation?: Tween;\n\t#rotationAnimation?: Tween;\n\n\t// models\n\tdot?: Model;\n\taccuracyRing?: Model;\n\theadingCone?: Model;\n\n\tconstructor(mapView: MapView, BlueDot: BlueDot) {\n\t\tthis.#mapView = mapView;\n\t\tthis.#blueDot = BlueDot;\n\t\tthis.#mapView.on('camera-change', this.#updateScale);\n\t}\n\n\tadd(position: ParsedBlueDotPosition) {\n\t\tthis.remove();\n\t\tthis.#updateScale({ zoomLevel: this.#mapView.Camera.zoomLevel });\n\t\t// Order of adding models matters for rendering order\n\t\tconst coordinate = new Coordinate({\n\t\t\tlatitude: position.latitude,\n\t\t\tlongitude: position.longitude,\n\t\t});\n\t\tthis.accuracyRing = this.#mapView.Models.add(coordinate, accuracyRingModel, {\n\t\t\tvisible: false,\n\t\t\tscale: position.accuracy ?? 0,\n\t\t\trotation: [0, 0, 0],\n\t\t\tcolor: this.options.accuracyRing.color,\n\t\t\topacity: this.options.accuracyRing.opacity,\n\t\t\tvisibleThroughGeometry: true,\n\t\t});\n\t\tthis.headingCone = this.#mapView.Models.add(coordinate, headingConeModel, {\n\t\t\tvisible: false,\n\t\t\tscale: this.#scale,\n\t\t\trotation: [0, 0, 0],\n\t\t\tcolor: this.#blueDot.status === 'inactive' ? this.options.inactiveColor : this.options.heading.color,\n\t\t\topacity: this.options.heading.opacity,\n\t\t\tvisibleThroughGeometry: true,\n\t\t});\n\t\tthis.dot = this.#mapView.Models.add(coordinate, blueDotModel, {\n\t\t\tvisible: false,\n\t\t\tscale: this.#scale,\n\t\t\trotation: [0, 0, 0],\n\t\t\tinteractive: true,\n\t\t\tvisibleThroughGeometry: true,\n\t\t\tmaterial: {\n\t\t\t\tInner: {\n\t\t\t\t\tcolor: this.#blueDot.status === 'inactive' ? this.options.inactiveColor : this.options.color,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\tget options() {\n\t\treturn this.#blueDot.getState();\n\t}\n\n\tgetPosition(): Coordinate | undefined {\n\t\tif (this.dot == null) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn this.#mapView.getState(this.dot).position;\n\t}\n\n\tsetPosition(value: Coordinate) {\n\t\tif (this.dot == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (this.dot) {\n\t\t\tthis.#mapView.updateState(this.dot, { visible: true, position: value });\n\t\t}\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, { position: value });\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.updateState(this.headingCone, { position: value });\n\t\t}\n\t}\n\n\t#accuracy: GeolocationPositionExtended['coords']['accuracy'] | undefined;\n\tsetAccuracy(value: GeolocationPositionExtended['coords']['accuracy'] | undefined) {\n\t\tif (this.accuracyRing == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#accuracy = value;\n\t\tconst accuracyRingState = this.#mapView.getState(this.accuracyRing);\n\t\tif (accuracyRingState == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (value != null) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\tvisible: shouldShowAccuracyRing(this.#blueDot.status, this.#accuracy),\n\t\t\t});\n\t\t\tif (this.#scaleAnimation) {\n\t\t\t\tthis.#scaleAnimation.stop();\n\t\t\t}\n\t\t\tthis.#mapView\n\t\t\t\t.tween({ scale: accuracyRingState.scale[0] })\n\t\t\t\t.to({ scale: value / 2 }, SCALE_ANIMATION_DURATION)\n\t\t\t\t.onUpdate(({ scale }) => {\n\t\t\t\t\tif (this.accuracyRing == null) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tscale: [scale, scale, 1],\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t} else {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\tvisible: false,\n\t\t\t});\n\t\t}\n\t}\n\n\t#heading: GeolocationPositionExtended['coords']['heading'] | undefined;\n\tsetHeading(value: GeolocationPositionExtended['coords']['heading'] | undefined) {\n\t\tif (this.headingCone == null) {\n\t\t\treturn;\n\t\t}\n\t\tthis.#heading = value;\n\t\tconst headingConeState = this.#mapView.getState(this.headingCone);\n\t\tif (headingConeState == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (value != null) {\n\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\tvisible: shouldShowHeadingCone(this.#blueDot.status, this.#heading, this.options.heading.displayWhenInactive),\n\t\t\t});\n\t\t\tif (this.#rotationAnimation) {\n\t\t\t\tthis.#rotationAnimation.stop();\n\t\t\t}\n\n\t\t\tconst currentZRad = headingConeState.rotation[2] != null ? toRadians(headingConeState.rotation[2]) : 0;\n\t\t\tconst targetZRad = -toRadians(value);\n\t\t\tconst { start, end } = shortestTweenRotation(currentZRad, targetZRad);\n\t\t\tthis.#rotationAnimation = this.#mapView\n\t\t\t\t.tween({ rotation: toDegrees(start) })\n\t\t\t\t.to({ rotation: toDegrees(end) }, ROTATION_ANIMATION_DURATION)\n\t\t\t\t.onUpdate(({ rotation }) => {\n\t\t\t\t\tif (this.headingCone == null) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\t// updateState expects degrees; preserve base X/Y and apply absolute Z in degrees\n\t\t\t\t\t\trotation: [0, 0, rotation],\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t\t.start();\n\t\t} else {\n\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\tvisible: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tsetAltitude(value: number | undefined) {\n\t\tif (this.dot == null) {\n\t\t\treturn;\n\t\t}\n\t\tconst update: TModelUpdateState = {\n\t\t\tverticalOffset: value,\n\t\t};\n\t\tthis.#mapView.updateState(this.dot, update);\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.updateState(this.accuracyRing, update);\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.updateState(this.headingCone, update);\n\t\t}\n\t}\n\n\t/**\n\t * Updates appearance of the BlueDot models based on a given status.\n\t */\n\tupdateAppearance() {\n\t\tswitch (this.#blueDot.status) {\n\t\t\tcase 'hidden':\n\t\t\tcase 'disabled':\n\t\t\t\tif (this.dot) {\n\t\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.accuracyRing) {\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.headingCone) {\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\tvisible: false,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'active':\n\t\t\tcase 'inactive':\n\t\t\t\tif (this.dot) {\n\t\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\t\tvisible: true,\n\t\t\t\t\t\tmaterial: {\n\t\t\t\t\t\t\tInner: {\n\t\t\t\t\t\t\t\tcolor: this.#blueDot.status === 'active' ? this.options.color : this.options.inactiveColor,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.accuracyRing) {\n\t\t\t\t\tthis.#mapView.updateState(this.accuracyRing, {\n\t\t\t\t\t\tvisible: shouldShowAccuracyRing(this.#blueDot.status, this.#accuracy),\n\t\t\t\t\t\t// Is there a use case where we ever want an inactive color accuracy ring?\n\t\t\t\t\t\t// color: state === 'active' ? this.#options.accuracyRing.color : this.#options.inactiveColor,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.headingCone) {\n\t\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\t\tvisible: shouldShowHeadingCone(\n\t\t\t\t\t\t\tthis.#blueDot.status,\n\t\t\t\t\t\t\tthis.#heading,\n\t\t\t\t\t\t\tthis.options.heading.displayWhenInactive,\n\t\t\t\t\t\t),\n\t\t\t\t\t\tcolor: this.#blueDot.status === 'active' ? this.options.heading.color : this.options.inactiveColor,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tremove() {\n\t\tif (this.dot) {\n\t\t\tthis.#mapView.Models.remove(this.dot);\n\t\t\tthis.dot = undefined;\n\t\t}\n\t\tif (this.accuracyRing) {\n\t\t\tthis.#mapView.Models.remove(this.accuracyRing);\n\t\t\tthis.accuracyRing = undefined;\n\t\t}\n\t\tif (this.headingCone) {\n\t\t\tthis.#mapView.Models.remove(this.headingCone);\n\t\t\tthis.headingCone = undefined;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.remove();\n\t\tthis.#mapView.off('camera-change', this.#updateScale);\n\t}\n\n\t#updateScale = ({ zoomLevel }: Pick<TEvents['camera-change'], 'zoomLevel'>) => {\n\t\t// We only want to update the scale if the zoom level of the camera changes.\n\t\t// Our camera can change zoom levels by a tiny fraction even when a pan or rotation action is performed,\n\t\t// so we round the zoom level to 5 decimals to avoid unnecessary updates.\n\t\tconst currentZoomLevel = Math.round(zoomLevel * 100000);\n\t\tif (currentZoomLevel !== this.#cachedZoomLevel) {\n\t\t\tthis.#cachedZoomLevel = currentZoomLevel;\n\t\t\tconst metersPerPixel = this.#mapView.getMetersPerPixel();\n\t\t\t// Compute scale from desired pixel radius and meters-per-pixel\n\t\t\tthis.#scale = computeBlueDotScale(this.options.radius, metersPerPixel);\n\t\t\tif (this.dot) {\n\t\t\t\tthis.#mapView.updateState(this.dot, {\n\t\t\t\t\tscale: [this.#scale, this.#scale, this.#scale],\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (this.headingCone) {\n\t\t\t\tthis.#mapView.updateState(this.headingCone, {\n\t\t\t\t\tscale: [this.#scale, this.#scale, 1],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[0]}],\"scene\":0,\"nodes\":[{\"mesh\":0}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2352,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":4704,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":6272,\"byteLength\":768,\"target\":34963}],\"buffers\":[{\"byteLength\":7040,\"uri\":\"data:application/octet-stream;base64,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AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgD8AAAA9AACAPwAAgD0AAIA/AADAPQAAgD8AAAA+AACAPwAAID4AAIA/AABAPgAAgD8AAGA+AACAPwAAgD4AAIA/AACQPgAAgD8AAKA+AACAPwAAsD4AAIA/AADAPgAAgD8AANA+AACAPwAA4D4AAIA/AADwPgAAgD8AAAA/AACAPwAACD8AAIA/AAAQPwAAgD8AABg/AACAPwAAID8AAIA/AAAoPwAAgD8AADA/AACAPwAAOD8AAIA/AABAPwAAgD8AAEg/AACAPwAAUD8AAIA/AABYPwAAgD8AAGA/AACAPwAAaD8AAIA/AABwPwAAgD8AAHg/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAA9AAAAAAAAgD0AAAAAAADAPQAAAAAAAAA+AAAAAAAAID4AAAAAAABAPgAAAAAAAGA+AAAAAAAAgD4AAAAAAACQPgAAAAAAAKA+AAAAAAAAsD4AAAAAAADAPgAAAAAAANA+AAAAAAAA4D4AAAAAAADwPgAAAAAAAAA/AAAAAAAACD8AAAAAAAAQPwAAAAAAABg/AAAAAAAAID8AAAAAAAAoPwAAAAAAADA/AAAAAAAAOD8AAAAAAABAPwAAAAAAAEg/AAAAAAAAUD8AAAAAAABYPwAAAAAAAGA/AAAAAAAAaD8AAAAAAABwPwAAAAAAAHg/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAgD8AAAA/X4p9P7j4GD+vQXY/xfswP5ltaj/tHEc/eoJaP3qCWj/tHEc/mW1qP8X7MD+vQXY/uPgYP1+KfT8AAAA/AACAP5AOzj5fin0/dQiePq9Bdj9MjGM+mW1qPxr2FT56glo/O5OsPe0cRz8M5Rs9xfswPzBoHTy4+Bg/AAAAAAAAAD8waB08kA7OPgzlGz11CJ4+O5OsPUyMYz4a9hU+GvYVPkyMYz47k6w9dQiePgzlGz2QDs4+MGgdPAAAAD8AAAAAuPgYPzBoHTzF+zA/DOUbPe0cRz87k6w9eoJaPxr2FT6ZbWo/TIxjPq9Bdj91CJ4+X4p9P5AOzj4AAIA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAIA/AAAAP1+KfT+QDs4+r0F2P3UInj6ZbWo/TIxjPnqCWj8a9hU+7RxHPzuTrD3F+zA/DOUbPbj4GD8waB08AAAAPwAAAACQDs4+MGgdPHUInj4M5Rs9TIxjPjuTrD0a9hU+GvYVPjuTrD1MjGM+DOUbPXUInj4waB08kA7OPgAAAAAAAAA/MGgdPLj4GD8M5Rs9xfswPzuTrD3tHEc/GvYVPnqCWj9MjGM+mW1qP3UInj6vQXY/kA7OPl+KfT8AAAA/AACAP7j4GD9fin0/xfswP69Bdj/tHEc/mW1qP3qCWj96glo/mW1qP+0cRz+vQXY/xfswP1+KfT+4+Bg/AACAPwAAAD8AACEAAQAhACIAAQABACIAAgAiACMAAgACACMAAwAjACQAAwADACQABAAkACUABAAEACUABQAlACYABQAFACYABgAmACcABgAGACcABwAnACgABwAHACgACAAoACkACAAIACkACQApACoACQAJACoACgAqACsACgAKACsACwArACwACwALACwADAAsAC0ADAAMAC0ADQAtAC4ADQANAC4ADgAuAC8ADgAOAC8ADwAvADAADwAPADAAEAAwADEAEAAQADEAEQAxADIAEQARADIAEgAyADMAEgASADMAEwAzADQAEwATADQAFAA0ADUAFAAUADUAFQA1ADYAFQAVADYAFgA2ADcAFgAWADcAFwA3ADgAFwAXADgAGAA4ADkAGAAYADkAGQA5ADoAGQAZADoAGgA6ADsAGgAaADsAGwA7ADwAGwAbADwAHAA8AD0AHAAcAD0AHQA9AD4AHQAdAD4AHgA+AD8AHgAeAD8AHwA/AEAAHwAfAEAAIABAAEEAIABiAGMAQgBjAGQAQwBkAGUARABlAGYARQBmAGcARgBnAGgARwBoAGkASABpAGoASQBqAGsASgBrAGwASwBsAG0ATABtAG4ATQBuAG8ATgBvAHAATwBwAHEAUABxAHIAUQByAHMAUgBzAHQAUwB0AHUAVAB1AHYAVQB2AHcAVgB3AHgAVwB4AHkAWAB5AHoAWQB6AHsAWgB7AHwAWwB8AH0AXAB9AH4AXQB+AH8AXgB/AIAAXwCAAIEAYACBAIIAYQCkAKMAgwClAKQAhACmAKUAhQCnAKYAhgCoAKcAhwCpAKgAiACqAKkAiQCrAKoAigCsAKsAiwCtAKwAjACuAK0AjQCvAK4AjgCwAK8AjwCxALAAkACyALEAkQCzALIAkgC0ALMAkwC1ALQAlAC2ALUAlQC3ALYAlgC4ALcAlwC5ALgAmAC6ALkAmQC7ALoAmgC8ALsAmwC9ALwAnAC+AL0AnQC/AL4AngDAAL8AnwDBAMAAoADCAMEAoQDDAMIAogA=\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":196,\"max\":[1,1,0.02500000037252903],\"min\":[-1,-1,-0.02500000037252903],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":2,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":3,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"AccuracyRing\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"NORMAL\":1,\"TEXCOORD_0\":2},\"indices\":3,\"material\":0}]}]}", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[2]}],\"scene\":0,\"nodes\":[{\"mesh\":0},{\"mesh\":1},{\"children\":[0,1]}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2352,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":4704,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":6272,\"byteLength\":768,\"target\":34963},{\"buffer\":0,\"byteOffset\":7040,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":9392,\"byteLength\":2352,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":11744,\"byteLength\":1568,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":13312,\"byteLength\":768,\"target\":34963}],\"buffers\":[{\"byteLength\":14080,\"uri\":\"data:application/octet-stream;base64,AAAAADMzs74pXI89O9eLPbnBr74pXI89XCcJPimPpb4pXI89yx1HPtb/lL4pXI89VG19PlRtfb4pXI891v+UPssdR74pXI89KY+lPlwnCb4pXI89ucGvPjvXi70pXI89MzOzPmH6e6MpXI89ucGvPjvXiz0pXI89KY+lPlwnCT4pXI891v+UPssdRz4pXI89VG19PlRtfT4pXI89yx1HPtb/lD4pXI89XCcJPimPpT4pXI89O9eLPbnBrz4pXI89RatFJDMzsz4pXI89O9eLvbnBrz4pXI89XCcJvimPpT4pXI89yx1Hvtb/lD4pXI89VG19vlRtfT4pXI891v+UvssdRz4pXI89KY+lvlwnCT4pXI89ucGvvjvXiz0pXI89MzOzvvkrpiQpXI89ucGvvjvXi70pXI89KY+lvlwnCb4pXI891v+UvssdR74pXI89VG19vlRtfb4pXI89yx1Hvtb/lL4pXI89XCcJvimPpb4pXI89O9eLvbnBr74pXI89RavFpDMzs74pXI89AAAAADMzs74E1yOvO9eLPbnBr74E1yOvXCcJPimPpb4F1yOvyx1HPtb/lL4G1yOvVG19PlRtfb4G1yOv1v+UPssdR74H1yOvKY+lPlwnCb4I1yOvucGvPjvXi70J1yOvMzOzPq2sBqQK1yOvucGvPjvXiz0L1yOvKY+lPlwnCT4M1yOv1v+UPssdRz4N1yOvVG19PlRtfT4O1yOvyx1HPtb/lD4O1yOvXCcJPimPpT4P1yOvO9eLPbnBrz4Q1yOvRatFJDMzsz4Q1yOvO9eLvbnBrz4Q1yOvXCcJvimPpT4P1yOvyx1Hvtb/lD4O1yOvVG19vlRtfT4O1yOv1v+UvssdRz4N1yOvKY+lvlwnCT4M1yOvucGvvjvXiz0L1yOvMzOzvu9UgiQK1yOvucGvvjvXi70J1yOvKY+lvlwnCb4I1yOv1v+UvssdR74H1yOvVG19vlRtfb4G1yOvyx1Hvtb/lL4G1yOvXCcJvimPpb4F1yOvO9eLvbnBr74E1yOvRavFpDMzs74E1yOvAAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAAClcDyMpXI89AAAAADMzs74pXI89O9eLPbnBr74pXI89XCcJPimPpb4pXI89yx1HPtb/lL4pXI89VG19PlRtfb4pXI891v+UPssdR74pXI89KY+lPlwnCb4pXI89ucGvPjvXi70pXI89MzOzPmH6e6MpXI89ucGvPjvXiz0pXI89KY+lPlwnCT4pXI891v+UPssdRz4pXI89VG19PlRtfT4pXI89yx1HPtb/lD4pXI89XCcJPimPpT4pXI89O9eLPbnBrz4pXI89RatFJDMzsz4pXI89O9eLvbnBrz4pXI89XCcJvimPpT4pXI89yx1Hvtb/lD4pXI89VG19vlRtfT4pXI891v+UvssdRz4pXI89KY+lvlwnCT4pXI89ucGvvjvXiz0pXI89MzOzvvkrpiQpXI89ucGvvjvXi70pXI89KY+lvlwnCb4pXI891v+UvssdR74pXI89VG19vlRtfb4pXI89yx1Hvtb/lL4pXI89XCcJvimPpb4pXI89O9eLvbnBr74pXI89RavFpDMzs74pXI89AAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOvAAAAAClcD6MK1yOv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AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgCUAAIA/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgKUAAIC/AAAAAAAAgD8AAAA9AACAPwAAgD0AAIA/AADAPQAAgD8AAAA+AACAPwAAID4AAIA/AABAPgAAgD8AAGA+AACAPwAAgD4AAIA/AACQPgAAgD8AAKA+AACAPwAAsD4AAIA/AADAPgAAgD8AANA+AACAPwAA4D4AAIA/AADwPgAAgD8AAAA/AACAPwAACD8AAIA/AAAQPwAAgD8AABg/AACAPwAAID8AAIA/AAAoPwAAgD8AADA/AACAPwAAOD8AAIA/AABAPwAAgD8AAEg/AACAPwAAUD8AAIA/AABYPwAAgD8AAGA/AACAPwAAaD8AAIA/AABwPwAAgD8AAHg/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAA9AAAAAAAAgD0AAAAAAADAPQAAAAAAAAA+AAAAAAAAID4AAAAAAABAPgAAAAAAAGA+AAAAAAAAgD4AAAAAAACQPgAAAAAAAKA+AAAAAAAAsD4AAAAAAADAPgAAAAAAANA+AAAAAAAA4D4AAAAAAADwPgAAAAAAAAA/AAAAAAAACD8AAAAAAAAQPwAAAAAAABg/AAAAAAAAID8AAAAAAAAoPwAAAAAAADA/AAAAAAAAOD8AAAAAAABAPwAAAAAAAEg/AAAAAAAAUD8AAAAAAABYPwAAAAAAAGA/AAAAAAAAaD8AAAAAAABwPwAAAAAAAHg/AAAAAAAAgD8AAAAAAAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/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CtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAACtejIZqZmT0AAAAAKVyPvpqZmT3Fvl89+pqMvpqZmT0scts9h3KEvpqZmT0ISx8+I2ZuvpqZmT3dvUo+3b1KvpqZmT0jZm4+CEsfvpqZmT2HcoQ+LHLbvZqZmT36mow+xb5fvZqZmT0pXI8+LeWTo5qZmT36mow+xb5fPZqZmT2HcoQ+LHLbPZqZmT0jZm4+CEsfPpqZmT3dvUo+3b1KPpqZmT0ISx8+I2ZuPpqZmT0scts9h3KEPpqZmT3Fvl89+pqMPpqZmT2eIh4kKVyPPpqZmT3Fvl+9+pqMPpqZmT0sctu9h3KEPpqZmT0ISx++I2ZuPpqZmT3dvUq+3b1KPpqZmT0jZm6+CEsfPpqZmT2HcoS+LHLbPZqZmT36moy+xb5fPZqZmT0pXI++pVJyJJqZmT36moy+xb5fvZqZmT2HcoS+LHLbvZqZmT0jZm6+CEsfvpqZmT3dvUq+3b1KvpqZmT0ISx++I2ZuvpqZmT0sctu9h3KEvpqZmT3Fvl+9+pqMvpqZmT2eIp6kKVyPvpqZmT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAACtejobgehT0AAAAA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AACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACAJQAAgD8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACApQAAgL8AAAAAAACAPwAAAD0AAIA/AACAPQAAgD8AAMA9AACAPwAAAD4AAIA/AAAgPgAAgD8AAEA+AACAPwAAYD4AAIA/AACAPgAAgD8AAJA+AACAPwAAoD4AAIA/AACwPgAAgD8AAMA+AACAPwAA0D4AAIA/AADgPgAAgD8AAPA+AACAPwAAAD8AAIA/AAAIPwAAgD8AABA/AACAPwAAGD8AAIA/AAAgPwAAgD8AACg/AACAPwAAMD8AAIA/AAA4PwAAgD8AAEA/AACAPwAASD8AAIA/AABQPwAAgD8AAFg/AACAPwAAYD8AAIA/AABoPwAAgD8AAHA/AACAPwAAeD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAD0AAAAAAACAPQAAAAAAAMA9AAAAAAAAAD4AAAAAAAAgPgAAAAAAAEA+AAAAAAAAYD4AAAAAAACAPgAAAAAAAJA+AAAAAAAAoD4AAAAAAACwPgAAAAAAAMA+AAAAAAAA0D4AAAAAAADgPgAAAAAAAPA+AAAAAAAAAD8AAAAAAAAIPwAAAAAAABA/AAAAAAAAGD8AAAAAAAAgPwAAAAAAACg/AAAAAAAAMD8AAAAAAAA4PwAAAAAAAEA/AAAAAAAASD8AAAAAAABQPwAAAAAAAFg/AAAAAAAAYD8AAAAAAABoPwAAAAAAAHA/AAAAAAAAeD8AAAAAAACAPwAAAAAAAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AACAPwAAAD9fin0/uPgYP69Bdj/F+zA/mW1qP+0cRz96glo/eoJaP+0cRz+ZbWo/xfswP69Bdj+4+Bg/X4p9PwAAAD8AAIA/kA7OPl+KfT91CJ4+r0F2P0yMYz6ZbWo/GvYVPnqCWj87k6w97RxHPwzlGz3F+zA/MGgdPLj4GD8AAAAAAAAAPzBoHTyQDs4+DOUbPXUInj47k6w9TIxjPhr2FT4a9hU+TIxjPjuTrD11CJ4+DOUbPZAOzj4waB08AAAAPwAAAAC4+Bg/MGgdPMX7MD8M5Rs97RxHPzuTrD16glo/GvYVPpltaj9MjGM+r0F2P3UInj5fin0/kA7OPgAAgD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAgD8AAAA/X4p9P5AOzj6vQXY/dQiePpltaj9MjGM+eoJaPxr2FT7tHEc/O5OsPcX7MD8M5Rs9uPgYPzBoHTwAAAA/AAAAAJAOzj4waB08dQiePgzlGz1MjGM+O5OsPRr2FT4a9hU+O5OsPUyMYz4M5Rs9dQiePjBoHTyQDs4+AAAAAAAAAD8waB08uPgYPwzlGz3F+zA/O5OsPe0cRz8a9hU+eoJaP0yMYz6ZbWo/dQiePq9Bdj+QDs4+X4p9PwAAAD8AAIA/uPgYP1+KfT/F+zA/r0F2P+0cRz+ZbWo/eoJaP3qCWj+ZbWo/7RxHP69Bdj/F+zA/X4p9P7j4GD8AAIA/AAAAPwAAIQABACEAIgABAAEAIgACACIAIwACAAIAIwADACMAJAADAAMAJAAEACQAJQAEAAQAJQAFACUAJgAFAAUAJgAGACYAJwAGAAYAJwAHACcAKAAHAAcAKAAIACgAKQAIAAgAKQAJACkAKgAJAAkAKgAKACoAKwAKAAoAKwALACsALAALAAsALAAMACwALQAMAAwALQANAC0ALgANAA0ALgAOAC4ALwAOAA4ALwAPAC8AMAAPAA8AMAAQADAAMQAQABAAMQARADEAMgARABEAMgASADIAMwASABIAMwATADMANAATABMANAAUADQANQAUABQANQAVADUANgAVABUANgAWADYANwAWABYANwAXADcAOAAXABcAOAAYADgAOQAYABgAOQAZADkAOgAZABkAOgAaADoAOwAaABoAOwAbADsAPAAbABsAPAAcADwAPQAcABwAPQAdAD0APgAdAB0APgAeAD4APwAeAB4APwAfAD8AQAAfAB8AQAAgAEAAQQAgAGIAYwBCAGMAZABDAGQAZQBEAGUAZgBFAGYAZwBGAGcAaABHAGgAaQBIAGkAagBJAGoAawBKAGsAbABLAGwAbQBMAG0AbgBNAG4AbwBOAG8AcABPAHAAcQBQAHEAcgBRAHIAcwBSAHMAdABTAHQAdQBUAHUAdgBVAHYAdwBWAHcAeABXAHgAeQBYAHkAegBZAHoAewBaAHsAfABbAHwAfQBcAH0AfgBdAH4AfwBeAH8AgABfAIAAgQBgAIEAggBhAKQAowCDAKUApACEAKYApQCFAKcApgCGAKgApwCHAKkAqACIAKoAqQCJAKsAqgCKAKwAqwCLAK0ArACMAK4ArQCNAK8ArgCOALAArwCPALEAsACQALIAsQCRALMAsgCSALQAswCTALUAtACUALYAtQCVALcAtgCWALgAtwCXALkAuACYALoAuQCZALsAugCaALwAuwCbAL0AvACcAL4AvQCdAL8AvgCeAMAAvwCfAMEAwACgAMIAwQChAMMAwgCiAA==\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":196,\"max\":[0.3499999940395355,0.3499999940395355,0.07000000029802322],\"min\":[-0.3499999940395355,-0.3499999940395355,-1.4901169187453434e-10],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":2,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":3,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"},{\"bufferView\":4,\"componentType\":5126,\"count\":196,\"max\":[0.2800000011920929,0.2800000011920929,0.07500000298023224],\"min\":[-0.2800000011920929,-0.2800000011920929,0.06499999761581421],\"type\":\"VEC3\"},{\"bufferView\":5,\"componentType\":5126,\"count\":196,\"max\":[1,1,1],\"min\":[-1,-1,-1],\"type\":\"VEC3\"},{\"bufferView\":6,\"componentType\":5126,\"count\":196,\"max\":[1,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":7,\"componentType\":5123,\"count\":384,\"max\":[195],\"min\":[0],\"type\":\"SCALAR\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.913098651791473,0.913098651791473,0.913098651791473,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"Border\"},{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1},\"alphaMode\":\"BLEND\",\"name\":\"Inner\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"NORMAL\":1,\"TEXCOORD_0\":2},\"indices\":3,\"material\":0}]},{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":4,\"NORMAL\":5,\"TEXCOORD_0\":6},\"indices\":7,\"material\":1}]}]}", "{\"asset\":{\"version\":\"2.0\"},\"scenes\":[{\"nodes\":[0]}],\"scene\":0,\"nodes\":[{\"mesh\":0}],\"bufferViews\":[{\"buffer\":0,\"byteOffset\":0,\"byteLength\":2880,\"target\":34962,\"byteStride\":12},{\"buffer\":0,\"byteOffset\":2880,\"byteLength\":1920,\"target\":34962,\"byteStride\":8},{\"buffer\":0,\"byteOffset\":4800,\"byteLength\":2880,\"target\":34962,\"byteStride\":12}],\"buffers\":[{\"byteLength\":7680,\"uri\":\"data:application/octet-stream;base64,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AACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAgD8AAAAAAACAPwAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAgAAAAIAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/ARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAAARlkP3Bx6L4AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAA8wQ1P/MENb8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAcHHoPgEZZL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgPiTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAAAAXzAgviTZfL8AAACAXzAgviTZfL8AAACAXzAgviTZfL8AAACAcHHovgEZZL8AAAAAcHHovgEZZL8AAAAAcHHovgEZZL8AAAAAcHHovgEZZL8AAACAcHHovgEZZL8AAACAcHHovgEZZL8AAACA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAAAA8wQ1v/MENb8AAACA8wQ1v/MENb8AAACA8wQ1v/MENb8AAACAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAAAAARlkv3Bx6L4AAACAARlkv3Bx6L4AAACAARlkv3Bx6L4AAACAJNl8v18wIL4AAAAAJNl8v18wIL4AAAAAJNl8v18wIL4AAAAAJNl8v18wIL4AAACAJNl8v18wIL4AAACAJNl8v18wIL4AAACAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAAX8V8P5kgIr4AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAA8ps6Ppi2ez8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAu6gFPlTPfT8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAx66gPfo1fz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWPIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAaHLWvIvpfz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAx66gvfo1fz8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAAu6gFvlTPfT8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAA8ps6vpi2ez8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAAZwxvvjvteD8AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAAAA6kZ3v++DhL4AAACA6kZ3v++DhL4AAACA6kZ3v++DhL4AAACAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAAJNl8P18wIL4AAAAA\"}],\"accessors\":[{\"bufferView\":0,\"componentType\":5126,\"count\":240,\"max\":[0.572234570980072,1.4460784196853638,0.10000000149011612],\"min\":[-0.7123466730117798,0,0],\"type\":\"VEC3\"},{\"bufferView\":1,\"componentType\":5126,\"count\":240,\"max\":[0,1],\"min\":[0,0],\"type\":\"VEC2\"},{\"bufferView\":2,\"componentType\":5126,\"count\":240,\"max\":[0.9876883029937744,0.9996573328971863,1],\"min\":[-0.9876883029937744,-0.9876883029937744,-1],\"type\":\"VEC3\"}],\"materials\":[{\"pbrMetallicRoughness\":{\"baseColorFactor\":[0.015996293361446288,0.13286832154414627,1,1],\"metallicFactor\":0,\"roughnessFactor\":1,\"baseColorTexture\":{\"index\":0,\"texCoord\":0}},\"alphaMode\":\"BLEND\",\"name\":\"HeadingCone\"}],\"textures\":[{\"sampler\":0,\"source\":0}],\"samplers\":[{\"magFilter\":9729,\"minFilter\":9729,\"wrapS\":33071,\"wrapT\":33071}],\"images\":[{\"mimeType\":\"image/png\",\"uri\":\"data:image/png;base64,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\"}],\"meshes\":[{\"primitives\":[{\"mode\":4,\"attributes\":{\"POSITION\":0,\"TEXCOORD_0\":1,\"NORMAL\":2},\"material\":0}]}]}", "import { haversineDistance } from '@packages/internal/common/utils';\nimport type {\n\tBlueDotPositionUpdateWithFloor,\n\tBlueDotState,\n\tBlueDotStatus,\n\tBlueDotUpdateState,\n\tGeolocationPositionExtended,\n} from './types';\nimport { MIN_BLUEDOT_RADIUS } from './constants';\n\nexport function deepMergeState(existing: BlueDotState, update?: BlueDotUpdateState): BlueDotState {\n\tif (update == null) {\n\t\treturn existing;\n\t}\n\n\tconst result: BlueDotState = { ...existing };\n\n\tfor (const key in update) {\n\t\tconst value = update[key as keyof BlueDotUpdateState];\n\t\tif (value !== undefined && key !== 'accuracyRing' && key !== 'heading') {\n\t\t\t(result as any)[key] = value;\n\t\t}\n\t}\n\n\tif (update.accuracyRing != null) {\n\t\tresult.accuracyRing = { ...existing.accuracyRing };\n\t\tfor (const key in update.accuracyRing) {\n\t\t\tconst value = update.accuracyRing[key as keyof typeof update.accuracyRing];\n\t\t\tif (value !== undefined) {\n\t\t\t\t(result.accuracyRing as any)[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (update.heading != null) {\n\t\tresult.heading = { ...existing.heading };\n\t\tfor (const key in update.heading) {\n\t\t\tconst value = update.heading[key as keyof typeof update.heading];\n\t\t\tif (value !== undefined) {\n\t\t\t\t(result.heading as any)[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Finds the intersection of a geographic line segment and a point.\n *\n * @param start - The start coordinate of the line segment.\n * @param end - The end coordinate of the line segment.\n * @param position - The position to check for intersection with the line segment.\n */\nexport function getPointLineIntersection(\n\t[startLongitude, startLatitude]: number[],\n\t[endLongitude, endLatitude]: number[],\n\t[positionLongitude, positionLatitude]: number[],\n) {\n\tconst dx = endLongitude - startLongitude;\n\tconst dy = endLatitude - startLatitude;\n\tconst segmentLengthSquared = dx ** 2 + dy ** 2;\n\n\tif (segmentLengthSquared === 0) {\n\t\t// the segment is a point, so no intersection\n\t\treturn;\n\t}\n\n\t// calculate the proportion along the segment (0 to 1) that the position is closest to\n\tconst proportion =\n\t\t((positionLongitude - startLongitude) * dx + (positionLatitude - startLatitude) * dy) / segmentLengthSquared;\n\n\t// project the intersection point onto the segment\n\tlet intersection: [number, number];\n\tif (proportion <= 0) {\n\t\tintersection = [startLongitude, startLatitude];\n\t} else if (proportion >= 1) {\n\t\tintersection = [endLongitude, endLatitude];\n\t} else {\n\t\tintersection = [startLongitude + proportion * dx, startLatitude + proportion * dy];\n\t}\n\n\t// calculate the distance from the position to the intersection\n\tconst distance = haversineDistance([positionLongitude, positionLatitude], intersection);\n\n\treturn {\n\t\tproportion: Math.max(0, Math.min(1, proportion)),\n\t\tintersection,\n\t\tdistance,\n\t};\n}\n\n/**\n * Finds the nearest segment of two coordinates on a path which the BlueDot position is closest to.\n *\n * @param pathCoordinates - The coordinates of the path to check.\n * @param position - The position of the BlueDot.\n */\nexport function findBlueDotOnPath(pathCoordinates: number[][], position: number[]) {\n\tif (pathCoordinates == null || pathCoordinates.length < 2) {\n\t\treturn;\n\t}\n\n\t// smallest distance found so far\n\tlet minDistance = Number.MAX_SAFE_INTEGER;\n\t// lon/lat of the intersection point\n\tlet nearestIntersection: [number, number] | undefined;\n\t// index of the first coordinate of the segment\n\tlet nearestSegmentIndex = 0;\n\t// how far along the segment the BlueDot is\n\tlet nearestProportion = 0;\n\n\t// check each segment of the path -- path should be simplified ahead of time\n\tfor (let i = 0; i < pathCoordinates.length - 1; i++) {\n\t\tconst start = pathCoordinates[i];\n\t\tconst end = pathCoordinates[i + 1];\n\n\t\tconst pointOnLine = getPointLineIntersection(start, end, position);\n\n\t\tif (pointOnLine == null) continue;\n\n\t\tif (pointOnLine.distance < minDistance) {\n\t\t\tminDistance = pointOnLine.distance;\n\t\t\tnearestIntersection = pointOnLine.intersection;\n\t\t\tnearestSegmentIndex = i;\n\t\t\tnearestProportion = pointOnLine.proportion;\n\t\t}\n\t}\n\n\tif (!nearestIntersection) {\n\t\treturn;\n\t}\n\n\treturn {\n\t\tintersection: nearestIntersection,\n\t\tdistance: minDistance,\n\t\tsegmentIndex: nearestSegmentIndex,\n\t\tproportion: nearestProportion,\n\t};\n}\n\nexport function getPositionWithOverrides(\n\tupdate: BlueDotPositionUpdateWithFloor | undefined,\n\toverrides: BlueDotPositionUpdateWithFloor | undefined,\n) {\n\tif (overrides == null) {\n\t\treturn update;\n\t}\n\n\tconst position: BlueDotPositionUpdateWithFloor = {\n\t\tlatitude: update?.latitude,\n\t\tlongitude: update?.longitude,\n\t\taccuracy: update?.accuracy,\n\t\tfloor: update?.floor,\n\t\theading: update?.heading,\n\t\ttimestamp: update?.timestamp,\n\t};\n\tif ('latitude' in overrides) {\n\t\tposition.latitude =\n\t\t\toverrides?.latitude == null || overrides.latitude === 'device' ? update?.latitude : overrides.latitude;\n\t}\n\tif ('longitude' in overrides) {\n\t\tposition.longitude =\n\t\t\toverrides.longitude == null || overrides.longitude === 'device' ? update?.longitude : overrides.longitude;\n\t}\n\tif ('accuracy' in overrides) {\n\t\tposition.accuracy = overrides.accuracy === 'device' ? update?.accuracy : overrides.accuracy;\n\t}\n\tif ('floor' in overrides) {\n\t\tposition.floor = overrides.floor === 'device' ? update?.floor : overrides.floor;\n\t}\n\tif ('heading' in overrides) {\n\t\tposition.heading = overrides.heading === 'device' ? update?.heading : overrides.heading;\n\t}\n\tif ('timestamp' in overrides) {\n\t\tposition.timestamp = overrides.timestamp;\n\t}\n\n\treturn position;\n}\n\n/**\n * Compute whether a position is within circular pan bounds.\n * @param positionLongitude The longitude to test\n * @param positionLatitude The latitude to test\n * @param radius The radius in meters\n * @param center The center coordinate\n * @returns True if within bounds, false otherwise\n */\nexport function isWithinPanBounds(\n\t{ longitude: positionLongitude, latitude: positionLatitude }: { longitude: number; latitude: number },\n\t{ radius, center }: { radius: number; center: { longitude: number; latitude: number } },\n): boolean {\n\tconst distance = haversineDistance([positionLongitude, positionLatitude], [center.longitude, center.latitude]);\n\n\treturn distance <= radius;\n}\n\n/**\n * Compute BlueDot model scale from desired pixel radius and current meters-per-pixel.\n * Ensures a minimum on-map size using MIN_BLUEDOT_RADIUS.\n * @param radius Desired BlueDot radius in pixels\n * @param metersPerPixel Current meters-per-pixel value\n */\nexport function computeBlueDotScale(radius: number, metersPerPixel: number): number {\n\tconst scale = radius / (MIN_BLUEDOT_RADIUS / metersPerPixel);\n\n\treturn Math.max(scale, 1);\n}\n\n/**\n * Ease-out cubic function used for smooth transitions.\n * @example\n * ```ts\n * const eased = easeOutCubic(0.5);\n * ```\n */\nexport function easeOutCubic(t: number): number {\n\treturn 1 - Math.pow(1 - t, 3);\n}\n\n/**\n * Interpolate altitude between a start altitude and target altitude using time-based easing.\n * @param now Current timestamp (ms)\n * @param startTime Transition start timestamp (ms)\n * @param duration Transition duration (ms)\n * @param startAltitude Altitude at the start of the transition\n * @param targetAltitude Current target altitude to reach\n * @returns The interpolated altitude and completion flag\n */\nexport function interpolateAltitude(\n\tnow: number,\n\tstartTime: number | undefined,\n\tduration: number,\n\tstartAltitude: number | undefined,\n\ttargetAltitude: number,\n): { altitude: number; done: boolean } {\n\tif (startTime == null || startAltitude == null) {\n\t\treturn { altitude: targetAltitude, done: true };\n\t}\n\n\tconst elapsed = now - startTime;\n\tconst progress = Math.min(elapsed / duration, 1);\n\n\tif (progress < 1) {\n\t\tconst eased = easeOutCubic(progress);\n\t\tconst altitude = startAltitude + (targetAltitude - startAltitude) * eased;\n\n\t\treturn { altitude, done: false };\n\t}\n\n\treturn { altitude: targetAltitude, done: true };\n}\n\nexport function shouldShowHeadingCone(\n\tstate: BlueDotStatus,\n\theading: GeolocationPositionExtended['coords']['heading'] | undefined,\n\tdisplayWhenInactive: boolean,\n) {\n\treturn heading != null && (state === 'active' || (state === 'inactive' && displayWhenInactive));\n}\n\nexport function shouldShowAccuracyRing(\n\tstate: BlueDotStatus,\n\taccuracy: GeolocationPositionExtended['coords']['accuracy'] | undefined,\n): boolean {\n\treturn state === 'active' && accuracy != null;\n}\n", "import z from 'zod';\n\nexport const geolocationPositionSchema = z.object({\n\tcoords: z.object({\n\t\tlatitude: z.number(),\n\t\tlongitude: z.number(),\n\t\taccuracy: z.number(),\n\t\taltitude: z.number().optional().nullable(),\n\t\taltitudeAccuracy: z.number().optional().nullable(),\n\t\theading: z.number().optional().nullable(),\n\t\tspeed: z.number().optional().nullable(),\n\t\tfloorLevel: z.number().optional().nullable(),\n\t}),\n\ttimestamp: z.number(),\n});\n\nexport const positionSchema = z.object({\n\tlatitude: z.number(),\n\tlongitude: z.number(),\n\tfloor: z.any().optional(),\n\taccuracy: z.number().optional(),\n\theading: z.number().optional().nullable(), // heading can be nullable due to the Geolocation API\n\ttimestamp: z.number().optional(),\n});\n", "import type { StateMachine } from './types';\n\nexport const stateMachine: StateMachine = {\n\thidden: {\n\t\tactions: {\n\t\t\tenable: 'hidden',\n\t\t\terror: 'hidden',\n\t\t\t'position-update': 'active',\n\t\t\tinitialize: 'inactive',\n\t\t\tdisable: 'disabled',\n\t\t\ttimeout: 'hidden',\n\t\t},\n\t},\n\tactive: {\n\t\tactions: {\n\t\t\tenable: 'active',\n\t\t\tdisable: 'disabled',\n\t\t\t'position-update': 'active',\n\t\t\terror: 'inactive',\n\t\t\ttimeout: 'inactive',\n\t\t},\n\t},\n\tinactive: {\n\t\tactions: {\n\t\t\tenable: 'inactive',\n\t\t\tdisable: 'disabled',\n\t\t\t'position-update': 'active',\n\t\t\terror: 'inactive',\n\t\t\ttimeout: 'inactive',\n\t\t},\n\t},\n\tdisabled: {\n\t\tactions: {\n\t\t\tenable: 'hidden',\n\t\t\tdisable: 'disabled',\n\t\t},\n\t},\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["simplify", "Coordinate", "label", "z", "BlueDot", "Coordinate", "z", "position", "simplify"]
7
7
  }
package/lib/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  BlueDot,
3
3
  init_define_process
4
- } from "./chunk-EEQMR2QG.js";
4
+ } from "./chunk-RONFZDXM.js";
5
5
 
6
6
  // src/index.ts
7
7
  init_define_process();
@@ -2,7 +2,7 @@ import {
2
2
  BlueDot,
3
3
  __name,
4
4
  init_define_process
5
- } from "../chunk-EEQMR2QG.js";
5
+ } from "../chunk-RONFZDXM.js";
6
6
 
7
7
  // src/react/index.ts
8
8
  init_define_process();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mappedin/blue-dot",
3
- "version": "6.0.1-beta.59",
3
+ "version": "6.0.1-beta.60",
4
4
  "homepage": "https://developer.mappedin.com/",
5
5
  "private": false,
6
6
  "main": "lib/esm/index.js",
@@ -43,9 +43,9 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "react": ">=16.8.0",
46
- "@mappedin/mappedin-js": "^6.1.1",
47
- "@mappedin/react-sdk": "^6.1.1",
48
- "@mappedin/react-native-sdk": "^6.1.1"
46
+ "@mappedin/mappedin-js": "^6.2.0",
47
+ "@mappedin/react-native-sdk": "^6.2.0",
48
+ "@mappedin/react-sdk": "^6.2.0"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "@mappedin/react-native-sdk": {
@@ -65,7 +65,7 @@
65
65
  "scripts": {
66
66
  "start": "pnpm build && concurrently \"node scripts/build.mjs --watchChanges\" \"node scripts/start.mjs\"",
67
67
  "build:deps": "RN_BUILD=true npx turbo build --filter=@mappedin/blue-dot --ui stream",
68
- "build": "pnpm clean && tsc -b && node scripts/build.mjs",
68
+ "build": "pnpm clean && tsc -b tsconfig.build.json && node scripts/build.mjs",
69
69
  "build:prod": "cross-env NODE_ENV=production pnpm build && pnpm build:rn",
70
70
  "build:rn": "cross-env RN_BUILD=true pnpm build",
71
71
  "types": "tsc -b",