@tonybfox/threejs-tools 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +321 -0
- package/dist/asset-loader/index.cjs +376 -0
- package/dist/asset-loader/index.cjs.map +1 -0
- package/dist/asset-loader/index.d.mts +101 -0
- package/dist/asset-loader/index.d.ts +101 -0
- package/dist/asset-loader/index.mjs +7 -0
- package/dist/asset-loader/index.mjs.map +1 -0
- package/dist/camera/index.cjs +313 -0
- package/dist/camera/index.cjs.map +1 -0
- package/dist/camera/index.d.mts +82 -0
- package/dist/camera/index.d.ts +82 -0
- package/dist/camera/index.mjs +7 -0
- package/dist/camera/index.mjs.map +1 -0
- package/dist/chunk-5DP6WDB3.mjs +1161 -0
- package/dist/chunk-5DP6WDB3.mjs.map +1 -0
- package/dist/chunk-BJKSICFA.mjs +1579 -0
- package/dist/chunk-BJKSICFA.mjs.map +1 -0
- package/dist/chunk-BYRZCHE7.mjs +277 -0
- package/dist/chunk-BYRZCHE7.mjs.map +1 -0
- package/dist/chunk-EIROAPF7.mjs +387 -0
- package/dist/chunk-EIROAPF7.mjs.map +1 -0
- package/dist/chunk-EQDOX34V.mjs +164 -0
- package/dist/chunk-EQDOX34V.mjs.map +1 -0
- package/dist/chunk-IIAZ2WJJ.mjs +405 -0
- package/dist/chunk-IIAZ2WJJ.mjs.map +1 -0
- package/dist/chunk-L4VIIJZD.mjs +340 -0
- package/dist/chunk-L4VIIJZD.mjs.map +1 -0
- package/dist/chunk-P35QJCOG.mjs +339 -0
- package/dist/chunk-P35QJCOG.mjs.map +1 -0
- package/dist/chunk-R64RVBRM.mjs +394 -0
- package/dist/chunk-R64RVBRM.mjs.map +1 -0
- package/dist/compass/index.cjs +375 -0
- package/dist/compass/index.cjs.map +1 -0
- package/dist/compass/index.d.mts +58 -0
- package/dist/compass/index.d.ts +58 -0
- package/dist/compass/index.mjs +7 -0
- package/dist/compass/index.mjs.map +1 -0
- package/dist/grid/index.cjs +200 -0
- package/dist/grid/index.cjs.map +1 -0
- package/dist/grid/index.d.mts +43 -0
- package/dist/grid/index.d.ts +43 -0
- package/dist/grid/index.mjs +7 -0
- package/dist/grid/index.mjs.map +1 -0
- package/dist/index.cjs +5049 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.mjs +47 -0
- package/dist/index.mjs.map +1 -0
- package/dist/measurements/index.cjs +1198 -0
- package/dist/measurements/index.cjs.map +1 -0
- package/dist/measurements/index.d.mts +449 -0
- package/dist/measurements/index.d.ts +449 -0
- package/dist/measurements/index.mjs +9 -0
- package/dist/measurements/index.mjs.map +1 -0
- package/dist/sunlight/index.cjs +441 -0
- package/dist/sunlight/index.cjs.map +1 -0
- package/dist/sunlight/index.d.mts +92 -0
- package/dist/sunlight/index.d.ts +92 -0
- package/dist/sunlight/index.mjs +7 -0
- package/dist/sunlight/index.mjs.map +1 -0
- package/dist/terrain/index.cjs +423 -0
- package/dist/terrain/index.cjs.map +1 -0
- package/dist/terrain/index.d.mts +219 -0
- package/dist/terrain/index.d.ts +219 -0
- package/dist/terrain/index.mjs +7 -0
- package/dist/terrain/index.mjs.map +1 -0
- package/dist/transform-controls/index.cjs +1587 -0
- package/dist/transform-controls/index.cjs.map +1 -0
- package/dist/transform-controls/index.d.mts +162 -0
- package/dist/transform-controls/index.d.ts +162 -0
- package/dist/transform-controls/index.mjs +13 -0
- package/dist/transform-controls/index.mjs.map +1 -0
- package/dist/view-helper/index.cjs +430 -0
- package/dist/view-helper/index.cjs.map +1 -0
- package/dist/view-helper/index.d.mts +75 -0
- package/dist/view-helper/index.d.ts +75 -0
- package/dist/view-helper/index.mjs +7 -0
- package/dist/view-helper/index.mjs.map +1 -0
- package/package.json +124 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../packages/asset-loader/src/AssetLoader.ts","../packages/camera/src/DualCameraControls.ts","../packages/compass/src/CompassOverlay.ts","../packages/grid/src/InfiniteGrid.ts","../packages/measurements/src/MeasurementTool.ts","../packages/measurements/src/MeasurementTypes.ts","../packages/sunlight/src/SunLightTool.ts","../packages/terrain/src/TerrainTool.ts","../packages/transform-controls/src/TransformControls.ts","../packages/view-helper/src/ViewHelper.ts"],"sourcesContent":["export * from '../packages/asset-loader/src'\nexport * from '../packages/camera/src'\nexport * from '../packages/compass/src'\nexport * from '../packages/grid/src'\nexport * from '../packages/measurements/src'\nexport * from '../packages/sunlight/src'\nexport * from '../packages/terrain/src'\nexport * from '../packages/transform-controls/src'\nexport * from '../packages/view-helper/src'\n","import * as THREE from 'three'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'\nimport { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'\n\n// Event types for asset loading\ninterface AssetLoaderEventMap {\n progress: { loaded: number; total: number; percentage: number }\n loaded: { asset: THREE.Object3D }\n error: { error: Error }\n placeholderCreated: { placeholder: THREE.Object3D }\n lowResLoaded: { lowRes: THREE.Object3D }\n}\n\nexport type AssetType = 'gltf' | 'fbx' | 'obj'\n\nexport interface AssetLoaderOptions {\n type: AssetType\n url: string\n size?: [number, number, number] // Optional size for placeholder\n lowResUrl?: string // Optional low-res model URL\n enableCaching?: boolean\n placeholderColor?: number\n placeholderOpacity?: number\n errorColor?: number // Color to use when loading fails\n errorOpacity?: number // Opacity to use when loading fails\n}\n\nexport class AssetLoader extends THREE.EventDispatcher<AssetLoaderEventMap> {\n private cache: Map<string, THREE.Object3D> = new Map()\n private gltfLoader: GLTFLoader\n private fbxLoader: FBXLoader\n private objLoader: OBJLoader\n private placeholder: THREE.Object3D | null = null\n private loadedAsset: THREE.Object3D | null = null\n private lowResAsset: THREE.Object3D | null = null\n private errorColor: number = 0xff4444\n private errorOpacity: number = 0.5\n\n constructor() {\n super()\n this.gltfLoader = new GLTFLoader()\n this.fbxLoader = new FBXLoader()\n this.objLoader = new OBJLoader()\n }\n\n /**\n * Create a placeholder cube with shader effect\n */\n private createPlaceholder(\n size: [number, number, number],\n color: number = 0x4fc3f7,\n opacity: number = 0.3\n ): THREE.Object3D {\n const [width, height, depth] = size\n const geometry = new THREE.BoxGeometry(width, height, depth)\n\n // Custom shader material with fill-up effect\n const material = new THREE.ShaderMaterial({\n side: THREE.DoubleSide,\n depthWrite: false,\n blending: THREE.AdditiveBlending,\n transparent: true,\n uniforms: {\n color: { value: new THREE.Color(color) },\n opacity: { value: opacity },\n fillProgress: { value: 0.0 },\n time: { value: 0.0 },\n isError: { value: 0.0 },\n },\n vertexShader: `\n varying vec3 vPosition;\n void main() {\n vPosition = position;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n `,\n fragmentShader: `\n uniform vec3 color;\n uniform float opacity;\n uniform float fillProgress;\n uniform float time;\n uniform float isError;\n varying vec3 vPosition;\n \n void main() {\n float normalizedY = (vPosition.y + 1.0) / 2.0; // Normalize from -1,1 to 0,1\n float alpha = opacity;\n \n // Create fill-up effect\n if (normalizedY > fillProgress) {\n alpha *= 0.3; // Reduce opacity for unfilled parts\n }\n \n // Error state effects\n if (isError > 0.5) {\n // Add pulsing effect for error state\n float pulse = 0.5 + 0.5 * sin(time * 4.0);\n alpha *= (0.3 + 0.4 * pulse);\n \n // Add error pattern\n float stripe = sin(vPosition.y * 20.0 + time * 2.0);\n alpha *= (0.7 + 0.3 * step(0.0, stripe));\n }\n \n // Add edge glow\n vec3 viewDirection = normalize(cameraPosition - vPosition);\n float edgeIntensity = pow(1.0 - abs(dot(viewDirection, normalize(vPosition))), 2.0);\n \n vec3 finalColor = color + edgeIntensity * 0.5;\n gl_FragColor = vec4(finalColor, alpha);\n }\n `,\n })\n\n const mesh = new THREE.Mesh(geometry, material)\n this.positionAssetAtBottomCenter(mesh)\n return mesh\n }\n\n /**\n * Update placeholder fill progress based on loading progress\n */\n private updatePlaceholder(progress: number) {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms && material.uniforms.fillProgress) {\n material.uniforms.fillProgress.value = progress\n }\n }\n }\n\n /**\n * Set placeholder to error state with configurable color and opacity\n */\n private setPlaceholderError() {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms) {\n // Change to error color\n if (material.uniforms.color) {\n material.uniforms.color.value = new THREE.Color(this.errorColor)\n }\n // Set error opacity\n if (material.uniforms.opacity) {\n material.uniforms.opacity.value = this.errorOpacity\n }\n // Set fill progress to indicate failure\n if (material.uniforms.fillProgress) {\n material.uniforms.fillProgress.value = 0.0\n }\n // Enable error state\n if (material.uniforms.isError) {\n material.uniforms.isError.value = 1.0\n }\n }\n }\n }\n\n /**\n * Update placeholder animation time (call this in your render loop)\n */\n public updatePlaceholderAnimation(deltaTime: number) {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms && material.uniforms.time) {\n material.uniforms.time.value += deltaTime\n }\n }\n }\n\n /**\n * Reposition an asset so that its bottom-center sits at the local origin.\n */\n private positionAssetAtBottomCenter(object: THREE.Object3D) {\n object.updateMatrixWorld(true)\n\n const boundingBox = new THREE.Box3().setFromObject(object)\n if (boundingBox.isEmpty()) {\n return\n }\n\n const center = boundingBox.getCenter(new THREE.Vector3())\n const bottomCenter = new THREE.Vector3(\n center.x,\n boundingBox.min.y + 0.01,\n center.z\n )\n\n if (\n !Number.isFinite(bottomCenter.x) ||\n !Number.isFinite(bottomCenter.y) ||\n !Number.isFinite(bottomCenter.z)\n ) {\n return\n }\n\n object.position.sub(bottomCenter)\n object.userData.bottomCenterOffset = bottomCenter\n object.updateMatrixWorld(true)\n }\n\n private ensureBottomCenterOffset(\n object: THREE.Object3D\n ): THREE.Vector3 | null {\n const offset = object.userData.bottomCenterOffset\n if (offset instanceof THREE.Vector3) {\n return offset\n }\n\n if (offset && typeof offset === 'object') {\n const {\n x = 0,\n y = 0,\n z = 0,\n } = offset as Partial<Record<'x' | 'y' | 'z', number>>\n const normalized = new THREE.Vector3(x ?? 0, y ?? 0, z ?? 0)\n object.userData.bottomCenterOffset = normalized\n return normalized\n }\n\n return null\n }\n\n private normalizeBottomCenterData(object: THREE.Object3D): boolean {\n const hasOffset = this.ensureBottomCenterOffset(object) !== null\n object.children.forEach((child) => this.normalizeBottomCenterData(child))\n return hasOffset\n }\n\n /**\n * Load an asset with the specified options\n */\n async load(options: AssetLoaderOptions): Promise<THREE.Object3D> {\n const {\n type,\n url,\n size,\n lowResUrl,\n enableCaching = true,\n placeholderColor = 0x4fc3f7,\n placeholderOpacity = 0.8,\n errorColor = 0xff4444,\n errorOpacity = 0.5,\n } = options\n\n // Check cache first\n if (enableCaching && this.cache.has(url)) {\n const cachedClone = this.cache.get(url)!.clone(true)\n const hasOffset = this.normalizeBottomCenterData(cachedClone)\n\n if (!hasOffset) {\n this.positionAssetAtBottomCenter(cachedClone)\n } else {\n cachedClone.updateMatrixWorld(true)\n }\n\n this.loadedAsset = cachedClone\n this.dispatchEvent({ type: 'loaded', asset: cachedClone })\n return cachedClone\n }\n\n // Store error styling options\n this.errorColor = errorColor\n this.errorOpacity = errorOpacity\n\n // Create placeholder if size is provided\n if (size) {\n this.placeholder = this.createPlaceholder(\n size,\n placeholderColor,\n placeholderOpacity\n )\n this.dispatchEvent({\n type: 'placeholderCreated',\n placeholder: this.placeholder,\n })\n }\n\n try {\n // Load low-res model first if provided\n if (lowResUrl) {\n const lowRes = await this.loadModel(type, lowResUrl, true)\n this.lowResAsset = lowRes\n this.dispatchEvent({ type: 'lowResLoaded', lowRes })\n }\n\n // Load main asset\n const asset = await this.loadModel(type, url, false)\n this.loadedAsset = asset\n\n // Cache if enabled\n if (enableCaching) {\n const cacheEntry = asset.clone(true)\n const hasOffset = this.normalizeBottomCenterData(cacheEntry)\n if (!hasOffset) {\n this.positionAssetAtBottomCenter(cacheEntry)\n } else {\n cacheEntry.updateMatrixWorld(true)\n }\n this.cache.set(url, cacheEntry)\n }\n\n this.dispatchEvent({ type: 'loaded', asset })\n return asset\n } catch (error) {\n // Set placeholder to error state\n this.setPlaceholderError()\n this.dispatchEvent({ type: 'error', error: error as Error })\n throw error\n }\n }\n\n /**\n * Load a model based on type\n */\n private loadModel(\n type: AssetType,\n url: string,\n isLowRes: boolean\n ): Promise<THREE.Object3D> {\n return new Promise((resolve, reject) => {\n const onProgress = (event: ProgressEvent) => {\n const percentage = (event.loaded / event.total) * 100\n this.dispatchEvent({\n type: 'progress',\n loaded: event.loaded,\n total: event.total,\n percentage,\n })\n\n // Update placeholder fill\n if (!isLowRes) {\n this.updatePlaceholder(percentage / 100)\n }\n }\n\n const onError = (error: unknown) => {\n reject(error)\n }\n\n switch (type) {\n case 'gltf':\n this.gltfLoader.load(\n url,\n (gltf) => {\n const scene = gltf.scene\n this.positionAssetAtBottomCenter(scene)\n resolve(scene)\n },\n onProgress,\n onError\n )\n break\n\n case 'fbx':\n this.fbxLoader.load(\n url,\n (fbx) => {\n this.positionAssetAtBottomCenter(fbx)\n resolve(fbx)\n },\n onProgress,\n onError\n )\n break\n\n case 'obj':\n this.objLoader.load(\n url,\n (obj) => {\n this.positionAssetAtBottomCenter(obj)\n resolve(obj)\n },\n onProgress,\n onError\n )\n break\n\n default:\n reject(new Error(`Unsupported asset type: ${type}`))\n }\n })\n }\n\n /**\n * Get the placeholder object\n */\n getPlaceholder(): THREE.Object3D | null {\n return this.placeholder\n }\n\n /**\n * Get the loaded asset\n */\n getAsset(): THREE.Object3D | null {\n return this.loadedAsset\n }\n\n /**\n * Get the low-res asset\n */\n getLowResAsset(): THREE.Object3D | null {\n return this.lowResAsset\n }\n\n /**\n * Clear the cache\n */\n clearCache() {\n this.cache.clear()\n }\n\n /**\n * Remove an item from cache\n */\n removeFromCache(url: string) {\n this.cache.delete(url)\n }\n\n /**\n * Get cache size\n */\n getCacheSize(): number {\n return this.cache.size\n }\n}\n","import * as THREE from 'three'\nimport CameraControls from 'camera-controls'\n\ntype Vector3Tuple = [number, number, number]\ntype Vector3Like = THREE.Vector3 | Vector3Tuple\n\nexport type CameraMode = 'perspective' | 'orthographic'\n\nexport interface PerspectiveCameraConfig {\n fov?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface OrthographicCameraConfig {\n size?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface DualCameraControlsOptions {\n domElement?: HTMLElement\n initialMode?: CameraMode\n initialTarget?: Vector3Like\n perspective?: PerspectiveCameraConfig\n orthographic?: OrthographicCameraConfig\n}\n\nexport interface ModeChangedEvent {\n type: 'modechange'\n mode: CameraMode\n previousMode: CameraMode\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nlet controlsInstalled = false\n\nconst tempVec3A = new THREE.Vector3()\nconst tempVec3B = new THREE.Vector3()\nconst tempVec2 = new THREE.Vector2()\n\nfunction ensureCameraControlsInstalled() {\n if (!controlsInstalled) {\n CameraControls.install({ THREE })\n controlsInstalled = true\n }\n}\n\nfunction toVector3(\n value: Vector3Like | undefined,\n fallback: Vector3Tuple,\n target: THREE.Vector3\n) {\n if (!value) {\n target.set(fallback[0], fallback[1], fallback[2])\n return target\n }\n\n if (Array.isArray(value)) {\n target.set(value[0], value[1], value[2])\n return target\n }\n\n target.copy(value)\n return target\n}\n\n/**\n * Camera controls that manage both perspective and orthographic cameras while\n * extending {@link CameraControls}. Provides helpers to toggle between the\n * camera types and keep the framing consistent.\n */\nexport class DualCameraControls extends CameraControls {\n readonly perspectiveCamera: THREE.PerspectiveCamera\n readonly orthographicCamera: THREE.OrthographicCamera\n\n private readonly renderer: THREE.WebGLRenderer\n private readonly domElementRef: HTMLElement\n private activeMode: CameraMode\n private readonly minOrthoHalfHeight: number\n private readonly updateClock = new THREE.Clock()\n\n constructor(\n renderer: THREE.WebGLRenderer,\n options: DualCameraControlsOptions = {}\n ) {\n ensureCameraControlsInstalled()\n\n const { domElement = renderer.domElement } = options\n const aspect = resolveAspect(renderer, domElement)\n\n const perspectiveConfig = options.perspective ?? {}\n const orthographicConfig = options.orthographic ?? {}\n\n const perspectiveCamera = new THREE.PerspectiveCamera(\n perspectiveConfig.fov ?? 60,\n aspect,\n perspectiveConfig.near ?? 0.1,\n perspectiveConfig.far ?? 2000\n )\n\n perspectiveCamera.position.copy(\n toVector3(\n perspectiveConfig.position,\n [12, 12, 12],\n new THREE.Vector3()\n )\n )\n\n if (perspectiveConfig.zoom !== undefined) {\n perspectiveCamera.zoom = perspectiveConfig.zoom\n perspectiveCamera.updateProjectionMatrix()\n }\n\n const orthoHalfHeight = Math.max(orthographicConfig.size ?? 20, 0.001) * 0.5\n const orthoHalfWidth = orthoHalfHeight * aspect\n\n const orthographicCamera = new THREE.OrthographicCamera(\n -orthoHalfWidth,\n orthoHalfWidth,\n orthoHalfHeight,\n -orthoHalfHeight,\n orthographicConfig.near ?? 0.1,\n orthographicConfig.far ?? 2000\n )\n\n orthographicCamera.position.copy(\n toVector3(\n orthographicConfig.position,\n [12, 12, 12],\n new THREE.Vector3()\n )\n )\n\n if (orthographicConfig.zoom !== undefined) {\n orthographicCamera.zoom = orthographicConfig.zoom\n orthographicCamera.updateProjectionMatrix()\n }\n\n const initialMode = options.initialMode ?? 'perspective'\n const initialCamera =\n initialMode === 'orthographic' ? orthographicCamera : perspectiveCamera\n\n super(initialCamera, domElement)\n\n const initialTarget = toVector3(\n options.initialTarget,\n [0, 0, 0],\n new THREE.Vector3()\n )\n void this.setLookAt(\n initialCamera.position.x,\n initialCamera.position.y,\n initialCamera.position.z,\n initialTarget.x,\n initialTarget.y,\n initialTarget.z,\n false\n )\n\n this.renderer = renderer\n this.domElementRef = domElement\n this.perspectiveCamera = perspectiveCamera\n this.orthographicCamera = orthographicCamera\n this.activeMode = initialMode\n this.minOrthoHalfHeight = orthoHalfHeight\n\n this.updateInputBindingsForMode(initialMode)\n }\n\n get mode(): CameraMode {\n return this.activeMode\n }\n\n /**\n * Returns the currently active camera instance.\n */\n get activeCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this.camera\n }\n\n /**\n * Switch to the perspective camera while keeping the current framing.\n */\n switchToPerspective(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.position.copy(position)\n this.perspectiveCamera.quaternion.copy(this.camera.quaternion)\n this.perspectiveCamera.up.copy(this.camera.up)\n this.perspectiveCamera.updateProjectionMatrix()\n\n this.camera = this.perspectiveCamera\n this.activeMode = 'perspective'\n this.updateInputBindingsForMode('perspective')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'orthographic',\n camera: this.perspectiveCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Switch to the orthographic camera while keeping the current framing.\n */\n switchToOrthographic(enableTransition = false) {\n if (this.activeMode === 'orthographic') {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.updateOrthographicFrustum(position, target, aspect)\n\n this.orthographicCamera.position.copy(position)\n this.orthographicCamera.quaternion.copy(this.camera.quaternion)\n this.orthographicCamera.up.copy(this.camera.up)\n this.orthographicCamera.updateProjectionMatrix()\n\n this.camera = this.orthographicCamera\n this.activeMode = 'orthographic'\n this.updateInputBindingsForMode('orthographic')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'perspective',\n camera: this.orthographicCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Toggles between perspective and orthographic camera modes.\n */\n toggleCameraMode(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n this.switchToOrthographic(enableTransition)\n } else {\n this.switchToPerspective(enableTransition)\n }\n }\n\n /**\n * Update camera projection parameters when the viewport size changes.\n */\n handleResize(width: number, height: number) {\n const aspect = height === 0 ? 1 : width / height\n\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n this.updateOrthographicFrustum(position, target, aspect)\n\n if (this.activeMode === 'orthographic') {\n this.camera = this.orthographicCamera\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n false\n )\n }\n }\n\n /**\n * Moves the camera to a new position and target.\n */\n moveCamera(\n position: Vector3Like,\n target: Vector3Like,\n enableTransition = true\n ) {\n toVector3(position, [0, 0, 0], tempVec3A)\n toVector3(target, [0, 0, 0], tempVec3B)\n\n return this.setLookAt(\n tempVec3A.x,\n tempVec3A.y,\n tempVec3A.z,\n tempVec3B.x,\n tempVec3B.y,\n tempVec3B.z,\n enableTransition\n )\n }\n\n /**\n * Updates the controls using an internally managed clock.\n * Useful when you don't want to pass delta time each frame.\n */\n updateDelta(): ReturnType<CameraControls['update']> {\n const delta = this.updateClock.getDelta()\n return super.update(delta)\n }\n\n private updateInputBindingsForMode(mode: CameraMode) {\n const { ACTION } = CameraControls\n\n if (mode === 'orthographic') {\n this.mouseButtons.left = ACTION.TRUCK\n this.mouseButtons.right = ACTION.ROTATE\n this.mouseButtons.wheel = ACTION.ZOOM\n this.touches.one = ACTION.TOUCH_TRUCK\n this.touches.two = ACTION.TOUCH_ZOOM_TRUCK\n } else {\n this.mouseButtons.left = ACTION.ROTATE\n this.mouseButtons.right = ACTION.TRUCK\n this.mouseButtons.wheel = ACTION.DOLLY\n this.touches.one = ACTION.TOUCH_ROTATE\n this.touches.two = ACTION.TOUCH_DOLLY_TRUCK\n }\n }\n\n private updateOrthographicFrustum(\n position: THREE.Vector3,\n target: THREE.Vector3,\n aspect: number\n ) {\n const distance = Math.max(position.distanceTo(target), 0.001)\n const fov = this.perspectiveCamera.fov\n const halfHeight = Math.max(\n distance * Math.tan(THREE.MathUtils.degToRad(fov * 0.5)),\n this.minOrthoHalfHeight\n )\n const halfWidth = halfHeight * aspect\n\n this.orthographicCamera.left = -halfWidth\n this.orthographicCamera.right = halfWidth\n this.orthographicCamera.top = halfHeight\n this.orthographicCamera.bottom = -halfHeight\n this.orthographicCamera.updateProjectionMatrix()\n }\n}\n\nfunction resolveAspect(\n renderer: THREE.WebGLRenderer,\n domElement: HTMLElement\n): number {\n const size = renderer.getSize(tempVec2)\n if (size.y > 0) {\n return size.x / size.y\n }\n\n const { clientWidth, clientHeight } = domElement\n if (clientHeight > 0) {\n return clientWidth / clientHeight\n }\n\n return 1\n}\n","import * as THREE from 'three'\n\nexport interface CompassOverlayOptions {\n container?: HTMLElement\n size?: number\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n offset?: { x: number; y: number }\n colors?: {\n background: string\n border: string\n arrow: string\n text: string\n ticks: string\n }\n}\n\n// Define event types for the compass\ninterface CompassOverlayEventMap {\n resetToNorth: {}\n}\n\nexport interface CompassOverlayEvent {\n type: 'resetToNorth'\n}\n\nexport class CompassOverlay extends THREE.EventDispatcher<CompassOverlayEventMap> {\n private camera: THREE.Camera\n private container: HTMLElement\n private compassElement!: HTMLElement\n private arrowElement!: HTMLElement\n private isActive: boolean = false\n private options: Required<CompassOverlayOptions>\n private currentRotation: number = 0\n\n constructor(camera: THREE.Camera, options: CompassOverlayOptions = {}) {\n super()\n this.camera = camera\n\n // Set default options\n this.options = {\n container: options.container || document.body,\n size: options.size || 100,\n position: options.position || 'bottom-right',\n offset: options.offset || { x: 20, y: 20 },\n colors: {\n background: options.colors?.background || '#1a1a1a',\n border: options.colors?.border || '#333333',\n arrow: options.colors?.arrow || '#ff4444',\n text: options.colors?.text || '#ffffff',\n ticks: options.colors?.ticks || '#666666',\n ...options.colors,\n },\n }\n\n this.container = this.options.container\n this.createCompassElement()\n this.setupStyles()\n }\n\n private createCompassElement(): void {\n // Create main compass container\n this.compassElement = document.createElement('div')\n this.compassElement.className = 'threejs-compass-overlay'\n\n // Create compass background with ticks\n const compassBg = document.createElement('div')\n compassBg.className = 'compass-background'\n\n // Create cardinal direction labels\n const directions = [\n { label: 'N', angle: 0 },\n { label: 'E', angle: 90 },\n { label: 'S', angle: 180 },\n { label: 'W', angle: 270 },\n ]\n\n // Create tick marks\n for (let i = 0; i < 360; i += 11.25) {\n const tick = document.createElement('div')\n tick.className =\n i % 45 === 0 ? 'compass-tick-major' : 'compass-tick-minor'\n const tickLength = i % 30 === 0 ? 8 : 4\n tick.style.transform = `rotate(${i}deg) translateY(-${this.options.size / 2 - tickLength - 2}px)`\n compassBg.appendChild(tick)\n }\n\n directions.forEach(({ label, angle }) => {\n const dirLabel = document.createElement('div')\n dirLabel.className = 'compass-label'\n dirLabel.textContent = label\n dirLabel.style.transform = `rotate(${angle}deg) translateY(-${this.options.size / 2 - 15}px) rotate(-${angle}deg)`\n compassBg.appendChild(dirLabel)\n })\n\n // Create arrow element\n this.arrowElement = document.createElement('div')\n this.arrowElement.className = 'compass-arrow'\n\n // Arrow SVG\n this.arrowElement.innerHTML = `\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\">\n <polygon points=\"10,2 14,12 10,10 6,12\" fill=\"${this.options.colors.arrow}\" stroke=\"#000\" stroke-width=\"0.5\"/>\n </svg>\n `\n\n this.compassElement.appendChild(compassBg)\n this.compassElement.appendChild(this.arrowElement)\n this.container.appendChild(this.compassElement)\n\n // Add double-click event to reset camera to north\n this.setupDoubleClickHandler()\n }\n\n private setupStyles(): void {\n // Check if styles already exist\n if (document.getElementById('threejs-compass-styles')) {\n return\n }\n\n const style = document.createElement('style')\n style.id = 'threejs-compass-styles'\n style.textContent = `\n .threejs-compass-overlay {\n position: fixed;\n width: ${this.options.size}px;\n height: ${this.options.size}px;\n background: ${this.options.colors.background};\n border: 2px solid ${this.options.colors.border};\n border-radius: 50%;\n z-index: 1000;\n pointer-events: none;\n user-select: none;\n transition: opacity 0.2s ease;\n ${this.getPositionStyles()};\n }\n\n .compass-background {\n position: relative;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n }\n\n .compass-label {\n position: absolute;\n top: 50%;\n left: 50%;\n transform-origin: center;\n color: ${this.options.colors.text};\n font-family: Arial, sans-serif;\n font-size: 12px;\n font-weight: bold;\n text-align: center;\n width: 12px;\n height: 12px;\n line-height: 12px;\n margin-left: -6px;\n margin-top: -6px;\n }\n\n .compass-tick-major {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 2px;\n height: 8px;\n background: ${this.options.colors.ticks};\n transform-origin: center top;\n margin-left: -1px;\n margin-top: -4px;\n }\n\n .compass-tick-minor {\n position: absolute;\n top: 50%;\n left: 50%;\n width: 1px;\n height: 4px;\n background: ${this.options.colors.ticks};\n transform-origin: center top;\n margin-left: -0.5px;\n margin-top: -2px;\n opacity: 0.6;\n }\n\n .compass-arrow {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n transform-origin: center;\n transition: transform 0.1s ease-out;\n z-index: 1;\n }\n\n .compass-arrow svg {\n display: block;\n filter: drop-shadow(0 0 2px rgba(0,0,0,0.5));\n }\n `\n\n document.head.appendChild(style)\n }\n\n private setupDoubleClickHandler(): void {\n // Enable pointer events for interaction\n this.compassElement.style.pointerEvents = 'auto'\n this.compassElement.style.cursor = 'pointer'\n\n // Add double-click event listener\n this.compassElement.addEventListener('dblclick', (event) => {\n event.preventDefault()\n event.stopPropagation()\n\n // Dispatch custom event\n this.dispatchEvent({ type: 'resetToNorth' })\n })\n\n // Add visual feedback on hover\n this.compassElement.addEventListener('mouseenter', () => {\n this.compassElement.style.opacity = '0.8'\n })\n\n this.compassElement.addEventListener('mouseleave', () => {\n this.compassElement.style.opacity = '1'\n })\n }\n\n private updateTicksAndLabels(): void {\n // Update compass labels\n\n // Update tick marks\n const majorTicks = this.compassElement.querySelectorAll(\n '.compass-tick-major'\n )\n const minorTicks = this.compassElement.querySelectorAll(\n '.compass-tick-minor'\n )\n\n majorTicks.forEach((tick, index) => {\n const angle = (index * 30) % 360 // Major ticks every 30 degrees\n const tickLength = 8\n ;(tick as HTMLElement).style.transform =\n `rotate(${angle}deg) translateY(-${this.options.size / 2 - tickLength - 2}px)`\n })\n\n minorTicks.forEach((tick, index) => {\n // Minor ticks are at angles that aren't multiples of 30\n const allAngles = []\n for (let i = 0; i < 360; i += 10) {\n if (i % 30 !== 0) {\n // Skip major tick positions\n allAngles.push(i)\n }\n }\n const angle = allAngles[index] || 0\n const tickLength = 4\n ;(tick as HTMLElement).style.transform =\n `rotate(${angle}deg) translateY(-${this.options.size / 2 - tickLength - 2}px)`\n })\n\n const labels = this.compassElement.querySelectorAll('.compass-label')\n labels.forEach((label, index) => {\n const directions = [\n { label: 'N', angle: 0 },\n { label: 'E', angle: 90 },\n { label: 'S', angle: 180 },\n { label: 'W', angle: 270 },\n ]\n const { angle } = directions[index]\n ;(label as HTMLElement).style.transform =\n `rotate(${angle}deg) translateY(-${this.options.size / 2 - 15}px) rotate(-${angle}deg)`\n })\n }\n\n private getPositionStyles(): string {\n const { position, offset } = this.options\n\n switch (position) {\n case 'top-left':\n return `top: ${offset.y}px; left: ${offset.x}px;`\n case 'top-right':\n return `top: ${offset.y}px; right: ${offset.x}px;`\n case 'bottom-left':\n return `bottom: ${offset.y}px; left: ${offset.x}px;`\n case 'bottom-right':\n default:\n return `bottom: ${offset.y}px; right: ${offset.x}px;`\n }\n }\n\n public start(): void {\n if (this.isActive) return\n this.isActive = true\n this.update()\n }\n\n public stop(): void {\n this.isActive = false\n }\n\n public update(): void {\n if (!this.isActive) return\n\n // Get the camera's world matrix\n const cameraMatrix = new THREE.Matrix4()\n this.camera.updateMatrixWorld()\n cameraMatrix.copy(this.camera.matrixWorld)\n\n // Extract the camera's forward direction (negative Z in camera space)\n const forward = new THREE.Vector3(0, 0, -1)\n forward.transformDirection(cameraMatrix)\n\n // Project to XZ plane (ignore Y component for top-down compass view)\n forward.y = 0\n forward.normalize()\n\n // Calculate angle from world -Z axis (north)\n // World Z- is \"north\", X- is \"east\" (flipped X axis)\n const targetAngle = Math.atan2(-forward.x, -forward.z) * (180 / Math.PI)\n\n // Calculate the shortest rotation path to avoid spinning around\n let angleDiff = targetAngle - this.currentRotation\n\n // Normalize the angle difference to be between -180 and 180\n while (angleDiff > 180) angleDiff -= 360\n while (angleDiff < -180) angleDiff += 360\n\n // Update current rotation with smooth transition\n this.currentRotation += angleDiff\n\n // Update arrow rotation (negative because we want the arrow to point to north, not where camera is facing)\n this.arrowElement.style.transform = `translate(-50%, -50%) rotate(${-this.currentRotation}deg)`\n\n // Continue updating if active\n if (this.isActive) {\n requestAnimationFrame(() => this.update())\n }\n }\n\n public setCamera(camera: THREE.Camera): void {\n this.camera = camera\n }\n\n public setSize(size: number): void {\n this.options.size = size\n this.compassElement.style.width = `${size}px`\n this.compassElement.style.height = `${size}px`\n this.updateTicksAndLabels()\n this.updateStyles()\n }\n\n public setPosition(\n position: CompassOverlayOptions['position'],\n offset?: { x: number; y: number }\n ): void {\n if (position) {\n this.options.position = position\n }\n if (offset) {\n this.options.offset = offset\n }\n\n // Update position styles\n const positionStyles = this.getPositionStyles()\n const styles = positionStyles.split(';').filter((s) => s.trim())\n\n // Clear existing position styles\n this.compassElement.style.top = ''\n this.compassElement.style.right = ''\n this.compassElement.style.bottom = ''\n this.compassElement.style.left = ''\n\n // Apply new position styles\n styles.forEach((style) => {\n const [property, value] = style.split(':').map((s) => s.trim())\n if (property && value) {\n ;(this.compassElement.style as any)[property] = value\n }\n })\n }\n\n public setColors(colors: Partial<CompassOverlayOptions['colors']>): void {\n this.options.colors = { ...this.options.colors, ...colors }\n this.updateStyles()\n }\n\n /**\n * Helper method to reset camera to look north (world Z- direction)\n * This is a convenience method that can be called when handling the 'resetToNorth' event\n */\n public static resetCameraToNorth(\n camera: THREE.Camera,\n smooth: boolean = true\n ): void {\n if (smooth) {\n // Create a smooth rotation animation to north\n const startQuaternion = camera.quaternion.clone()\n const targetQuaternion = new THREE.Quaternion()\n\n // Set target rotation to look at north (Z-)\n const targetMatrix = new THREE.Matrix4()\n targetMatrix.lookAt(\n camera.position,\n camera.position.clone().add(new THREE.Vector3(0, 0, -1)),\n new THREE.Vector3(0, 1, 0)\n )\n targetQuaternion.setFromRotationMatrix(targetMatrix)\n\n // Animate rotation\n const duration = 500 // milliseconds\n const startTime = Date.now()\n\n const animate = () => {\n const elapsed = Date.now() - startTime\n const progress = Math.min(elapsed / duration, 1)\n\n // Use smooth easing\n const easeProgress = 1 - Math.pow(1 - progress, 3)\n\n camera.quaternion.slerpQuaternions(\n startQuaternion,\n targetQuaternion,\n easeProgress\n )\n\n if (progress < 1) {\n requestAnimationFrame(animate)\n }\n }\n animate()\n } else {\n // Instant rotation to north\n camera.lookAt(camera.position.clone().add(new THREE.Vector3(0, 0, -1)))\n }\n }\n\n private updateStyles(): void {\n // Remove existing styles\n const existingStyle = document.getElementById('threejs-compass-styles')\n if (existingStyle) {\n existingStyle.remove()\n }\n\n // Recreate styles with new values\n this.setupStyles()\n }\n\n public dispose(): void {\n this.stop()\n\n if (this.compassElement && this.compassElement.parentNode) {\n this.compassElement.parentNode.removeChild(this.compassElement)\n }\n\n // Remove styles if no other compass instances exist\n const compassElements = document.querySelectorAll(\n '.threejs-compass-overlay'\n )\n if (compassElements.length === 0) {\n const style = document.getElementById('threejs-compass-styles')\n if (style) {\n style.remove()\n }\n }\n }\n}\n","import * as THREE from 'three'\n\n// Define custom event types\ninterface InfiniteGridEventMap {\n subdivisionsChanged: { subdivisions: number }\n divisionsChanged: { divisions: number }\n colorChanged: {\n color: THREE.Color | number\n colorType: 'color1' | 'color2' | 'fog'\n }\n fogChanged: { property: 'near' | 'far'; value: number }\n}\n\nexport class InfiniteGrid extends THREE.Object3D {\n subdivisions: number\n divisions: number\n gridMaterial: THREE.ShaderMaterial\n private eventDispatcher: THREE.EventDispatcher<InfiniteGridEventMap>\n\n constructor(divisions: number = 1, subdivisions: number = 10) {\n super()\n\n // Create an internal EventDispatcher for custom events\n this.eventDispatcher = new THREE.EventDispatcher<InfiniteGridEventMap>()\n this.divisions = divisions\n this.subdivisions = subdivisions\n\n // Create a custom grid shader material\n const gridSize = 100\n\n // Create a plane for the grid\n const gridGeometry = new THREE.PlaneGeometry(\n gridSize * 2,\n gridSize * 2,\n 1,\n 1\n )\n\n // Custom grid shader material\n this.gridMaterial = new THREE.ShaderMaterial({\n uniforms: {\n uSize1: { value: this.divisions / this.subdivisions },\n uSize2: { value: this.divisions },\n uColor1: { value: new THREE.Color(0x444444) },\n uColor2: { value: new THREE.Color(0x666666) },\n uFogColor: { value: new THREE.Color(0x2a2a2a) },\n uFogNear: { value: 20.0 },\n uFogFar: { value: 60.0 },\n },\n vertexShader: `\n varying vec3 worldPosition;\n \n void main() {\n worldPosition = position.xzy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n `,\n fragmentShader: `\n uniform float uSize1;\n uniform float uSize2;\n uniform vec3 uColor1;\n uniform vec3 uColor2;\n uniform vec3 uFogColor;\n uniform float uFogNear;\n uniform float uFogFar;\n \n varying vec3 worldPosition;\n \n float getGrid(float size) {\n vec2 r = worldPosition.xz / size;\n vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);\n float line = min(grid.x, grid.y);\n return 1.0 - min(line, 1.0);\n }\n \n void main() {\n float g1 = getGrid(uSize1);\n float g2 = getGrid(uSize2);\n \n // Calculate fog factor using both near and far\n float dist = length(worldPosition);\n float fogFactor = smoothstep(uFogNear, uFogFar, dist);\n \n // Mix grid colors\n vec3 color = mix(uColor1, uColor2, g2);\n \n // Apply fog to color and use inverse fog factor for alpha (fade out with distance)\n vec3 finalColor = mix(color, uFogColor, fogFactor);\n float alpha = (g1 + g2) * (1.0 - fogFactor);\n \n gl_FragColor = vec4(finalColor, alpha);\n }\n `,\n transparent: true,\n side: THREE.DoubleSide,\n depthWrite: false,\n })\n\n // Create the grid mesh\n const gridMesh = new THREE.Mesh(gridGeometry, this.gridMaterial)\n gridMesh.renderOrder = -1\n gridMesh.rotation.x = -Math.PI / 2\n this.add(gridMesh)\n // return gridMesh;\n }\n\n setSubdivisions(subdivisions: number): void {\n this.subdivisions = subdivisions\n this.gridMaterial.uniforms.uSize1.value = this.divisions / this.subdivisions\n this.eventDispatcher.dispatchEvent({\n type: 'subdivisionsChanged',\n subdivisions,\n })\n }\n\n setDivisions(divisions: number): void {\n this.divisions = divisions\n this.gridMaterial.uniforms.uSize1.value = this.divisions / this.subdivisions\n this.gridMaterial.uniforms.uSize2.value = this.divisions\n this.eventDispatcher.dispatchEvent({ type: 'divisionsChanged', divisions })\n }\n\n setColor1(color: THREE.Color | number): void {\n if (typeof color === 'number') {\n this.gridMaterial.uniforms.uColor1.value.setHex(color)\n } else {\n this.gridMaterial.uniforms.uColor1.value.copy(color)\n }\n this.eventDispatcher.dispatchEvent({\n type: 'colorChanged',\n color,\n colorType: 'color1',\n })\n }\n\n setColor2(color: THREE.Color | number): void {\n if (typeof color === 'number') {\n this.gridMaterial.uniforms.uColor2.value.setHex(color)\n } else {\n this.gridMaterial.uniforms.uColor2.value.copy(color)\n }\n this.eventDispatcher.dispatchEvent({\n type: 'colorChanged',\n color,\n colorType: 'color2',\n })\n }\n\n setFogColor(color: THREE.Color | number): void {\n if (typeof color === 'number') {\n this.gridMaterial.uniforms.uFogColor.value.setHex(color)\n } else {\n this.gridMaterial.uniforms.uFogColor.value.copy(color)\n }\n this.eventDispatcher.dispatchEvent({\n type: 'colorChanged',\n color,\n colorType: 'fog',\n })\n }\n\n setFogNear(near: number): void {\n const fogFar = this.gridMaterial.uniforms.uFogFar.value\n const clampedNear = Math.min(near, fogFar)\n this.gridMaterial.uniforms.uFogNear.value = clampedNear\n this.eventDispatcher.dispatchEvent({\n type: 'fogChanged',\n property: 'near',\n value: clampedNear,\n })\n }\n\n setFogFar(far: number): void {\n const fogNear = this.gridMaterial.uniforms.uFogNear.value\n const clampedFar = Math.max(far, fogNear)\n this.gridMaterial.uniforms.uFogFar.value = clampedFar\n this.eventDispatcher.dispatchEvent({\n type: 'fogChanged',\n property: 'far',\n value: clampedFar,\n })\n }\n\n // Custom event listener methods (prefixed to avoid conflicts with Object3D)\n addGridEventListener<K extends keyof InfiniteGridEventMap>(\n type: K,\n listener: (event: InfiniteGridEventMap[K] & { type: K }) => void\n ): void {\n this.eventDispatcher.addEventListener(type, listener)\n }\n\n removeGridEventListener<K extends keyof InfiniteGridEventMap>(\n type: K,\n listener: (event: InfiniteGridEventMap[K] & { type: K }) => void\n ): void {\n this.eventDispatcher.removeEventListener(type, listener)\n }\n\n hasGridEventListener<K extends keyof InfiniteGridEventMap>(\n type: K,\n listener: (event: InfiniteGridEventMap[K] & { type: K }) => void\n ): boolean {\n return this.eventDispatcher.hasEventListener(type, listener)\n }\n}\n","import * as THREE from 'three'\nimport { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'\nimport {\n Measurement,\n MeasurementPoint,\n MeasurementData,\n MeasurementPointData,\n MeasurementToolOptions,\n MeasurementToolEvents,\n MeasurementCreationOptions,\n MeasurementOptions,\n SnapMode,\n SnapResult,\n} from './MeasurementTypes'\n\n/**\n * Main measurement tool class for Three.js scenes\n * Provides both programmatic and interactive measurement creation\n *\n * **Important**: This tool uses CSS2DObject for labels, which requires\n * CSS2DRenderer to be set up and rendered alongside your main WebGL renderer.\n *\n * @example\n * ```javascript\n * import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer.js'\n *\n * // Set up CSS2DRenderer\n * const css2dRenderer = new CSS2DRenderer()\n * css2dRenderer.setSize(window.innerWidth, window.innerHeight)\n * css2dRenderer.domElement.style.position = 'absolute'\n * css2dRenderer.domElement.style.top = '0'\n * css2dRenderer.domElement.style.pointerEvents = 'none'\n * document.body.appendChild(css2dRenderer.domElement)\n *\n * // In your animation loop:\n * function animate() {\n * renderer.render(scene, camera) // WebGL rendering\n * css2dRenderer.render(scene, camera) // CSS2D label rendering\n * }\n * ```\n */\nexport class MeasurementTool extends THREE.EventDispatcher<MeasurementToolEvents> {\n private scene: THREE.Scene\n private camera: THREE.Camera\n private measurements: Measurement[] = []\n private raycaster: THREE.Raycaster = new THREE.Raycaster()\n\n // Interactive mode properties\n private isInteractive: boolean = false\n private domElement: HTMLElement | null = null\n private controls: { enabled: boolean } | null = null\n private defaultTargets: THREE.Object3D[] = []\n private activeTargets: THREE.Object3D[] = []\n private currentMeasurement: Partial<Measurement> | null = null\n private activeInteractionOptions: MeasurementOptions | null = null\n private pendingMeasurementOptions: MeasurementOptions | null = null\n private previewLine: THREE.Line | null = null\n private previewLabel: CSS2DObject | null = null\n private snapMarker: THREE.Sprite | null = null\n private originalCursor: string = ''\n private cursorHidden: boolean = false\n\n // Configuration defaults\n private defaultOptions: MeasurementOptions = {\n lineColor: 0xff0000,\n labelColor: '#ffffff',\n lineWidth: 2,\n fontSize: 16,\n fontFamily: 'Arial, sans-serif',\n snapMode: SnapMode.VERTEX,\n snapEnabled: true,\n snapDistance: 0.05,\n targets: [],\n isDynamic: false,\n }\n private previewColor: number = 0x00ffff\n private markerColor: number = 0x00ff00\n private markerSize: number = 0.08\n private markerVisible: boolean = true\n\n // Edit mode properties\n private isEditMode: boolean = false\n private editingMeasurement: Measurement | null = null\n private editingPoint: 'start' | 'end' | null = null\n private startEditSprite: THREE.Sprite | null = null\n private endEditSprite: THREE.Sprite | null = null\n private editSpriteMaterial: THREE.SpriteMaterial | null = null\n private isDragging: boolean = false\n\n // Materials\n private previewMaterial: THREE.LineDashedMaterial\n private markerMaterial: THREE.SpriteMaterial\n\n /**\n * Create a crosshair texture for the snap marker sprite\n */\n private createCrosshairTexture(): THREE.Texture {\n const size = 64\n const canvas = document.createElement('canvas')\n canvas.width = size\n canvas.height = size\n\n const context = canvas.getContext('2d')!\n const centerX = size / 2\n const centerY = size / 2\n const lineLength = 20\n const gap = 6\n\n // Clear canvas\n context.clearRect(0, 0, size, size)\n\n // Set line style\n context.strokeStyle = '#ffffff'\n context.lineWidth = 3\n context.lineCap = 'round'\n\n // Draw crosshair lines\n context.beginPath()\n\n // Horizontal line (left)\n context.moveTo(centerX - lineLength, centerY)\n context.lineTo(centerX - gap, centerY)\n\n // Horizontal line (right)\n context.moveTo(centerX + gap, centerY)\n context.lineTo(centerX + lineLength, centerY)\n\n // Vertical line (top)\n context.moveTo(centerX, centerY - lineLength)\n context.lineTo(centerX, centerY - gap)\n\n // Vertical line (bottom)\n context.moveTo(centerX, centerY + gap)\n context.lineTo(centerX, centerY + lineLength)\n\n context.stroke()\n\n // Add black outline for better visibility\n context.strokeStyle = '#000000'\n context.lineWidth = 5\n context.globalCompositeOperation = 'destination-over'\n\n context.beginPath()\n\n // Horizontal line (left)\n context.moveTo(centerX - lineLength, centerY)\n context.lineTo(centerX - gap, centerY)\n\n // Horizontal line (right)\n context.moveTo(centerX + gap, centerY)\n context.lineTo(centerX + lineLength, centerY)\n\n // Vertical line (top)\n context.moveTo(centerX, centerY - lineLength)\n context.lineTo(centerX, centerY - gap)\n\n // Vertical line (bottom)\n context.moveTo(centerX, centerY + gap)\n context.lineTo(centerX, centerY + lineLength)\n\n context.stroke()\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.needsUpdate = true\n return texture\n }\n\n /**\n * Create a dot texture for edit point sprites\n */\n private createDotTexture(): THREE.Texture {\n const size = 64\n const canvas = document.createElement('canvas')\n canvas.width = size\n canvas.height = size\n\n const context = canvas.getContext('2d')!\n const centerX = size / 2\n const centerY = size / 2\n const radius = 12\n\n // Clear canvas\n context.clearRect(0, 0, size, size)\n\n // Draw white circle\n context.fillStyle = '#ffffff'\n context.beginPath()\n context.arc(centerX, centerY, radius, 0, Math.PI * 2)\n context.fill()\n\n // Add black outline\n context.strokeStyle = '#000000'\n context.lineWidth = 3\n context.beginPath()\n context.arc(centerX, centerY, radius, 0, Math.PI * 2)\n context.stroke()\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.needsUpdate = true\n return texture\n }\n\n constructor(\n scene: THREE.Scene,\n camera: THREE.Camera,\n options: MeasurementToolOptions = {}\n ) {\n super()\n\n this.scene = scene\n this.camera = camera\n\n // Apply options (excluding domElement and controls which need special handling)\n const { domElement, controls } = options\n\n // Set DOM element if provided\n if (domElement) {\n this.domElement = domElement\n }\n\n // Set controls if provided\n if (controls) {\n this.controls = controls\n }\n\n this.previewMaterial = new THREE.LineDashedMaterial({\n color: this.previewColor,\n linewidth: this.defaultOptions.lineWidth,\n dashSize: 0.1,\n gapSize: 0.05,\n })\n\n this.markerMaterial = new THREE.SpriteMaterial({\n map: this.createCrosshairTexture(),\n color: this.markerColor,\n transparent: true,\n opacity: 0.8,\n sizeAttenuation: false, // Keep constant size regardless of distance\n depthTest: false, // Always render in front of other objects\n })\n\n this.editSpriteMaterial = new THREE.SpriteMaterial({\n map: this.createDotTexture(),\n color: 0xffaa00, // Orange color for edit points\n transparent: true,\n opacity: 0.9,\n sizeAttenuation: false,\n depthTest: false,\n })\n\n // Set up raycaster\n this.raycaster.params.Line.threshold = 0.01\n this.raycaster.params.Points.threshold = 0.01\n }\n\n /**\n * Create a measurement point that optionally tracks a scene object.\n */\n private createMeasurementPoint(\n worldPosition: THREE.Vector3,\n object?: THREE.Object3D,\n localPosition?: THREE.Vector3\n ): MeasurementPoint {\n if (!object) {\n return { position: worldPosition.clone() }\n }\n\n const anchorLocal =\n localPosition?.clone() ?? object.worldToLocal(worldPosition.clone())\n const resolvedWorld = object.localToWorld(anchorLocal.clone())\n\n return {\n position: resolvedWorld,\n anchor: {\n object,\n localPosition: anchorLocal,\n },\n }\n }\n\n /**\n * Update a measurement point's world position from its anchor (if dynamic)\n */\n private updateMeasurementPoint(point: MeasurementPoint): boolean {\n if (!point.anchor) {\n return false\n }\n\n const newWorldPosition = point.anchor.localPosition.clone()\n point.anchor.object.localToWorld(newWorldPosition)\n\n if (!point.position.equals(newWorldPosition)) {\n point.position.copy(newWorldPosition)\n return true\n }\n\n return false\n }\n\n /**\n * Add a measurement between two world positions with optional attachments.\n *\n * @param start - Starting world position\n * @param end - Ending world position\n * @param options - Optional configuration for the measurement\n */\n addMeasurement(\n start: THREE.Vector3,\n end: THREE.Vector3,\n options: MeasurementCreationOptions = {}\n ): Measurement {\n const hasAnchors = Boolean(options.startObject || options.endObject)\n const resolvedOptions = this.resolveMeasurementOptions(\n options,\n options.isDynamic ?? hasAnchors\n )\n\n const startPoint = this.createMeasurementPoint(\n start,\n options.startObject,\n options.startLocalPosition\n )\n const endPoint = this.createMeasurementPoint(\n end,\n options.endObject,\n options.endLocalPosition\n )\n\n return this.addMeasurementFromPoints(startPoint, endPoint, resolvedOptions, {\n id: options.id,\n })\n }\n\n private resolveMeasurementOptions(\n overrides: MeasurementCreationOptions = {},\n inferredDynamic?: boolean\n ): MeasurementOptions {\n let targetCandidates: THREE.Object3D[] | undefined\n\n if (overrides.targets && overrides.targets.length > 0) {\n targetCandidates = overrides.targets\n } else if (this.defaultOptions.targets.length > 0) {\n targetCandidates = this.defaultOptions.targets\n } else if (this.defaultTargets.length > 0) {\n targetCandidates = this.defaultTargets\n }\n\n const targets =\n targetCandidates && targetCandidates.length > 0\n ? targetCandidates\n : this.getAllMeshes()\n\n const isDynamic =\n overrides.isDynamic ??\n inferredDynamic ??\n this.defaultOptions.isDynamic\n\n return {\n lineColor: overrides.lineColor ?? this.defaultOptions.lineColor,\n labelColor: overrides.labelColor ?? this.defaultOptions.labelColor,\n lineWidth: overrides.lineWidth ?? this.defaultOptions.lineWidth,\n fontSize: overrides.fontSize ?? this.defaultOptions.fontSize,\n fontFamily: overrides.fontFamily ?? this.defaultOptions.fontFamily,\n snapMode: overrides.snapMode ?? this.defaultOptions.snapMode,\n snapEnabled: overrides.snapEnabled ?? this.defaultOptions.snapEnabled,\n snapDistance: overrides.snapDistance ?? this.defaultOptions.snapDistance,\n targets,\n isDynamic,\n }\n }\n\n private getActiveMeasurementOptions(): MeasurementOptions | null {\n if (this.isEditMode && this.editingMeasurement) {\n return this.editingMeasurement.options\n }\n\n return this.activeInteractionOptions\n }\n\n /**\n * @deprecated Use addMeasurement(obj1, obj2, { startLocalPos, endLocalPos }) instead\n * Add a dynamic measurement between two objects\n */\n addDynamicMeasurement(\n startObject: THREE.Object3D,\n endObject: THREE.Object3D,\n startLocalPos: THREE.Vector3 = new THREE.Vector3(),\n endLocalPos: THREE.Vector3 = new THREE.Vector3()\n ): Measurement {\n const startWorld = startObject.localToWorld(startLocalPos.clone())\n const endWorld = endObject.localToWorld(endLocalPos.clone())\n\n return this.addMeasurement(startWorld, endWorld, {\n startObject,\n endObject,\n startLocalPosition: startLocalPos,\n endLocalPosition: endLocalPos,\n })\n }\n\n /**\n * @deprecated Use addMeasurement(staticPos, targetObject, { endLocalPos }) instead\n * Add a measurement from a static point to a dynamic object\n */\n addMeasurementToObject(\n staticPos: THREE.Vector3,\n targetObject: THREE.Object3D,\n objectLocalPos: THREE.Vector3 = new THREE.Vector3()\n ): Measurement {\n const endWorld = targetObject.localToWorld(objectLocalPos.clone())\n\n return this.addMeasurement(staticPos, endWorld, {\n endObject: targetObject,\n endLocalPosition: objectLocalPos,\n })\n }\n\n /**\n * Core method to add a measurement from two measurement points\n */\n private addMeasurementFromPoints(\n start: MeasurementPoint,\n end: MeasurementPoint,\n options: MeasurementOptions,\n context?: { id?: string }\n ): Measurement {\n const id = context?.id || this.generateId()\n const distance = start.position.distanceTo(end.position)\n\n // Create line geometry\n const geometry = new THREE.BufferGeometry().setFromPoints([\n start.position,\n end.position,\n ])\n const line = new THREE.Line(\n geometry,\n new THREE.LineBasicMaterial({\n color: options.lineColor,\n linewidth: options.lineWidth,\n })\n )\n\n // Create label\n const label = this.createLabel(distance, options)\n const midpoint = start.position\n .clone()\n .add(end.position)\n .multiplyScalar(0.5)\n label.position.copy(midpoint)\n\n const measurement: Measurement = {\n id,\n start,\n end,\n line,\n label,\n distance,\n options: {\n ...options,\n targets: [...options.targets],\n },\n }\n\n // Add to scene and tracking\n this.scene.add(line)\n this.scene.add(label)\n this.measurements.push(measurement)\n\n // Dispatch event\n this.dispatchEvent({\n type: 'measurementCreated',\n measurement,\n })\n\n return measurement\n }\n\n /**\n * Update all dynamic measurements in real-time\n * Call this in your animation loop to keep dynamic measurements up-to-date\n */\n updateDynamicMeasurements(): boolean {\n let updated = false\n\n for (const measurement of this.measurements) {\n if (!measurement.options.isDynamic) continue\n\n let needsUpdate = false\n\n // Update start point\n if (this.updateMeasurementPoint(measurement.start)) {\n needsUpdate = true\n }\n\n // Update end point\n if (this.updateMeasurementPoint(measurement.end)) {\n needsUpdate = true\n }\n\n if (needsUpdate) {\n // Recalculate distance\n const newDistance = measurement.start.position.distanceTo(\n measurement.end.position\n )\n measurement.distance = newDistance\n\n // Update line geometry\n const positions = [measurement.start.position, measurement.end.position]\n measurement.line.geometry.setFromPoints(positions)\n measurement.line.geometry.attributes.position.needsUpdate = true\n\n // Update label position and text\n const midpoint = measurement.start.position\n .clone()\n .add(measurement.end.position)\n .multiplyScalar(0.5)\n measurement.label.position.copy(midpoint)\n this.updateLabelText(measurement.label.element, newDistance)\n\n updated = true\n }\n }\n\n return updated\n }\n\n /**\n * Set whether interactive measurements should be dynamic or static\n */\n setDynamicMode(enabled: boolean): void {\n this.setDefaultMeasurementOptions({ isDynamic: enabled })\n }\n\n /**\n * Get the current dynamic mode state\n */\n getDynamicMode(): boolean {\n return this.defaultOptions.isDynamic\n }\n\n /**\n * Enter edit mode for a specific measurement\n * Shows edit sprites at the measurement endpoints\n * @param measurementIdOrIndex - The measurement ID or index\n * @param targets - Optional target objects for snapping during edit\n */\n enterEditMode(\n measurementIdOrIndex: string | number,\n targets?: THREE.Object3D[]\n ): void {\n // Exit any current edit mode\n this.exitEditMode()\n\n // Find the measurement\n let measurement: Measurement | undefined\n if (typeof measurementIdOrIndex === 'string') {\n measurement = this.measurements.find((m) => m.id === measurementIdOrIndex)\n } else {\n measurement = this.measurements[measurementIdOrIndex]\n }\n\n if (!measurement) {\n console.warn('Measurement not found:', measurementIdOrIndex)\n return\n }\n\n if (!this.domElement) {\n console.warn(\n 'DOM element not set. Call setDomElement() or enableInteraction() first.'\n )\n return\n }\n\n this.isEditMode = true\n this.editingMeasurement = measurement\n\n // Select targets for editing\n const resolvedTargets =\n targets && targets.length > 0\n ? targets\n : measurement.options.targets.length > 0\n ? measurement.options.targets\n : this.getAllMeshes()\n\n this.activeTargets = resolvedTargets\n\n // Persist overrides so future edits reuse them\n if (targets && targets.length > 0) {\n measurement.options.targets = [...targets]\n }\n\n // Create edit sprites at the endpoints\n this.createEditSprites()\n\n // Set up event listeners for dragging\n this.domElement.addEventListener('mousedown', this.onEditMouseDown)\n this.domElement.addEventListener('mousemove', this.onEditMouseMove)\n this.domElement.addEventListener('mouseup', this.onEditMouseUp)\n this.domElement.style.cursor = 'pointer'\n\n this.dispatchEvent({\n type: 'editModeEntered',\n measurement,\n })\n }\n\n /**\n * Exit edit mode\n */\n exitEditMode(): void {\n if (!this.isEditMode) return\n\n const measurement = this.editingMeasurement\n\n // Remove edit sprites\n this.removeEditSprites()\n\n // Remove event listeners\n if (this.domElement) {\n this.domElement.removeEventListener('mousedown', this.onEditMouseDown)\n this.domElement.removeEventListener('mousemove', this.onEditMouseMove)\n this.domElement.removeEventListener('mouseup', this.onEditMouseUp)\n this.domElement.style.cursor = this.isInteractive\n ? 'crosshair'\n : 'default'\n }\n\n this.isEditMode = false\n this.editingMeasurement = null\n this.editingPoint = null\n this.isDragging = false\n this.activeTargets = []\n\n if (measurement) {\n this.dispatchEvent({\n type: 'editModeExited',\n measurement,\n })\n }\n }\n\n /**\n * Set the DOM element for interactions (both measurement and edit mode)\n */\n setDomElement(domElement: HTMLElement): void {\n this.domElement = domElement\n }\n\n /**\n * Set the camera controls to disable during edit dragging\n */\n setControls(controls: { enabled: boolean }): void {\n this.controls = controls\n }\n\n /**\n * Set target objects for snapping (used in both interactive mode and edit mode)\n */\n setTargetObjects(targets: THREE.Object3D[]): void {\n this.defaultTargets = targets.length > 0 ? targets : this.getAllMeshes()\n this.defaultOptions.targets = [...this.defaultTargets]\n }\n\n /**\n * Update default measurement options used when none are provided explicitly.\n */\n setDefaultMeasurementOptions(\n options: Partial<MeasurementCreationOptions>\n ): void {\n if (options.lineColor !== undefined) {\n this.defaultOptions.lineColor = options.lineColor\n }\n if (options.labelColor !== undefined) {\n this.defaultOptions.labelColor = options.labelColor\n }\n if (options.lineWidth !== undefined) {\n this.defaultOptions.lineWidth = options.lineWidth\n }\n if (options.fontSize !== undefined) {\n this.defaultOptions.fontSize = options.fontSize\n }\n if (options.fontFamily !== undefined) {\n this.defaultOptions.fontFamily = options.fontFamily\n }\n if (options.snapMode !== undefined) {\n this.defaultOptions.snapMode = options.snapMode\n }\n if (options.snapEnabled !== undefined) {\n this.defaultOptions.snapEnabled = options.snapEnabled\n }\n if (options.snapDistance !== undefined) {\n this.defaultOptions.snapDistance = options.snapDistance\n }\n if (options.targets !== undefined) {\n this.defaultTargets = options.targets\n this.defaultOptions.targets = [...options.targets]\n if (this.activeInteractionOptions) {\n this.activeInteractionOptions.targets = [...options.targets]\n this.activeTargets = options.targets\n }\n }\n if (options.isDynamic !== undefined) {\n this.defaultOptions.isDynamic = options.isDynamic\n if (this.activeInteractionOptions) {\n this.activeInteractionOptions.isDynamic = options.isDynamic\n }\n }\n\n if (this.activeInteractionOptions) {\n if (options.lineColor !== undefined) {\n this.activeInteractionOptions.lineColor = options.lineColor\n }\n if (options.labelColor !== undefined) {\n this.activeInteractionOptions.labelColor = options.labelColor\n }\n if (options.lineWidth !== undefined) {\n this.activeInteractionOptions.lineWidth = options.lineWidth\n }\n if (options.fontSize !== undefined) {\n this.activeInteractionOptions.fontSize = options.fontSize\n }\n if (options.fontFamily !== undefined) {\n this.activeInteractionOptions.fontFamily = options.fontFamily\n }\n if (options.snapMode !== undefined) {\n this.activeInteractionOptions.snapMode = options.snapMode\n }\n if (options.snapEnabled !== undefined) {\n this.activeInteractionOptions.snapEnabled = options.snapEnabled\n }\n if (options.snapDistance !== undefined) {\n this.activeInteractionOptions.snapDistance = options.snapDistance\n }\n }\n }\n\n /**\n * Disable camera controls (used during edit dragging)\n */\n private disableControls(): void {\n if (this.controls) {\n this.controls.enabled = false\n }\n }\n\n /**\n * Enable camera controls (used after edit dragging)\n */\n private enableControls(): void {\n if (this.controls) {\n this.controls.enabled = true\n }\n }\n\n /**\n * Enable interactive measurement mode\n */\n enableInteraction(options: MeasurementCreationOptions = {}): void {\n if (this.isInteractive) {\n this.disableInteraction()\n }\n\n const resolvedOptions = this.resolveMeasurementOptions(options)\n this.activeInteractionOptions = {\n ...resolvedOptions,\n targets: [...resolvedOptions.targets],\n }\n this.activeTargets =\n this.activeInteractionOptions.targets.length > 0\n ? this.activeInteractionOptions.targets\n : this.getAllMeshes()\n\n this.isInteractive = true\n\n if (this.domElement) {\n // Add event listeners\n this.domElement.addEventListener('click', this.onMouseClick)\n this.domElement.addEventListener('mousemove', this.onMouseMove)\n this.domElement.addEventListener('keydown', this.onKeyDown)\n\n // Set cursor style\n this.domElement.style.cursor = 'crosshair'\n }\n // Create snap marker\n this.createSnapMarker()\n\n this.dispatchEvent({ type: 'started' })\n }\n\n /**\n * Disable interactive measurement mode\n */\n disableInteraction(): void {\n if (!this.isInteractive || !this.domElement) return\n\n // Exit edit mode if active\n this.exitEditMode()\n\n // Remove event listeners\n this.domElement.removeEventListener('click', this.onMouseClick)\n this.domElement.removeEventListener('mousemove', this.onMouseMove)\n this.domElement.removeEventListener('keydown', this.onKeyDown)\n\n // Reset cursor\n this.showCursor()\n this.domElement.style.cursor = 'default'\n\n // Clean up current measurement\n this.cancelCurrentMeasurement()\n\n // Remove snap marker\n this.removeSnapMarker()\n\n this.isInteractive = false\n this.activeInteractionOptions = null\n this.activeTargets = []\n\n this.dispatchEvent({ type: 'ended' })\n }\n\n /**\n * Remove the last measurement (undo)\n */\n undoLast(): void {\n if (this.measurements.length === 0) return\n\n const lastMeasurement = this.measurements.pop()!\n this.removeMeasurementFromScene(lastMeasurement)\n\n this.dispatchEvent({\n type: 'measurementRemoved',\n measurement: lastMeasurement,\n })\n }\n\n /**\n * Remove a specific measurement\n */\n removeMeasurement(measurement: Measurement): void {\n const index = this.measurements.indexOf(measurement)\n if (index === -1) return\n\n this.measurements.splice(index, 1)\n this.removeMeasurementFromScene(measurement)\n\n this.dispatchEvent({\n type: 'measurementRemoved',\n measurement,\n })\n }\n\n /**\n * Clear all measurements\n */\n clearAll(): void {\n const count = this.measurements.length\n\n this.measurements.forEach((measurement) => {\n this.removeMeasurementFromScene(measurement)\n })\n\n this.measurements = []\n\n this.dispatchEvent({\n type: 'measurementsCleared',\n count,\n })\n }\n\n /**\n * Get all measurements\n */\n getMeasurements(): Measurement[] {\n return [...this.measurements]\n }\n\n /**\n * Convert a MeasurementPoint to serializable data\n */\n private serializeMeasurementPoint(\n point: MeasurementPoint\n ): MeasurementPointData {\n return {\n position: point.position.toArray() as [number, number, number],\n anchorObjectId: point.anchor?.object.uuid,\n anchorLocalPosition: point.anchor\n ? (point.anchor.localPosition.toArray() as [number, number, number])\n : undefined,\n }\n }\n\n /**\n * Serialize measurements to JSON-compatible format\n * Note: Dynamic measurements will lose their object references and become static when deserialized\n */\n serialize(): MeasurementData[] {\n return this.measurements.map((measurement) => ({\n id: measurement.id,\n start: this.serializeMeasurementPoint(measurement.start),\n end: this.serializeMeasurementPoint(measurement.end),\n distance: measurement.distance,\n options: {\n snapMode: measurement.options.snapMode,\n snapEnabled: measurement.options.snapEnabled,\n snapDistance: measurement.options.snapDistance,\n lineColor: measurement.options.lineColor,\n labelColor: measurement.options.labelColor,\n lineWidth: measurement.options.lineWidth,\n fontSize: measurement.options.fontSize,\n fontFamily: measurement.options.fontFamily,\n isDynamic: measurement.options.isDynamic,\n targetObjectIds: measurement.options.targets.map((obj) => obj.uuid),\n },\n }))\n }\n\n /**\n * Deserialize measurements from JSON data\n * Note: Dynamic measurements become static since object references are lost\n */\n deserialize(data: MeasurementData[]): void {\n // Clear existing measurements\n this.clearAll()\n\n data.forEach((item) => {\n const start = new THREE.Vector3().fromArray(item.start.position)\n const end = new THREE.Vector3().fromArray(item.end.position)\n\n const startObject = item.start.anchorObjectId\n ? (this.scene.getObjectByProperty(\n 'uuid',\n item.start.anchorObjectId\n ) as THREE.Object3D | null)\n : null\n const endObject = item.end.anchorObjectId\n ? (this.scene.getObjectByProperty(\n 'uuid',\n item.end.anchorObjectId\n ) as THREE.Object3D | null)\n : null\n\n const restoredTargets =\n item.options.targetObjectIds && item.options.targetObjectIds.length > 0\n ? (item.options.targetObjectIds\n .map((uuid) => this.scene.getObjectByProperty('uuid', uuid))\n .filter((obj) => obj !== undefined) as THREE.Object3D[])\n : undefined\n\n this.addMeasurement(start, end, {\n id: item.id,\n targets:\n restoredTargets && restoredTargets.length > 0\n ? restoredTargets\n : undefined,\n snapMode: item.options.snapMode,\n snapEnabled: item.options.snapEnabled,\n snapDistance: item.options.snapDistance,\n lineColor: item.options.lineColor,\n labelColor: item.options.labelColor,\n lineWidth: item.options.lineWidth,\n fontSize: item.options.fontSize,\n fontFamily: item.options.fontFamily,\n isDynamic: item.options.isDynamic,\n startObject: startObject || undefined,\n startLocalPosition: item.start.anchorLocalPosition\n ? new THREE.Vector3().fromArray(item.start.anchorLocalPosition)\n : undefined,\n endObject: endObject || undefined,\n endLocalPosition: item.end.anchorLocalPosition\n ? new THREE.Vector3().fromArray(item.end.anchorLocalPosition)\n : undefined,\n })\n })\n }\n\n /**\n * Dispose of all resources\n */\n dispose(): void {\n this.exitEditMode()\n this.disableInteraction()\n this.clearAll()\n\n this.previewMaterial.dispose()\n\n if (this.markerMaterial.map) {\n this.markerMaterial.map.dispose()\n }\n this.markerMaterial.dispose()\n\n if (this.editSpriteMaterial) {\n if (this.editSpriteMaterial.map) {\n this.editSpriteMaterial.map.dispose()\n }\n this.editSpriteMaterial.dispose()\n }\n }\n\n // Private methods\n\n private onMouseClick = (event: MouseEvent): void => {\n if (!this.isInteractive) return\n\n const snapResult = this.getSnapResult(event)\n if (!snapResult) return\n\n if (!this.currentMeasurement) {\n // Start new measurement\n this.startMeasurement(snapResult)\n } else {\n // Complete measurement\n this.completeMeasurement(snapResult)\n }\n }\n\n private onMouseMove = (event: MouseEvent): void => {\n if (!this.isInteractive) return\n\n const snapResult = this.getSnapResult(event)\n if (!snapResult) {\n this.hideSnapMarker()\n this.showCursor()\n return\n }\n\n if (!this.currentMeasurement) {\n // Show marker for potential start point and hide cursor\n this.updateSnapMarker(snapResult.point, true)\n this.hideCursor()\n } else {\n // Show marker for potential end point and hide cursor\n this.updateSnapMarker(snapResult.point, true)\n this.hideCursor()\n this.updatePreview(snapResult.point)\n }\n }\n\n private onKeyDown = (event: KeyboardEvent): void => {\n if (!this.isInteractive) return\n\n if (event.key === 'Escape') {\n this.cancelCurrentMeasurement()\n }\n }\n\n private hideCursor(): void {\n if (!this.domElement || this.cursorHidden) return\n\n this.originalCursor = this.domElement.style.cursor\n this.domElement.style.cursor = 'none'\n this.cursorHidden = true\n }\n\n private showCursor(): void {\n if (!this.domElement || !this.cursorHidden) return\n\n this.domElement.style.cursor = this.originalCursor || 'crosshair'\n this.cursorHidden = false\n }\n\n private createSnapMarker(): void {\n if (!this.markerVisible) return\n\n // Remove existing snap marker if it exists\n if (this.snapMarker) {\n this.scene.remove(this.snapMarker)\n }\n\n this.snapMarker = new THREE.Sprite(this.markerMaterial)\n this.snapMarker.scale.setScalar(this.markerSize)\n this.snapMarker.visible = false\n\n // Ensure marker always renders in front\n this.snapMarker.renderOrder = 999\n this.snapMarker.material.depthTest = false\n\n this.scene.add(this.snapMarker)\n }\n\n private updateSnapMarker(\n point: THREE.Vector3,\n visible: boolean = true\n ): void {\n if (!this.snapMarker || !this.markerVisible) return\n\n this.snapMarker.position.copy(point)\n this.snapMarker.visible = visible\n }\n\n private hideSnapMarker(): void {\n if (this.snapMarker) {\n this.snapMarker.visible = false\n }\n }\n\n private removeSnapMarker(): void {\n if (this.snapMarker) {\n this.scene.remove(this.snapMarker)\n this.snapMarker = null\n }\n }\n\n private startMeasurement(snapResult: SnapResult): void {\n const id = this.generateId()\n const point = snapResult.point\n const baseOptions =\n this.activeInteractionOptions ?? this.defaultOptions\n const measurementOptions: MeasurementOptions = {\n ...baseOptions,\n targets: [...baseOptions.targets],\n }\n this.pendingMeasurementOptions = measurementOptions\n\n // Hide snap marker temporarily while creating preview\n this.hideSnapMarker()\n\n // Create preview line\n const geometry = new THREE.BufferGeometry().setFromPoints([point, point])\n this.previewLine = new THREE.Line(geometry, this.previewMaterial)\n this.previewLine.computeLineDistances() // For dashed material\n this.scene.add(this.previewLine)\n\n // Create preview label\n this.previewLabel = this.createLabel(0, measurementOptions)\n this.previewLabel.position.copy(point)\n this.scene.add(this.previewLabel)\n\n const startPoint =\n measurementOptions.isDynamic && snapResult.object\n ? this.createMeasurementPoint(point, snapResult.object)\n : this.createMeasurementPoint(point)\n\n this.currentMeasurement = {\n id,\n start: startPoint,\n }\n }\n\n private updatePreview(point: THREE.Vector3): void {\n if (!this.currentMeasurement || !this.previewLine || !this.previewLabel)\n return\n\n const start = this.currentMeasurement.start!\n const distance = start.position.distanceTo(point)\n\n // Update preview line\n const geometry = new THREE.BufferGeometry().setFromPoints([\n start.position,\n point,\n ])\n this.previewLine.geometry.dispose()\n this.previewLine.geometry = geometry\n this.previewLine.computeLineDistances()\n\n // Update preview label\n const midpoint = start.position.clone().add(point).multiplyScalar(0.5)\n this.previewLabel.position.copy(midpoint)\n this.updateLabelText(this.previewLabel.element, distance)\n\n this.dispatchEvent({\n type: 'previewUpdated',\n start: start.position,\n current: point,\n distance,\n })\n }\n\n private completeMeasurement(snapResult: SnapResult): void {\n if (!this.currentMeasurement) return\n\n const start = this.currentMeasurement.start!\n const point = snapResult.point\n const options =\n this.pendingMeasurementOptions ??\n this.activeInteractionOptions ??\n this.defaultOptions\n\n this.disableInteraction()\n\n // Clean up preview\n this.cleanupPreview()\n\n const resolvedOptions: MeasurementOptions = {\n ...options,\n targets: [...options.targets],\n }\n\n const endPoint =\n resolvedOptions.isDynamic && snapResult.object\n ? this.createMeasurementPoint(point, snapResult.object)\n : this.createMeasurementPoint(point)\n\n // Create actual measurement using the measurement points\n this.addMeasurementFromPoints(start, endPoint, resolvedOptions)\n\n // Reset current measurement and object references\n this.currentMeasurement = null\n this.pendingMeasurementOptions = null\n\n // Re-create snap marker for next measurement\n this.createSnapMarker()\n }\n\n private cancelCurrentMeasurement(): void {\n this.cleanupPreview()\n this.currentMeasurement = null\n this.pendingMeasurementOptions = null\n\n // Re-create snap marker after canceling\n this.createSnapMarker()\n }\n\n private cleanupPreview(): void {\n if (this.previewLine) {\n this.scene.remove(this.previewLine)\n this.previewLine.geometry.dispose()\n this.previewLine = null\n }\n\n if (this.previewLabel) {\n this.scene.remove(this.previewLabel)\n // CSS2DObject cleanup - remove the HTML element from DOM\n if (this.previewLabel.element.parentNode) {\n this.previewLabel.element.parentNode.removeChild(\n this.previewLabel.element\n )\n }\n this.previewLabel = null\n }\n }\n\n private getSnapResult(event: MouseEvent): SnapResult | null {\n const mouse = new THREE.Vector2()\n const rect = this.domElement!.getBoundingClientRect()\n\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1\n\n const options =\n this.getActiveMeasurementOptions() ?? this.defaultOptions\n const targets =\n this.activeTargets.length > 0\n ? this.activeTargets\n : options.targets.length > 0\n ? options.targets\n : this.getAllMeshes()\n\n this.raycaster.setFromCamera(mouse, this.camera)\n const intersects = this.raycaster.intersectObjects(targets, true)\n\n if (intersects.length === 0) return null\n\n const intersection = intersects[0]\n let snapPoint = intersection.point.clone()\n let snapped = false\n let snapMode = SnapMode.DISABLED\n\n if (options.snapEnabled) {\n const snapResult = this.performSnapping(intersection, options)\n snapPoint = snapResult.point\n snapped = snapResult.snapped\n snapMode = snapResult.snapMode\n }\n\n return {\n point: snapPoint,\n originalPoint: intersection.point,\n snapped,\n snapMode,\n object: intersection.object,\n }\n }\n\n private performSnapping(\n intersection: THREE.Intersection,\n options: MeasurementOptions\n ): SnapResult {\n const originalPoint = intersection.point\n let snapPoint = originalPoint.clone()\n let snapped = false\n let snapMode = SnapMode.DISABLED\n\n if (options.snapMode === SnapMode.VERTEX) {\n const vertexSnap = this.snapToVertex(intersection, options.snapDistance)\n if (vertexSnap) {\n snapPoint = vertexSnap\n snapped = true\n snapMode = SnapMode.VERTEX\n }\n } else if (options.snapMode === SnapMode.FACE) {\n // Face snapping uses the intersection point (already on face)\n snapped = true\n snapMode = SnapMode.FACE\n }\n\n return {\n point: snapPoint,\n originalPoint,\n snapped,\n snapMode,\n object: intersection.object,\n }\n }\n\n private snapToVertex(\n intersection: THREE.Intersection,\n snapDistance: number\n ): THREE.Vector3 | null {\n const geometry = (intersection.object as THREE.Mesh).geometry\n if (!geometry.attributes.position) return null\n\n const positions = geometry.attributes.position\n const worldMatrix = intersection.object.matrixWorld\n const closestVertex = new THREE.Vector3()\n let minDistance = Infinity\n let found = false\n\n // Check all vertices\n for (let i = 0; i < positions.count; i++) {\n const vertex = new THREE.Vector3()\n vertex.fromBufferAttribute(positions, i)\n vertex.applyMatrix4(worldMatrix)\n\n const distance = vertex.distanceTo(intersection.point)\n if (distance < snapDistance && distance < minDistance) {\n minDistance = distance\n closestVertex.copy(vertex)\n found = true\n }\n }\n\n return found ? closestVertex : null\n }\n\n private createLabel(\n distance: number,\n options: MeasurementOptions\n ): CSS2DObject {\n // Create HTML element for the label\n const labelDiv = document.createElement('div')\n labelDiv.className = 'measurement-label'\n\n // Set styles for the label\n Object.assign(labelDiv.style, {\n color: options.labelColor,\n fontSize: `${options.fontSize}px`,\n fontFamily: options.fontFamily,\n fontWeight: 'bold',\n background: 'rgba(0, 0, 0, 0.9)',\n padding: '8px 12px',\n borderRadius: '8px',\n border: '2px solid rgba(255, 255, 255, 0.3)',\n whiteSpace: 'nowrap',\n userSelect: 'none',\n pointerEvents: 'auto', // Enable pointer events for double-click\n boxShadow: '0 2px 8px rgba(0, 0, 0, 0.5)',\n textShadow: '1px 1px 2px rgba(0, 0, 0, 0.8)',\n zIndex: '1000',\n cursor: 'pointer',\n })\n\n // Update the text content\n this.updateLabelText(labelDiv, distance)\n\n // Create CSS2DObject\n const css2dObject = new CSS2DObject(labelDiv)\n\n // Add double-click event listener to enter edit mode\n labelDiv.addEventListener('dblclick', (event) => {\n event.stopPropagation()\n // Find the measurement that owns this label\n const measurement = this.measurements.find((m) => m.label === css2dObject)\n if (measurement) {\n this.enterEditMode(measurement.id)\n }\n })\n\n return css2dObject\n }\n\n private updateLabelText(element: HTMLElement, distance: number): void {\n const text = `${distance.toFixed(2)}m`\n element.textContent = text\n }\n\n private removeMeasurementFromScene(measurement: Measurement): void {\n this.scene.remove(measurement.line)\n this.scene.remove(measurement.label)\n\n measurement.line.geometry.dispose()\n if (measurement.line.material instanceof THREE.Material) {\n measurement.line.material.dispose()\n }\n\n // CSS2DObject cleanup - remove the HTML element from DOM\n if (measurement.label.element.parentNode) {\n measurement.label.element.parentNode.removeChild(\n measurement.label.element\n )\n }\n }\n\n private getAllMeshes(): THREE.Object3D[] {\n const meshes: THREE.Object3D[] = []\n\n this.scene.traverse((object) => {\n if (object instanceof THREE.Mesh) {\n meshes.push(object)\n }\n })\n\n return meshes\n }\n\n private generateId(): string {\n return `measurement_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n }\n\n // Edit mode helper methods\n\n private createEditSprites(): void {\n if (!this.editingMeasurement || !this.editSpriteMaterial) return\n\n const measurement = this.editingMeasurement\n\n // Create start point sprite\n this.startEditSprite = new THREE.Sprite(this.editSpriteMaterial.clone())\n this.startEditSprite.position.copy(measurement.start.position)\n this.startEditSprite.scale.set(this.markerSize, this.markerSize, 1)\n this.startEditSprite.userData.editPoint = 'start'\n this.scene.add(this.startEditSprite)\n\n // Create end point sprite\n this.endEditSprite = new THREE.Sprite(this.editSpriteMaterial.clone())\n this.endEditSprite.position.copy(measurement.end.position)\n this.endEditSprite.scale.set(this.markerSize, this.markerSize, 1)\n this.endEditSprite.userData.editPoint = 'end'\n this.scene.add(this.endEditSprite)\n }\n\n private removeEditSprites(): void {\n if (this.startEditSprite) {\n this.scene.remove(this.startEditSprite)\n if (this.startEditSprite.material instanceof THREE.Material) {\n this.startEditSprite.material.dispose()\n }\n this.startEditSprite = null\n }\n\n if (this.endEditSprite) {\n this.scene.remove(this.endEditSprite)\n if (this.endEditSprite.material instanceof THREE.Material) {\n this.endEditSprite.material.dispose()\n }\n this.endEditSprite = null\n }\n }\n\n private onEditMouseDown = (event: MouseEvent): void => {\n if (!this.isEditMode || !this.domElement) return\n const mouse = new THREE.Vector2()\n const rect = this.domElement.getBoundingClientRect()\n\n mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1\n mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1\n\n this.raycaster.setFromCamera(mouse, this.camera)\n\n // Check if clicking on edit sprites\n const sprites = [this.startEditSprite, this.endEditSprite].filter(\n (s) => s !== null\n ) as THREE.Sprite[]\n const spriteIntersects = this.raycaster.intersectObjects(sprites)\n\n if (spriteIntersects.length > 0) {\n const sprite = spriteIntersects[0].object\n this.editingPoint = sprite.userData.editPoint as 'start' | 'end'\n this.isDragging = true\n\n // Disable camera controls during dragging\n this.disableControls()\n\n // Hide the edit sprite being dragged and show crosshair marker\n if (this.editingPoint === 'start' && this.startEditSprite) {\n this.startEditSprite.visible = false\n } else if (this.editingPoint === 'end' && this.endEditSprite) {\n this.endEditSprite.visible = false\n }\n\n // Show snap marker\n this.createSnapMarker()\n if (this.snapMarker) {\n this.snapMarker.position.copy(sprite.position)\n this.snapMarker.visible = true\n }\n\n // Hide cursor\n this.hideCursor()\n }\n }\n\n private onEditMouseMove = (event: MouseEvent): void => {\n if (!this.isEditMode || !this.isDragging || !this.editingMeasurement) return\n\n const snapResult = this.getSnapResult(event)\n if (!snapResult) return\n\n // Update snap marker position\n if (this.snapMarker) {\n this.snapMarker.position.copy(snapResult.point)\n this.snapMarker.visible = this.markerVisible\n }\n\n // Update the measurement preview\n if (this.editingPoint === 'start') {\n this.updateMeasurementPreview(\n snapResult.point,\n this.editingMeasurement.end.position\n )\n } else if (this.editingPoint === 'end') {\n this.updateMeasurementPreview(\n this.editingMeasurement.start.position,\n snapResult.point\n )\n }\n }\n\n private onEditMouseUp = (event: MouseEvent): void => {\n if (\n !this.isEditMode ||\n !this.isDragging ||\n !this.editingMeasurement ||\n !this.editingPoint\n )\n return\n\n const snapResult = this.getSnapResult(event)\n if (!snapResult) {\n this.cancelEdit()\n return\n }\n\n // Update the measurement point\n const point =\n this.editingPoint === 'start'\n ? this.editingMeasurement.start\n : this.editingMeasurement.end\n\n // Update position\n point.position.copy(snapResult.point)\n\n // Update dynamic point data if applicable\n const measurementOptions = this.editingMeasurement.options\n if (measurementOptions.isDynamic && snapResult.object) {\n const localPos = snapResult.object.worldToLocal(snapResult.point.clone())\n point.anchor = {\n object: snapResult.object,\n localPosition: localPos,\n }\n } else {\n // Make it static\n point.anchor = undefined\n }\n\n // Recalculate distance and update geometry\n const newDistance = this.editingMeasurement.start.position.distanceTo(\n this.editingMeasurement.end.position\n )\n this.editingMeasurement.distance = newDistance\n\n // Update line geometry\n const positions = [\n this.editingMeasurement.start.position,\n this.editingMeasurement.end.position,\n ]\n this.editingMeasurement.line.geometry.setFromPoints(positions)\n this.editingMeasurement.line.geometry.attributes.position.needsUpdate = true\n\n // Update label position and text\n const midpoint = this.editingMeasurement.start.position\n .clone()\n .add(this.editingMeasurement.end.position)\n .multiplyScalar(0.5)\n this.editingMeasurement.label.position.copy(midpoint)\n this.updateLabelText(this.editingMeasurement.label.element, newDistance)\n\n // Update edit sprite positions\n if (this.startEditSprite) {\n this.startEditSprite.position.copy(this.editingMeasurement.start.position)\n this.startEditSprite.visible = true\n }\n if (this.endEditSprite) {\n this.endEditSprite.position.copy(this.editingMeasurement.end.position)\n this.endEditSprite.visible = true\n }\n\n // Remove snap marker\n this.removeSnapMarker()\n\n // Show cursor\n this.showCursor()\n\n // Re-enable camera controls\n this.enableControls()\n\n // Dispatch update event\n this.dispatchEvent({\n type: 'measurementUpdated',\n measurement: this.editingMeasurement,\n })\n\n // Reset dragging state\n this.isDragging = false\n this.editingPoint = null\n }\n\n private cancelEdit(): void {\n // Reset dragging state\n this.isDragging = false\n this.editingPoint = null\n\n // Re-enable camera controls\n this.enableControls()\n\n // Show edit sprites\n if (this.startEditSprite) {\n this.startEditSprite.visible = true\n }\n if (this.endEditSprite) {\n this.endEditSprite.visible = true\n }\n\n // Remove snap marker\n this.removeSnapMarker()\n\n // Show cursor\n this.showCursor()\n }\n\n private updateMeasurementPreview(\n startPos: THREE.Vector3,\n endPos: THREE.Vector3\n ): void {\n if (!this.editingMeasurement) return\n\n const distance = startPos.distanceTo(endPos)\n\n // Update line geometry\n const positions = [startPos, endPos]\n this.editingMeasurement.line.geometry.setFromPoints(positions)\n this.editingMeasurement.line.geometry.attributes.position.needsUpdate = true\n\n // Update label position and text\n const midpoint = startPos.clone().add(endPos).multiplyScalar(0.5)\n this.editingMeasurement.label.position.copy(midpoint)\n this.updateLabelText(this.editingMeasurement.label.element, distance)\n }\n}\n","import * as THREE from 'three'\nimport { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'\n\n/**\n * Defines how a measurement point is attached to a scene object.\n */\nexport interface MeasurementAnchor {\n /** Object the point is attached to */\n object: THREE.Object3D\n /** Local position relative to the object */\n localPosition: THREE.Vector3\n}\n\n/**\n * Represents a measurement point in world space with an optional anchor.\n */\nexport interface MeasurementPoint {\n /** World position of the measurement point */\n position: THREE.Vector3\n /** Optional attachment data for dynamic updates */\n anchor?: MeasurementAnchor\n}\n\n/**\n * Per-measurement configuration captured at creation time.\n */\nexport interface MeasurementOptions {\n /** Render color for the measurement line */\n lineColor: number\n /** Render color for the measurement label text */\n labelColor: string\n /** Width of the rendered line */\n lineWidth: number\n /** Font size for label text */\n fontSize: number\n /** Font family for label text */\n fontFamily: string\n /** Snapping mode used when the measurement was created */\n snapMode: SnapMode\n /** Whether snapping was enabled for this measurement */\n snapEnabled: boolean\n /** Snap distance threshold for this measurement */\n snapDistance: number\n /** Targets that were considered for snapping */\n targets: THREE.Object3D[]\n /** Whether this measurement should remain linked to scene objects */\n isDynamic: boolean\n}\n\n/**\n * Runtime representation of a measurement inside the scene.\n */\nexport interface Measurement {\n /** Unique identifier for the measurement */\n id: string\n /** Starting point of the measurement */\n start: MeasurementPoint\n /** Ending point of the measurement */\n end: MeasurementPoint\n /** The line geometry representing the measurement */\n line: THREE.Line\n /** The CSS2D label showing the distance */\n label: CSS2DObject\n /** The calculated distance between start and end points */\n distance: number\n /** Config that should be reused when editing this measurement */\n options: MeasurementOptions\n}\n\n/**\n * Options accepted when creating or importing a measurement.\n */\nexport interface MeasurementCreationOptions {\n /** Explicit measurement identifier */\n id?: string\n /** Objects that should be considered for snapping/intersections */\n targets?: THREE.Object3D[]\n /** Whether snapping should be enabled */\n snapEnabled?: boolean\n /** Snap distance threshold */\n snapDistance?: number\n /** Snapping mode */\n snapMode?: SnapMode\n /** Line color */\n lineColor?: number\n /** Label color */\n labelColor?: string\n /** Line width */\n lineWidth?: number\n /** Label font size */\n fontSize?: number\n /** Label font family */\n fontFamily?: string\n /** Whether the measurement should stay linked to objects */\n isDynamic?: boolean\n /** Object the start point should follow */\n startObject?: THREE.Object3D\n /** Local position relative to startObject (defaults to world position converted to local) */\n startLocalPosition?: THREE.Vector3\n /** Object the end point should follow */\n endObject?: THREE.Object3D\n /** Local position relative to endObject (defaults to world position converted to local) */\n endLocalPosition?: THREE.Vector3\n}\n\n/**\n * Serializable measurement point data for export/import.\n */\nexport interface MeasurementPointData {\n /** Position as array [x, y, z] */\n position: [number, number, number]\n /** UUID of the anchor object if the point is dynamic */\n anchorObjectId?: string\n /** Local position relative to the anchor object */\n anchorLocalPosition?: [number, number, number]\n}\n\n/**\n * Serializable measurement configuration data.\n */\nexport interface SerializedMeasurementOptions {\n /** Snapping mode used by the measurement */\n snapMode: SnapMode\n /** Whether snapping was enabled for the measurement */\n snapEnabled: boolean\n /** Snap distance threshold used by the measurement */\n snapDistance: number\n /** Measurement line color */\n lineColor: number\n /** Measurement label color */\n labelColor: string\n /** Measurement line width */\n lineWidth: number\n /** Measurement label font size */\n fontSize: number\n /** Measurement label font family */\n fontFamily: string\n /** Whether the measurement should stay linked to objects */\n isDynamic: boolean\n /** UUIDs of the target objects captured for this measurement */\n targetObjectIds?: string[]\n}\n\n/**\n * Serializable measurement data for export/import.\n */\nexport interface MeasurementData {\n /** Unique identifier */\n id: string\n /** Starting point data */\n start: MeasurementPointData\n /** Ending point data */\n end: MeasurementPointData\n /** Calculated distance */\n distance: number\n /** Captured configuration for the measurement */\n options: SerializedMeasurementOptions\n}\n\n/**\n * Configuration options for the measurement tool\n */\nexport interface MeasurementToolOptions {\n /** DOM element for mouse interactions (required for interactive mode and editing) */\n domElement?: HTMLElement\n /** Camera controls to disable during edit dragging (e.g., OrbitControls) */\n controls?: { enabled: boolean }\n}\n\n/**\n * Snapping mode options\n */\nexport enum SnapMode {\n VERTEX = 'vertex',\n FACE = 'face',\n EDGE = 'edge',\n DISABLED = 'disabled',\n}\n\n/**\n * Event types dispatched by the measurement tool\n */\nexport interface MeasurementToolEvents {\n /** Fired when a new measurement is created */\n measurementCreated: { measurement: Measurement }\n /** Fired when a measurement is removed */\n measurementRemoved: { measurement: Measurement }\n /** Fired when all measurements are cleared */\n measurementsCleared: { count: number }\n /** Fired when interactive mode starts */\n started: {}\n /** Fired when interactive mode ends */\n ended: {}\n /** Fired when preview line is updated */\n previewUpdated: {\n start: THREE.Vector3\n current: THREE.Vector3\n distance: number\n }\n /** Fired when edit mode is entered */\n editModeEntered: { measurement: Measurement }\n /** Fired when edit mode is exited */\n editModeExited: { measurement: Measurement }\n /** Fired when a measurement is updated */\n measurementUpdated: { measurement: Measurement }\n}\n\n/**\n * Raycast result with snapping information\n */\nexport interface SnapResult {\n /** The snapped position */\n point: THREE.Vector3\n /** The original intersection point */\n originalPoint: THREE.Vector3\n /** Whether snapping occurred */\n snapped: boolean\n /** The snap mode that was applied */\n snapMode: SnapMode\n /** The object that was intersected */\n object: THREE.Object3D\n}\n","import * as THREE from 'three'\n\nexport type SunLightWeather = 'sunny' | 'partly-cloudy' | 'overcast'\n\nexport interface SunLightToolOptions {\n light?: THREE.DirectionalLight\n ambientLight?: THREE.Light\n latitude?: number\n longitude?: number\n dayOfYear?: number\n timeOfDay?: number\n timeZoneOffsetMinutes?: number\n referenceYear?: number\n useSystemTime?: boolean\n weather?: SunLightWeather\n showHelper?: boolean\n helperSize?: number\n helperColor?: number\n enableHemisphereLight?: boolean\n hemisphereSkyColor?: number\n hemisphereGroundColor?: number\n hemisphereIntensity?: number\n lightDistance?: number\n shadowCameraSize?: number\n shadowCameraFar?: number\n}\n\nexport interface SunLightState {\n date: Date\n latitude: number\n longitude: number\n solarAzimuth: number\n solarAltitude: number\n weather: SunLightWeather\n useSystemTime: boolean\n}\n\nexport interface SunLightToolEvents {\n stateChanged: { state: SunLightState }\n weatherChanged: { weather: SunLightWeather }\n systemTimeToggled: { useSystemTime: boolean }\n}\n\ninterface WeatherPresetConfig {\n sunIntensity: number\n sunColor: THREE.Color\n ambientIntensity: number\n ambientColor: THREE.Color\n hemisphereIntensity: number\n hemisphereSkyColor: THREE.Color\n hemisphereGroundColor: THREE.Color\n shadowBias: number\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000\nconst DEG2RAD = Math.PI / 180\nconst RAD2DEG = 180 / Math.PI\nconst J1970 = 2440588\nconst J2000 = 2451545\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(Math.max(value, min), max)\n\nconst normalizeLongitude = (value: number): number => {\n const normalized = ((((value + 180) % 360) + 360) % 360) - 180\n return normalized\n}\n\nconst isLeapYear = (year: number): boolean =>\n (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\n\nconst limitDayOfYear = (day: number, year: number): number => {\n const maxDay = isLeapYear(year) ? 366 : 365\n return clamp(Math.floor(day), 1, maxDay)\n}\n\nconst normalizeHours = (hours: number): number => {\n const normalized = hours % 24\n return normalized < 0 ? normalized + 24 : normalized\n}\n\nconst TWILIGHT_SUN_COLOR = new THREE.Color(0xff8c5c)\nconst TWILIGHT_AMBIENT_COLOR = new THREE.Color(0xffb48a)\nconst TWILIGHT_SKY_COLOR = new THREE.Color(0xff9966)\nconst TWILIGHT_GROUND_COLOR = new THREE.Color(0x362a24)\n\nconst toJulian = (date: Date): number => date.valueOf() / DAY_MS - 0.5 + J1970\nconst toDays = (date: Date): number => toJulian(date) - J2000\n\nconst solarMeanAnomaly = (days: number): number =>\n DEG2RAD * (357.5291 + 0.98560028 * days)\n\nconst eclipticLongitude = (meanAnomaly: number): number => {\n const c =\n DEG2RAD *\n (1.9148 * Math.sin(meanAnomaly) +\n 0.02 * Math.sin(2 * meanAnomaly) +\n 0.0003 * Math.sin(3 * meanAnomaly))\n const p = DEG2RAD * 102.9372\n return meanAnomaly + c + p + Math.PI\n}\n\nconst declination = (longitude: number): number => {\n const e = DEG2RAD * 23.4397\n return Math.asin(Math.sin(e) * Math.sin(longitude))\n}\n\nconst rightAscension = (longitude: number): number => {\n const e = DEG2RAD * 23.4397\n return Math.atan2(Math.sin(longitude) * Math.cos(e), Math.cos(longitude))\n}\n\nconst siderealTime = (days: number, longitudeWest: number): number =>\n DEG2RAD * (280.16 + 360.9856235 * days) - longitudeWest\n\nconst solarAzimuth = (\n hourAngle: number,\n latitudeRad: number,\n declinationRad: number\n): number =>\n Math.atan2(\n Math.sin(hourAngle),\n Math.cos(hourAngle) * Math.sin(latitudeRad) -\n Math.tan(declinationRad) * Math.cos(latitudeRad)\n )\n\nconst solarAltitude = (\n hourAngle: number,\n latitudeRad: number,\n declinationRad: number\n): number =>\n Math.asin(\n Math.sin(latitudeRad) * Math.sin(declinationRad) +\n Math.cos(latitudeRad) * Math.cos(declinationRad) * Math.cos(hourAngle)\n )\n\nconst computeDayOfYear = (date: Date): number => {\n const startOfYear = Date.UTC(date.getUTCFullYear(), 0, 0)\n const diff = date.getTime() - startOfYear\n return Math.floor(diff / (24 * 60 * 60 * 1000))\n}\n\nconst buildWeatherPreset = (\n weather: SunLightWeather,\n solarAltitude: number\n): WeatherPresetConfig => {\n const altitudeFactor = clamp(Math.sin(solarAltitude) + 0.1, 0, 1)\n switch (weather) {\n case 'sunny':\n return {\n sunIntensity: 1.5 * altitudeFactor,\n sunColor: new THREE.Color(0xfff2cf),\n ambientIntensity: 0.35 + 0.45 * altitudeFactor,\n ambientColor: new THREE.Color(0xf5e7cf),\n hemisphereIntensity: 0.4 + 0.4 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xb8d8ff),\n hemisphereGroundColor: new THREE.Color(0xf4d1aa),\n shadowBias: -0.0005,\n }\n case 'partly-cloudy':\n return {\n sunIntensity: 1.1 * altitudeFactor,\n sunColor: new THREE.Color(0xfff6e5),\n ambientIntensity: 0.45 + 0.35 * altitudeFactor,\n ambientColor: new THREE.Color(0xe8ecf1),\n hemisphereIntensity: 0.5 + 0.3 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xc8d7eb),\n hemisphereGroundColor: new THREE.Color(0xe6d9c2),\n shadowBias: -0.0003,\n }\n case 'overcast':\n return {\n sunIntensity: 0.35 * altitudeFactor,\n sunColor: new THREE.Color(0xf0f4ff),\n ambientIntensity: 0.75,\n ambientColor: new THREE.Color(0xd9dde5),\n hemisphereIntensity: 0.8,\n hemisphereSkyColor: new THREE.Color(0xcdd5df),\n hemisphereGroundColor: new THREE.Color(0xc8c8c8),\n shadowBias: -0.0001,\n }\n default:\n return {\n sunIntensity: 1.0 * altitudeFactor,\n sunColor: new THREE.Color(0xffd9b3),\n ambientIntensity: 0.35 + 0.25 * altitudeFactor,\n ambientColor: new THREE.Color(0xffe3c4),\n hemisphereIntensity: 0.4 + 0.3 * altitudeFactor,\n hemisphereSkyColor: new THREE.Color(0xffc8a3),\n hemisphereGroundColor: new THREE.Color(0x5f463a),\n shadowBias: -0.0002,\n }\n }\n}\n\nexport class SunLightTool extends THREE.EventDispatcher<SunLightToolEvents> {\n private scene: THREE.Scene\n private light: THREE.DirectionalLight\n private ambientLight?: THREE.Light\n private hemisphereLight?: THREE.HemisphereLight\n private helper?: THREE.DirectionalLightHelper\n private createdLight: boolean = false\n private createdHemisphere: boolean = false\n private latitude: number\n private longitude: number\n private dayOfYear: number\n private timeOfDay: number\n private timeZoneOffsetMinutes: number\n private referenceYear: number\n private weather: SunLightWeather\n private useSystemTime: boolean\n private lightDistance: number\n private shadowCameraSize: number\n private shadowCameraFar: number\n private state: SunLightState\n\n constructor(scene: THREE.Scene, options: SunLightToolOptions = {}) {\n super()\n this.scene = scene\n const defaultLatitude = options.latitude ?? 51.5072\n const defaultLongitude = options.longitude ?? -0.1276\n this.latitude = clamp(defaultLatitude, -90, 90)\n this.longitude = normalizeLongitude(defaultLongitude)\n this.referenceYear = options.referenceYear ?? new Date().getUTCFullYear()\n this.dayOfYear = limitDayOfYear(\n options.dayOfYear ?? 172,\n this.referenceYear\n )\n this.timeOfDay = normalizeHours(options.timeOfDay ?? 12)\n this.timeZoneOffsetMinutes = options.timeZoneOffsetMinutes ?? 0\n this.weather = options.weather ?? 'sunny'\n this.useSystemTime = options.useSystemTime ?? false\n this.lightDistance = options.lightDistance ?? 150\n this.shadowCameraSize = options.shadowCameraSize ?? 100\n this.shadowCameraFar = options.shadowCameraFar ?? 600\n\n const existingDirectional = options.light\n this.light =\n existingDirectional ?? new THREE.DirectionalLight(0xffffff, 1.0)\n this.createdLight = !existingDirectional\n\n if (!this.light.parent) {\n this.scene.add(this.light)\n }\n\n if (!this.light.target.parent) {\n this.scene.add(this.light.target)\n }\n\n this.configureShadowMap(this.light)\n\n if (options.ambientLight) {\n this.ambientLight = options.ambientLight\n }\n\n if (options.enableHemisphereLight ?? true) {\n this.hemisphereLight = new THREE.HemisphereLight(\n options.hemisphereSkyColor ?? 0xbad4ff,\n options.hemisphereGroundColor ?? 0x74675a,\n options.hemisphereIntensity ?? 0.45\n )\n this.scene.add(this.hemisphereLight)\n this.createdHemisphere = true\n }\n\n if (options.showHelper) {\n this.helper = new THREE.DirectionalLightHelper(\n this.light,\n options.helperSize ?? 25,\n options.helperColor ?? 0xffd27f\n )\n this.scene.add(this.helper)\n }\n\n this.state = {\n date: new Date(),\n latitude: this.latitude,\n longitude: this.longitude,\n solarAzimuth: 0,\n solarAltitude: 0,\n weather: this.weather,\n useSystemTime: this.useSystemTime,\n }\n\n this.update()\n }\n\n getLight(): THREE.DirectionalLight {\n return this.light\n }\n\n getHemisphereLight(): THREE.HemisphereLight | undefined {\n return this.hemisphereLight\n }\n\n getState(): SunLightState {\n return { ...this.state, date: new Date(this.state.date.getTime()) }\n }\n\n getDayOfYear(): number {\n return this.dayOfYear\n }\n\n getTimeOfDay(): number {\n return this.timeOfDay\n }\n\n getTimeZoneOffset(): number {\n return this.timeZoneOffsetMinutes\n }\n\n getWeather(): SunLightWeather {\n return this.weather\n }\n\n usesSystemTime(): boolean {\n return this.useSystemTime\n }\n\n setLatitude(latitude: number): void {\n const clamped = clamp(latitude, -90, 90)\n if (clamped === this.latitude) return\n this.latitude = clamped\n this.update()\n }\n\n setLongitude(longitude: number): void {\n const normalized = normalizeLongitude(longitude)\n if (normalized === this.longitude) return\n this.longitude = normalized\n this.update()\n }\n\n setLocation(latitude: number, longitude: number): void {\n let changed = false\n const lat = clamp(latitude, -90, 90)\n if (lat !== this.latitude) {\n this.latitude = lat\n changed = true\n }\n const lon = normalizeLongitude(longitude)\n if (lon !== this.longitude) {\n this.longitude = lon\n changed = true\n }\n if (changed) {\n this.update()\n }\n }\n\n setDayOfYear(day: number): void {\n const limited = limitDayOfYear(day, this.referenceYear)\n if (limited === this.dayOfYear) return\n this.dayOfYear = limited\n this.update()\n }\n\n setTimeOfDay(hours: number): void {\n const normalized = normalizeHours(hours)\n if (normalized === this.timeOfDay) return\n this.timeOfDay = normalized\n this.update()\n }\n\n setTimeZoneOffset(minutes: number): void {\n if (minutes === this.timeZoneOffsetMinutes) return\n this.timeZoneOffsetMinutes = minutes\n this.update()\n }\n\n setWeather(weather: SunLightWeather): void {\n if (weather === this.weather) return\n this.weather = weather\n this.dispatchEvent({ type: 'weatherChanged', weather })\n this.update()\n }\n\n setUseSystemTime(enabled: boolean): void {\n if (enabled === this.useSystemTime) return\n this.useSystemTime = enabled\n this.dispatchEvent({\n type: 'systemTimeToggled',\n useSystemTime: this.useSystemTime,\n })\n this.update()\n }\n\n update(dateOverride?: Date): void {\n const date = this.computeDate(dateOverride)\n const position = this.computeSunPosition(date)\n this.applySunPosition(position, date)\n this.state = {\n date,\n latitude: this.latitude,\n longitude: this.longitude,\n solarAzimuth: position.azimuth,\n solarAltitude: position.altitude,\n weather: this.weather,\n useSystemTime: this.useSystemTime,\n }\n this.applyWeather(position.altitude)\n this.dispatchEvent({ type: 'stateChanged', state: this.getState() })\n }\n\n dispose(): void {\n if (this.helper) {\n this.scene.remove(this.helper)\n this.helper.dispose()\n this.helper = undefined\n }\n\n if (this.createdHemisphere && this.hemisphereLight) {\n this.scene.remove(this.hemisphereLight)\n this.hemisphereLight.dispose()\n this.hemisphereLight = undefined\n }\n\n if (this.createdLight && this.light) {\n this.scene.remove(this.light)\n if (this.light.shadow?.map) {\n this.light.shadow.map.dispose()\n }\n this.light.dispose()\n }\n }\n\n private configureShadowMap(light: THREE.DirectionalLight): void {\n light.castShadow = true\n const camera = light.shadow.camera\n if (\n camera instanceof THREE.OrthographicCamera &&\n typeof this.shadowCameraSize === 'number'\n ) {\n const size = this.shadowCameraSize\n camera.left = -size\n camera.right = size\n camera.top = size\n camera.bottom = -size\n camera.near = 0.5\n camera.far = this.shadowCameraFar\n camera.updateProjectionMatrix()\n }\n light.shadow.mapSize.set(2048, 2048)\n light.shadow.bias = -0.0005\n }\n\n private computeDate(dateOverride?: Date): Date {\n if (dateOverride) {\n return new Date(dateOverride.getTime())\n }\n\n if (this.useSystemTime) {\n const now = new Date()\n this.referenceYear = now.getUTCFullYear()\n this.dayOfYear = computeDayOfYear(now)\n this.timeOfDay =\n now.getUTCHours() +\n now.getUTCMinutes() / 60 +\n now.getUTCSeconds() / 3600\n return now\n }\n\n const daysInYear = isLeapYear(this.referenceYear) ? 366 : 365\n const dayIndex = clamp(this.dayOfYear, 1, daysInYear)\n const date = new Date(Date.UTC(this.referenceYear, 0, 1, 0, 0, 0, 0))\n const minutesFromYearStart =\n (dayIndex - 1) * 24 * 60 +\n this.timeOfDay * 60 -\n this.timeZoneOffsetMinutes\n date.setUTCMinutes(minutesFromYearStart)\n return date\n }\n\n private computeSunPosition(date: Date): {\n azimuth: number\n altitude: number\n } {\n const days = toDays(date)\n const lw = -this.longitude * DEG2RAD\n const phi = this.latitude * DEG2RAD\n const meanAnomaly = solarMeanAnomaly(days)\n const longitude = eclipticLongitude(meanAnomaly)\n const decl = declination(longitude)\n const ra = rightAscension(longitude)\n const sidereal = siderealTime(days, lw)\n const hourAngle = sidereal - ra\n return {\n azimuth: solarAzimuth(hourAngle, phi, decl),\n altitude: solarAltitude(hourAngle, phi, decl),\n }\n }\n\n private applySunPosition(\n position: { azimuth: number; altitude: number },\n date: Date\n ): void {\n const radius = this.lightDistance\n const altitude = position.altitude\n // Astronomical azimuth: 0° = South, increasing clockwise (East=90°, North=180°, West=270°)\n // Three.js coordinates: +X = East, +Z = North, -X = West, -Z = South\n // The solarAzimuth function returns azimuth measured from South, clockwise\n const azimuth = position.azimuth\n\n // Correct coordinate mapping for Three.js\n // sin(azimuth) gives us the East-West component, but we need to negate it:\n // azimuth 90° (East) should give +X, azimuth 270° (West) should give -X\n // cos(azimuth) gives us the North-South component, also needs to be positive for correct clockwise motion:\n // azimuth 0° (South) should give -Z, azimuth 180° (North) should give +Z\n const x = -radius * Math.cos(altitude) * Math.sin(azimuth)\n const y = radius * Math.sin(altitude)\n const z = radius * Math.cos(altitude) * Math.cos(azimuth)\n\n this.light.position.set(x, y, z)\n this.light.target.position.set(0, 0, 0)\n this.light.target.updateMatrixWorld()\n\n if (this.helper) {\n this.helper.update()\n }\n\n // Update cached time properties when not using real-time\n if (!this.useSystemTime) {\n this.referenceYear = date.getUTCFullYear()\n }\n }\n\n private applyWeather(solarAltitude: number): void {\n const preset = buildWeatherPreset(this.weather, solarAltitude)\n const altitudeDeg = solarAltitude * RAD2DEG\n const twilightStartDeg = -6\n const daylightDeg = 4\n const daylightRange = daylightDeg - twilightStartDeg\n\n const daylightFactor = clamp(\n (altitudeDeg - twilightStartDeg) / daylightRange,\n 0,\n 1\n )\n const twilightFactor = 1 - daylightFactor\n\n const sunColor = preset.sunColor.lerp(TWILIGHT_SUN_COLOR, twilightFactor)\n const ambientColor = preset.ambientColor.lerp(\n TWILIGHT_AMBIENT_COLOR,\n twilightFactor\n )\n const skyColor = preset.hemisphereSkyColor.lerp(\n TWILIGHT_SKY_COLOR,\n twilightFactor\n )\n const groundColor = preset.hemisphereGroundColor.lerp(\n TWILIGHT_GROUND_COLOR,\n twilightFactor\n )\n\n const adjustedSunIntensity = preset.sunIntensity * daylightFactor\n const adjustedAmbientIntensity = Math.max(\n 0.05,\n preset.ambientIntensity * (0.3 + 0.7 * daylightFactor)\n )\n const adjustedHemisphereIntensity = Math.max(\n 0.05,\n preset.hemisphereIntensity * (0.35 + 0.65 * daylightFactor)\n )\n\n this.light.intensity = adjustedSunIntensity\n this.light.visible = adjustedSunIntensity > 0.001\n this.light.color.copy(sunColor)\n this.light.shadow.bias = preset.shadowBias\n\n if (this.ambientLight) {\n this.ambientLight.intensity = adjustedAmbientIntensity\n this.ambientLight.color.copy(ambientColor)\n }\n\n if (this.hemisphereLight) {\n this.hemisphereLight.intensity = adjustedHemisphereIntensity\n this.hemisphereLight.color.copy(skyColor)\n this.hemisphereLight.groundColor.copy(groundColor)\n }\n }\n}\n","import * as THREE from 'three'\nimport {\n GeoCoordinates,\n TerrainDimensions,\n TerrainToolOptions,\n TerrainData,\n TerrainToolEvents,\n ElevationPoint,\n MapboxTextureOptions,\n} from './TerrainTypes'\n\ntype TerrainTextureSource = {\n url: string\n revokeOnUse: boolean\n}\n\n/**\n * Terrain mesh creator for Three.js scenes\n * Fetches elevation data from Open-Elevation API and creates 3D terrain meshes\n *\n * @example\n * ```javascript\n * const terrainTool = new TerrainTool(scene, {\n * widthSegments: 100,\n * depthSegments: 100,\n * elevationScale: 2.0,\n * useDemoData: false // Set to true for demo/testing without API\n * })\n *\n * // Listen for events\n * terrainTool.addEventListener('dataLoaded', (e) => {\n * console.log('Terrain data loaded:', e.data)\n * })\n *\n * terrainTool.addEventListener('meshLoaded', (e) => {\n * console.log('Terrain mesh created:', e.mesh)\n * })\n *\n * // Load terrain for a location\n * terrainTool.loadTerrain(\n * { latitude: 36.1699, longitude: -115.1398 }, // Las Vegas\n * { width: 5000, depth: 5000 } // 5km x 5km\n * )\n * ```\n */\nexport class TerrainTool extends THREE.EventDispatcher<TerrainToolEvents> {\n private scene: THREE.Scene\n private mesh: THREE.Mesh | null = null\n private currentData: TerrainData | null = null\n private isLoading: boolean = false\n private mapboxOptions?: MapboxTextureOptions\n private generatedTextureUrls: Set<string> = new Set()\n\n // Configuration\n public widthSegments: number\n public depthSegments: number\n public elevationScale: number\n public baseColor: number\n public wireframe: boolean\n public textureUrl: string | undefined\n public receiveShadow: boolean\n public castShadow: boolean\n public useDemoData: boolean\n\n /**\n * Creates a new TerrainTool instance\n * @param scene - The Three.js scene to add terrain to\n * @param options - Configuration options\n */\n constructor(scene: THREE.Scene, options: TerrainToolOptions = {}) {\n super()\n this.scene = scene\n\n // Apply options with defaults\n this.widthSegments = options.widthSegments ?? 50\n this.depthSegments = options.depthSegments ?? 50\n this.elevationScale = options.elevationScale ?? 1.0\n this.baseColor = options.baseColor ?? 0x8b7355\n this.wireframe = options.wireframe ?? false\n this.textureUrl = options.textureUrl\n this.mapboxOptions = options.mapbox\n this.receiveShadow = options.receiveShadow ?? true\n this.castShadow = options.castShadow ?? true\n this.useDemoData = options.useDemoData ?? false\n }\n\n /**\n * Update Mapbox imagery configuration at runtime\n */\n setMapboxOptions(options?: MapboxTextureOptions): void {\n this.mapboxOptions = options\n }\n\n /**\n * Loads terrain data and creates a mesh\n * @param center - Center coordinates (latitude, longitude)\n * @param dimensions - Terrain dimensions in meters\n */\n async loadTerrain(\n center: GeoCoordinates,\n dimensions: TerrainDimensions\n ): Promise<void> {\n if (this.isLoading) {\n console.warn('Terrain is already loading')\n return\n }\n\n this.isLoading = true\n this.dispatchEvent({\n type: 'updateStarted',\n center,\n dimensions,\n })\n\n try {\n // Fetch elevation data\n const terrainData = await this.fetchElevationData(center, dimensions)\n\n // Store the data\n this.currentData = terrainData\n\n // Dispatch data loaded event\n this.dispatchEvent({\n type: 'dataLoaded',\n data: terrainData,\n })\n\n const textureSource = await this.resolveTexture(center, dimensions)\n\n // Create and add mesh to scene\n await this.createMesh(terrainData, textureSource)\n } catch (error) {\n console.error('Error loading terrain:', error)\n this.dispatchEvent({\n type: 'error',\n message: 'Failed to load terrain',\n error: error as Error,\n })\n } finally {\n this.isLoading = false\n }\n }\n\n /**\n * Updates the terrain with new coordinates and/or dimensions\n * @param center - New center coordinates (optional, keeps current if not provided)\n * @param dimensions - New dimensions (optional, keeps current if not provided)\n */\n async updateTerrain(\n center?: GeoCoordinates,\n dimensions?: TerrainDimensions\n ): Promise<void> {\n if (!this.currentData && !center) {\n console.warn('No current terrain data and no center provided')\n return\n }\n\n const newCenter = center || this.currentData!.center\n const newDimensions = dimensions || this.currentData!.dimensions\n\n await this.loadTerrain(newCenter, newDimensions)\n }\n\n /**\n * Fetches elevation data from Open-Elevation API or generates demo data\n * @private\n */\n private async fetchElevationData(\n center: GeoCoordinates,\n dimensions: TerrainDimensions\n ): Promise<TerrainData> {\n if (this.useDemoData) {\n return this.generateDemoData(center, dimensions)\n }\n\n // Calculate grid of lat/lon points\n const points: { latitude: number; longitude: number }[] = []\n\n // Approximate degrees per meter at this latitude\n const metersPerDegreeLat = 111320\n const metersPerDegreeLon =\n 111320 *\n Math.max(Math.abs(Math.cos((center.latitude * Math.PI) / 180)), 1e-6)\n\n const latRange = dimensions.depth / metersPerDegreeLat\n const lonRange = dimensions.width / metersPerDegreeLon\n\n const latStep = latRange / this.depthSegments\n const lonStep = lonRange / this.widthSegments\n\n const startLat = center.latitude + latRange / 2\n const startLon = center.longitude - lonRange / 2\n\n // Create grid of points\n for (let z = 0; z <= this.depthSegments; z++) {\n for (let x = 0; x <= this.widthSegments; x++) {\n points.push({\n latitude: startLat - z * latStep,\n longitude: startLon + x * lonStep,\n })\n }\n }\n\n // Fetch elevation data from Open-Elevation API\n // Note: This API has rate limits and may not work for large requests\n // In production, you might want to use a different API or cache results\n const response = await fetch(\n 'https://api.open-elevation.com/api/v1/lookup',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n locations: points,\n }),\n }\n )\n\n if (!response.ok) {\n throw new Error(`Elevation API error: ${response.statusText}`)\n }\n\n const data = await response.json()\n const results: ElevationPoint[] = data.results\n\n // Convert to 2D grid\n const elevations: number[][] = []\n let minElevation = Infinity\n let maxElevation = -Infinity\n\n for (let z = 0; z <= this.depthSegments; z++) {\n const row: number[] = []\n for (let x = 0; x <= this.widthSegments; x++) {\n const index = z * (this.widthSegments + 1) + x\n const elevation = results[index].elevation\n row.push(elevation)\n minElevation = Math.min(minElevation, elevation)\n maxElevation = Math.max(maxElevation, elevation)\n }\n elevations.push(row)\n }\n\n return {\n center,\n dimensions,\n elevations,\n minElevation,\n maxElevation,\n }\n }\n\n /**\n * Generates demo terrain data using perlin-like noise\n * @private\n */\n private generateDemoData(\n center: GeoCoordinates,\n dimensions: TerrainDimensions\n ): TerrainData {\n const elevations: number[][] = []\n let minElevation = Infinity\n let maxElevation = -Infinity\n\n // Simple sine-based terrain generation for demo\n const seed = center.latitude + center.longitude\n for (let z = 0; z <= this.depthSegments; z++) {\n const row: number[] = []\n for (let x = 0; x <= this.widthSegments; x++) {\n // Create varied terrain using multiple sine waves\n const nx = (x / this.widthSegments) * 4\n const nz = (z / this.depthSegments) * 4\n\n let elevation = 0\n // Large features\n elevation += Math.sin(nx + seed) * 500\n elevation += Math.cos(nz + seed) * 500\n // Medium features\n elevation += Math.sin(nx * 2 + seed) * 200\n elevation += Math.cos(nz * 2 + seed) * 200\n // Small features\n elevation += Math.sin(nx * 4 + seed) * 50\n elevation += Math.cos(nz * 4 + seed) * 50\n // Random noise\n elevation += (Math.random() - 0.5) * 30\n\n row.push(elevation)\n minElevation = Math.min(minElevation, elevation)\n maxElevation = Math.max(maxElevation, elevation)\n }\n elevations.push(row)\n }\n\n return {\n center,\n dimensions,\n elevations,\n minElevation,\n maxElevation,\n }\n }\n\n /**\n * Creates a terrain mesh from elevation data\n * @private\n */\n private async createMesh(\n data: TerrainData,\n textureSource?: TerrainTextureSource\n ): Promise<void> {\n // Remove existing mesh if any\n if (this.mesh) {\n this.scene.remove(this.mesh)\n this.mesh.geometry.dispose()\n if (Array.isArray(this.mesh.material)) {\n this.mesh.material.forEach((mat) => mat.dispose())\n } else {\n this.mesh.material.dispose()\n }\n }\n\n // Create plane geometry\n const geometry = new THREE.PlaneGeometry(\n data.dimensions.width,\n data.dimensions.depth,\n this.widthSegments,\n this.depthSegments\n )\n\n // Apply elevation data to geometry vertices\n const positions = geometry.attributes.position\n let vertexIndex = 0\n\n for (let z = 0; z <= this.depthSegments; z++) {\n for (let x = 0; x <= this.widthSegments; x++) {\n const elevation = data.elevations[z][x]\n // Normalize elevation relative to min elevation\n const height = (elevation - data.minElevation) * this.elevationScale\n positions.setZ(vertexIndex, height)\n vertexIndex++\n }\n }\n\n // Recompute normals for proper lighting\n geometry.computeVertexNormals()\n\n // Create material\n let material: THREE.Material\n\n if (textureSource?.url) {\n try {\n const texture = await new THREE.TextureLoader().loadAsync(\n textureSource.url\n )\n material = new THREE.MeshStandardMaterial({\n map: texture,\n wireframe: this.wireframe,\n })\n } catch (error) {\n console.warn('Failed to load terrain texture, using base color.', error)\n material = new THREE.MeshStandardMaterial({\n color: this.baseColor,\n wireframe: this.wireframe,\n })\n } finally {\n if (textureSource.revokeOnUse) {\n this.releaseGeneratedTexture(textureSource.url)\n }\n }\n } else {\n material = new THREE.MeshStandardMaterial({\n color: this.baseColor,\n wireframe: this.wireframe,\n })\n }\n\n // Create mesh\n this.mesh = new THREE.Mesh(geometry, material)\n this.mesh.rotation.x = -Math.PI / 2 // Rotate to horizontal\n this.mesh.receiveShadow = this.receiveShadow\n this.mesh.castShadow = this.castShadow\n\n // Add to scene\n this.scene.add(this.mesh)\n\n // Dispatch mesh loaded event\n this.dispatchEvent({\n type: 'meshLoaded',\n mesh: this.mesh,\n })\n }\n\n private async resolveTexture(\n center: GeoCoordinates,\n dimensions: TerrainDimensions\n ): Promise<TerrainTextureSource | undefined> {\n if (this.textureUrl) {\n return {\n url: this.textureUrl,\n revokeOnUse: false,\n }\n }\n\n if (!this.mapboxOptions) {\n return undefined\n }\n\n try {\n const url = await this.fetchMapboxTexture(\n center,\n dimensions,\n this.mapboxOptions\n )\n this.generatedTextureUrls.add(url)\n return {\n url,\n revokeOnUse: true,\n }\n } catch (error) {\n console.warn(\n 'Failed to fetch Mapbox imagery, falling back to base material.',\n error\n )\n return undefined\n }\n }\n\n private computeBoundingBox(\n center: GeoCoordinates,\n dimensions: TerrainDimensions,\n paddingRatio: number\n ): { minLat: number; maxLat: number; minLon: number; maxLon: number } {\n const metersPerDegreeLat = 111320\n const latRadians = (center.latitude * Math.PI) / 180\n const cosLat = Math.cos(latRadians)\n const metersPerDegreeLon = 111320 * Math.max(Math.abs(cosLat), 1e-6)\n\n const appliedPadding = Math.max(0, paddingRatio)\n const widthWithPadding = dimensions.width * (1 + appliedPadding)\n const depthWithPadding = dimensions.depth * (1 + appliedPadding)\n\n const halfDepthDegrees = depthWithPadding / 2 / metersPerDegreeLat\n const halfWidthDegrees = widthWithPadding / 2 / metersPerDegreeLon\n\n const clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max)\n\n const minLat = clamp(center.latitude - halfDepthDegrees, -90, 90)\n const maxLat = clamp(center.latitude + halfDepthDegrees, -90, 90)\n const minLon = clamp(center.longitude - halfWidthDegrees, -180, 180)\n const maxLon = clamp(center.longitude + halfWidthDegrees, -180, 180)\n\n return { minLat, maxLat, minLon, maxLon }\n }\n\n private async fetchMapboxTexture(\n center: GeoCoordinates,\n dimensions: TerrainDimensions,\n options: MapboxTextureOptions\n ): Promise<string> {\n const styleId = options.styleId ?? 'mapbox/satellite-v9'\n const normalizedStyleId = styleId\n .replace('mapbox://styles/', '')\n .replace(/^\\/+/, '')\n\n const width = Math.min(\n 1280,\n Math.max(1, Math.floor(options.imageWidth ?? 1024))\n )\n const height = Math.min(\n 1280,\n Math.max(1, Math.floor(options.imageHeight ?? 1024))\n )\n const highResSuffix = options.highResolution ? '@2x' : ''\n const format = options.imageFormat ?? 'png'\n const paddingRatio = options.paddingRatio ?? 0.1\n\n const bounds = this.computeBoundingBox(center, dimensions, paddingRatio)\n const bbox = `${bounds.minLon.toFixed(6)},${bounds.minLat.toFixed(\n 6\n )},${bounds.maxLon.toFixed(6)},${bounds.maxLat.toFixed(6)}`\n\n const params = new URLSearchParams({\n access_token: options.accessToken,\n format,\n })\n\n const requestUrl = `https://api.mapbox.com/styles/v1/${normalizedStyleId}/static/[${bbox}]/${width}x${height}${highResSuffix}?${params.toString()}`\n\n const response = await fetch(requestUrl)\n if (!response.ok) {\n throw new Error(\n `Mapbox imagery request failed: ${response.status} ${response.statusText}`\n )\n }\n\n const blob = await response.blob()\n\n if (\n typeof URL === 'undefined' ||\n typeof URL.createObjectURL !== 'function'\n ) {\n throw new Error(\n 'URL.createObjectURL is not available in this environment'\n )\n }\n\n return URL.createObjectURL(blob)\n }\n\n private releaseGeneratedTexture(url: string): void {\n if (!this.generatedTextureUrls.has(url)) {\n return\n }\n\n if (\n typeof URL !== 'undefined' &&\n typeof URL.revokeObjectURL === 'function'\n ) {\n URL.revokeObjectURL(url)\n }\n\n this.generatedTextureUrls.delete(url)\n }\n\n /**\n * Gets the current terrain mesh\n */\n getMesh(): THREE.Mesh | null {\n return this.mesh\n }\n\n /**\n * Gets the current terrain data\n */\n getData(): TerrainData | null {\n return this.currentData\n }\n\n /**\n * Checks if terrain is currently loading\n */\n isTerrainLoading(): boolean {\n return this.isLoading\n }\n\n /**\n * Disposes of all resources\n */\n dispose(): void {\n if (this.mesh) {\n this.scene.remove(this.mesh)\n this.mesh.geometry.dispose()\n if (Array.isArray(this.mesh.material)) {\n this.mesh.material.forEach((mat) => mat.dispose())\n } else {\n this.mesh.material.dispose()\n }\n this.mesh = null\n }\n this.currentData = null\n\n if (this.generatedTextureUrls.size > 0) {\n for (const url of Array.from(this.generatedTextureUrls)) {\n this.releaseGeneratedTexture(url)\n }\n }\n }\n}\n","// @ts-nocheck\nimport {\n BoxGeometry,\n BufferGeometry,\n Camera,\n Controls,\n CylinderGeometry,\n DoubleSide,\n Euler,\n Float32BufferAttribute,\n Line,\n LineBasicMaterial,\n Matrix4,\n Mesh,\n MeshBasicMaterial,\n Object3D,\n OctahedronGeometry,\n PlaneGeometry,\n Quaternion,\n Raycaster,\n SphereGeometry,\n TorusGeometry,\n Vector3,\n Box3,\n} from 'three'\nimport { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js'\n\nconst _raycaster = new Raycaster()\n\nconst _tempVector = new Vector3()\nconst _tempVector2 = new Vector3()\nconst _tempQuaternion = new Quaternion()\nconst _unit = {\n X: new Vector3(1, 0, 0),\n Y: new Vector3(0, 1, 0),\n Z: new Vector3(0, 0, 1),\n}\n\n/**\n * Fires if any type of change (object or property change) is performed. Property changes\n * are separate events you can add event listeners to. The event type is \"propertyname-changed\".\n *\n * @event TransformControls#change\n * @type {Object}\n */\nconst _changeEvent = { type: 'change' }\n\n/**\n * Fires if a pointer (mouse/touch) becomes active.\n *\n * @event TransformControls#mouseDown\n * @type {Object}\n */\nconst _mouseDownEvent = { type: 'mouseDown', mode: null }\n\n/**\n * Fires if a pointer (mouse/touch) is no longer active.\n *\n * @event TransformControls#mouseUp\n * @type {Object}\n */\nconst _mouseUpEvent = { type: 'mouseUp', mode: null }\n\n/**\n * Fires if the controlled 3D object is changed.\n *\n * @event TransformControls#objectChange\n * @type {Object}\n */\nconst _objectChangeEvent = { type: 'objectChange' }\n\n/**\n * This class can be used to transform objects in 3D space by adapting a similar interaction model\n * of DCC tools like Blender. Unlike other controls, it is not intended to transform the scene's camera.\n *\n * `TransformControls` expects that its attached 3D object is part of the scene graph.\n *\n * @augments Controls\n */\nclass TransformControls extends Controls<{}> {\n // @ts-ignore - dynamic properties\n [key: string]: any\n\n _root: TransformControlsRoot\n _gizmo: TransformControlsGizmo\n _plane: TransformControlsPlane\n _overlay: HTMLDivElement\n _distanceLabel: CSS2DObject\n _activeMode: string // Tracks which mode is active during drag in 'all' mode\n _rotationArc: Line | null // Arc showing rotation angle\n _rotationAngleLabel: CSS2DObject // Label showing rotation angle\n\n _offset: Vector3\n _startNorm: Vector3\n _endNorm: Vector3\n _cameraScale: Vector3\n\n _parentPosition: Vector3\n _parentQuaternion: Quaternion\n _parentQuaternionInv: Quaternion\n _parentScale: Vector3\n\n _worldScaleStart: Vector3\n _worldQuaternionInv: Quaternion\n _worldScale: Vector3\n _tempPosition: Vector3\n\n _positionStart: Vector3\n _quaternionStart: Quaternion\n _scaleStart: Vector3\n\n _getPointer: (event: PointerEvent) => { x: number; y: number; button: number }\n _onPointerDown: (event: PointerEvent) => void\n _onPointerHover: (event: PointerEvent) => void\n _onPointerMove: (event: PointerEvent) => void\n _onPointerUp: (event: PointerEvent) => void\n\n /**\n * Constructs a new controls instance.\n *\n * @param {Camera} camera - The camera of the rendered scene.\n * @param {?HTMLDOMElement} domElement - The HTML element used for event listeners.\n */\n constructor(camera: Camera, domElement: HTMLElement | null = null) {\n super(undefined, domElement)\n\n const root = new TransformControlsRoot(this)\n this._root = root\n\n const gizmo = new TransformControlsGizmo()\n this._gizmo = gizmo\n root.add(gizmo)\n\n const plane = new TransformControlsPlane()\n this._plane = plane\n root.add(plane)\n\n const scope = this\n\n // Create overlay element\n this._overlay = document.createElement('div')\n this._overlay.classList.add('absolute')\n this._overlay.classList.add('bottom-2')\n this._overlay.classList.add('left-80')\n this._overlay.classList.add('z-50')\n this._overlay.classList.add('bg-gray-700')\n this._overlay.classList.add('bg-opacity-70')\n this._overlay.classList.add('text-white')\n this._overlay.classList.add('p-2')\n this._overlay.classList.add('rounded-md')\n this._overlay.classList.add('border')\n this._overlay.classList.add('border-gray-500')\n this._overlay.classList.add('hidden')\n\n if (domElement) {\n domElement.appendChild(this._overlay)\n }\n\n // Create CSS2D distance label\n const labelDiv = document.createElement('div')\n labelDiv.className = 'distance-label'\n labelDiv.style.padding = '4px 8px'\n labelDiv.style.background = 'rgba(0, 0, 0, 0.8)'\n labelDiv.style.border = '1px solid rgba(255, 255, 255, 0.3)'\n labelDiv.style.borderRadius = '4px'\n labelDiv.style.color = '#fff'\n labelDiv.style.fontSize = '12px'\n labelDiv.style.fontFamily = 'monospace'\n labelDiv.style.whiteSpace = 'nowrap'\n labelDiv.style.pointerEvents = 'none'\n labelDiv.style.userSelect = 'none'\n labelDiv.textContent = '0.00'\n\n this._distanceLabel = new CSS2DObject(labelDiv)\n this._distanceLabel.visible = false\n root.add(this._distanceLabel)\n\n // Create CSS2D rotation angle label\n const angleLabelDiv = document.createElement('div')\n angleLabelDiv.className = 'rotation-angle-label'\n angleLabelDiv.style.padding = '4px 8px'\n angleLabelDiv.style.background = 'rgba(0, 0, 0, 0.8)'\n angleLabelDiv.style.border = '1px solid rgba(255, 255, 255, 0.3)'\n angleLabelDiv.style.borderRadius = '4px'\n angleLabelDiv.style.color = '#fff'\n angleLabelDiv.style.fontSize = '12px'\n angleLabelDiv.style.fontFamily = 'monospace'\n angleLabelDiv.style.whiteSpace = 'nowrap'\n angleLabelDiv.style.pointerEvents = 'none'\n angleLabelDiv.style.userSelect = 'none'\n angleLabelDiv.textContent = '0°'\n\n this._rotationAngleLabel = new CSS2DObject(angleLabelDiv)\n this._rotationAngleLabel.visible = false\n root.add(this._rotationAngleLabel)\n\n // Initialize rotation arc (will be created dynamically)\n this._rotationArc = null\n\n // Defined getter, setter and store for a property\n function defineProperty(propName: string, defaultValue: any) {\n let propValue = defaultValue\n\n Object.defineProperty(scope, propName, {\n get: function () {\n return propValue !== undefined ? propValue : defaultValue\n },\n\n set: function (value: any) {\n if (propValue !== value) {\n propValue = value\n ;(plane as any)[propName] = value\n ;(gizmo as any)[propName] = value\n\n scope.dispatchEvent({\n type: propName + '-changed',\n value: value,\n } as any)\n scope.dispatchEvent(_changeEvent as any)\n }\n },\n })\n ;(scope as any)[propName] = defaultValue\n ;(plane as any)[propName] = defaultValue\n ;(gizmo as any)[propName] = defaultValue\n }\n\n // Define properties with getters/setter\n // Setting the defined property will automatically trigger change event\n // Defined properties are passed down to gizmo and plane\n\n /**\n * The camera of the rendered scene.\n *\n * @name TransformControls#camera\n * @type {Camera}\n */\n defineProperty('camera', camera)\n defineProperty('object', undefined)\n defineProperty('enabled', true)\n\n /**\n * The current transformation axis.\n *\n * @name TransformControls#axis\n * @type {string}\n */\n defineProperty('axis', null)\n\n /**\n * The current transformation axis.\n *\n * @name TransformControls#mode\n * @type {('translate'|'rotate'|'scale'|'all')}\n * @default 'all'\n */\n defineProperty('mode', 'all')\n\n /**\n * By default, 3D objects are continuously translated. If you set this property to a numeric\n * value (world units), you can define in which steps the 3D object should be translated.\n *\n * @name TransformControls#translationSnap\n * @type {?number}\n * @default null\n */\n defineProperty('translationSnap', null)\n\n /**\n * By default, 3D objects are continuously rotated. If you set this property to a numeric\n * value (radians), you can define in which steps the 3D object should be rotated.\n *\n * @name TransformControls#rotationSnap\n * @type {?number}\n * @default null\n */\n defineProperty('rotationSnap', null)\n\n /**\n * By default, 3D objects are continuously scaled. If you set this property to a numeric\n * value, you can define in which steps the 3D object should be scaled.\n *\n * @name TransformControls#scaleSnap\n * @type {?number}\n * @default null\n */\n defineProperty('scaleSnap', null)\n\n /**\n * Defines in which coordinate space transformations should be performed.\n *\n * @name TransformControls#space\n * @type {('world'|'local')}\n * @default 'world'\n */\n defineProperty('space', 'world')\n\n /**\n * The size of the helper UI (axes/planes).\n *\n * @name TransformControls#size\n * @type {number}\n * @default 1\n */\n defineProperty('size', 0.75)\n\n /**\n * Whether dragging is currently performed or not.\n *\n * @name TransformControls#dragging\n * @type {boolean}\n * @readonly\n * @default false\n */\n defineProperty('dragging', false)\n\n /**\n * The active transformation mode when in 'all' mode.\n *\n * @name TransformControls#activeMode\n * @type {('translate'|'rotate'|'scale')}\n * @readonly\n * @default 'translate'\n */\n defineProperty('activeMode', 'translate')\n\n /**\n * Whether the x-axis helper should be visible or not.\n *\n * @name TransformControls#showX\n * @type {boolean}\n * @default true\n */\n defineProperty('showX', true)\n\n /**\n * Whether the y-axis helper should be visible or not.\n *\n * @name TransformControls#showY\n * @type {boolean}\n * @default true\n */\n defineProperty('showY', true)\n\n /**\n * Whether the z-axis helper should be visible or not.\n *\n * @name TransformControls#showZ\n * @type {boolean}\n * @default true\n */\n defineProperty('showZ', true)\n\n /**\n * The minimum allowed X position during translation.\n *\n * @name TransformControls#minX\n * @type {number}\n * @default -Infinity\n */\n defineProperty('minX', -Infinity)\n\n /**\n * The maximum allowed X position during translation.\n *\n * @name TransformControls#maxX\n * @type {number}\n * @default Infinity\n */\n defineProperty('maxX', Infinity)\n\n /**\n * The minimum allowed y position during translation.\n *\n * @name TransformControls#minY\n * @type {number}\n * @default -Infinity\n */\n defineProperty('minY', -Infinity)\n\n /**\n * The maximum allowed Y position during translation.\n *\n * @name TransformControls#maxY\n * @type {number}\n * @default Infinity\n */\n defineProperty('maxY', Infinity)\n\n /**\n * The minimum allowed z position during translation.\n *\n * @name TransformControls#minZ\n * @type {number}\n * @default -Infinity\n */\n defineProperty('minZ', -Infinity)\n\n /**\n * The maximum allowed Z position during translation.\n *\n * @name TransformControls#maxZ\n * @type {number}\n * @default Infinity\n */\n defineProperty('maxZ', Infinity)\n\n /**\n * The minimum allowed rotation angle during rotation (in radians).\n *\n * @name TransformControls#minRotation\n * @type {number}\n * @default -2 * Math.PI (-360 degrees)\n */\n defineProperty('minRotation', -2 * Math.PI)\n\n /**\n * The maximum allowed rotation angle during rotation (in radians).\n *\n * @name TransformControls#maxRotation\n * @type {number}\n * @default 2 * Math.PI (360 degrees)\n */\n defineProperty('maxRotation', 2 * Math.PI)\n\n // Reusable utility variables\n\n const worldPosition = new Vector3()\n const worldPositionStart = new Vector3()\n const worldQuaternion = new Quaternion()\n const worldQuaternionStart = new Quaternion()\n const cameraPosition = new Vector3()\n const cameraQuaternion = new Quaternion()\n const pointStart = new Vector3()\n const pointEnd = new Vector3()\n const rotationAxis = new Vector3()\n const rotationAngle = 0\n const eye = new Vector3()\n\n // TODO: remove properties unused in plane and gizmo\n\n defineProperty('worldPosition', worldPosition)\n defineProperty('worldPositionStart', worldPositionStart)\n defineProperty('worldQuaternion', worldQuaternion)\n defineProperty('worldQuaternionStart', worldQuaternionStart)\n defineProperty('cameraPosition', cameraPosition)\n defineProperty('cameraQuaternion', cameraQuaternion)\n defineProperty('pointStart', pointStart)\n defineProperty('pointEnd', pointEnd)\n defineProperty('rotationAxis', rotationAxis)\n defineProperty('rotationAngle', rotationAngle)\n defineProperty('eye', eye)\n\n this._offset = new Vector3()\n this._startNorm = new Vector3()\n this._endNorm = new Vector3()\n this._cameraScale = new Vector3()\n\n this._parentPosition = new Vector3()\n this._parentQuaternion = new Quaternion()\n this._parentQuaternionInv = new Quaternion()\n this._parentScale = new Vector3()\n\n this._worldScaleStart = new Vector3()\n this._worldQuaternionInv = new Quaternion()\n this._worldScale = new Vector3()\n this._tempPosition = new Vector3()\n\n this._positionStart = new Vector3()\n this._quaternionStart = new Quaternion()\n this._scaleStart = new Vector3()\n\n this._getPointer = getPointer.bind(this)\n this._onPointerDown = onPointerDown.bind(this)\n this._onPointerHover = onPointerHover.bind(this)\n this._onPointerMove = onPointerMove.bind(this)\n this._onPointerUp = onPointerUp.bind(this)\n\n if (domElement !== null) {\n this.connect(domElement)\n }\n }\n\n connect(element: HTMLElement) {\n super.connect(element)\n\n if (this.domElement?.parentNode) {\n this.domElement.parentNode.appendChild(this._overlay)\n }\n\n this.domElement?.addEventListener('pointerdown', this._onPointerDown)\n this.domElement?.addEventListener('pointermove', this._onPointerHover)\n this.domElement?.addEventListener('pointerup', this._onPointerUp)\n\n if (this.domElement) {\n this.domElement.style.touchAction = 'none' // disable touch scroll\n }\n }\n\n disconnect() {\n if (this._overlay.parentNode) {\n this._overlay.parentNode.removeChild(this._overlay)\n }\n this.domElement?.removeEventListener('pointerdown', this._onPointerDown)\n this.domElement?.removeEventListener('pointermove', this._onPointerHover)\n this.domElement?.removeEventListener('pointermove', this._onPointerMove)\n this.domElement?.removeEventListener('pointerup', this._onPointerUp)\n\n if (this.domElement) {\n this.domElement.style.touchAction = 'auto'\n }\n }\n\n /**\n * Returns the visual representation of the controls. Add the helper to your scene to\n * visually transform the attached 3D object.\n *\n * @return {TransformControlsRoot} The helper.\n */\n getHelper() {\n return this._root\n }\n\n pointerHover(pointer) {\n if (this.object === undefined || this.dragging === true) return\n\n if (pointer !== null) _raycaster.setFromCamera(pointer, this.camera)\n\n let intersect = null\n\n if (this.mode === 'all') {\n // Check all pickers in order: scale, rotate, translate\n // This order ensures smaller handles (scale cubes) are prioritized\n intersect = intersectObjectWithRay(\n this._gizmo.picker['scale'],\n _raycaster\n )\n if (!intersect) {\n intersect = intersectObjectWithRay(\n this._gizmo.picker['rotate'],\n _raycaster\n )\n }\n if (!intersect) {\n intersect = intersectObjectWithRay(\n this._gizmo.picker['translate'],\n _raycaster\n )\n }\n } else {\n intersect = intersectObjectWithRay(\n this._gizmo.picker[this.mode],\n _raycaster\n )\n }\n\n if (intersect) {\n this.axis = intersect.object.name\n } else {\n this.axis = null\n }\n }\n\n pointerDown(pointer) {\n if (\n this.object === undefined ||\n this.dragging === true ||\n (pointer != null && pointer.button !== 0)\n )\n return\n\n if (this.axis !== null) {\n if (pointer !== null) _raycaster.setFromCamera(pointer, this.camera)\n\n // Determine which mode is active when in 'all' mode\n if (this.mode === 'all') {\n // Check which picker was intersected to determine the active mode\n let intersect = intersectObjectWithRay(\n this._gizmo.picker['scale'],\n _raycaster\n )\n if (intersect && intersect.object.name === this.axis) {\n this.activeMode = 'scale'\n } else {\n intersect = intersectObjectWithRay(\n this._gizmo.picker['rotate'],\n _raycaster\n )\n if (intersect && intersect.object.name === this.axis) {\n this.activeMode = 'rotate'\n } else {\n this.activeMode = 'translate'\n }\n }\n } else {\n this.activeMode = this.mode\n }\n\n const planeIntersect = intersectObjectWithRay(\n this._plane,\n _raycaster,\n true\n )\n\n if (planeIntersect) {\n this.object.updateMatrixWorld()\n this.object.parent.updateMatrixWorld()\n\n this._positionStart.copy(this.object.position)\n this._quaternionStart.copy(this.object.quaternion)\n this._scaleStart.copy(this.object.scale)\n\n // Use bounding box center for worldPositionStart\n const boundingBoxCenter = calculateBoundingBoxCenter(this.object)\n this.worldPositionStart.copy(boundingBoxCenter)\n\n // Still need to get rotation and scale from the object's matrix\n this.object.matrixWorld.decompose(\n this._tempPosition, // Use temporary variable for position\n this.worldQuaternionStart,\n this._worldScaleStart\n )\n\n this.pointStart.copy(planeIntersect.point).sub(this.worldPositionStart)\n }\n\n this.dragging = true\n _mouseDownEvent.mode = this.mode === 'all' ? this.activeMode : this.mode\n this.dispatchEvent(_mouseDownEvent)\n }\n }\n\n pointerMove(pointer) {\n const axis = this.axis\n // Use active mode when in 'all' mode, otherwise use the current mode\n const mode = this.mode === 'all' ? this.activeMode : this.mode\n const object = this.object\n let space = this.space\n\n if (mode === 'scale') {\n space = 'local'\n } else if (axis === 'E' || axis === 'XYZE' || axis === 'XYZ') {\n space = 'world'\n }\n\n if (\n object === undefined ||\n axis === null ||\n this.dragging === false ||\n (pointer !== null && pointer.button !== -1)\n ) {\n this._updateDistanceOverlay()\n return\n }\n\n if (pointer !== null) _raycaster.setFromCamera(pointer, this.camera)\n\n const planeIntersect = intersectObjectWithRay(this._plane, _raycaster, true)\n\n if (!planeIntersect) return\n\n this.pointEnd.copy(planeIntersect.point).sub(this.worldPositionStart)\n\n if (mode === 'translate') {\n // Apply translate\n\n this._offset.copy(this.pointEnd).sub(this.pointStart)\n\n if (space === 'local' && axis !== 'XYZ') {\n this._offset.applyQuaternion(this._worldQuaternionInv)\n }\n\n if (axis.indexOf('X') === -1) this._offset.x = 0\n if (axis.indexOf('Y') === -1) this._offset.y = 0\n if (axis.indexOf('Z') === -1) this._offset.z = 0\n\n if (space === 'local' && axis !== 'XYZ') {\n this._offset\n .applyQuaternion(this._quaternionStart)\n .divide(this._parentScale)\n } else {\n this._offset\n .applyQuaternion(this._parentQuaternionInv)\n .divide(this._parentScale)\n }\n\n object.position.copy(this._offset).add(this._positionStart)\n\n // Apply translation snap\n\n if (this.translationSnap) {\n if (space === 'local') {\n object.position.applyQuaternion(\n _tempQuaternion.copy(this._quaternionStart).invert()\n )\n\n if (axis.search('X') !== -1) {\n object.position.x =\n Math.round(object.position.x / this.translationSnap) *\n this.translationSnap\n }\n\n if (axis.search('Y') !== -1) {\n object.position.y =\n Math.round(object.position.y / this.translationSnap) *\n this.translationSnap\n }\n\n if (axis.search('Z') !== -1) {\n object.position.z =\n Math.round(object.position.z / this.translationSnap) *\n this.translationSnap\n }\n\n object.position.applyQuaternion(this._quaternionStart)\n }\n\n if (space === 'world') {\n if (object.parent) {\n object.position.add(\n _tempVector.setFromMatrixPosition(object.parent.matrixWorld)\n )\n }\n\n if (axis.search('X') !== -1) {\n object.position.x =\n Math.round(object.position.x / this.translationSnap) *\n this.translationSnap\n }\n\n if (axis.search('Y') !== -1) {\n object.position.y =\n Math.round(object.position.y / this.translationSnap) *\n this.translationSnap\n }\n\n if (axis.search('Z') !== -1) {\n object.position.z =\n Math.round(object.position.z / this.translationSnap) *\n this.translationSnap\n }\n\n if (object.parent) {\n object.position.sub(\n _tempVector.setFromMatrixPosition(object.parent.matrixWorld)\n )\n }\n }\n }\n\n object.position.x = Math.max(\n this.minX,\n Math.min(this.maxX, object.position.x)\n )\n object.position.y = Math.max(\n this.minY,\n Math.min(this.maxY, object.position.y)\n )\n object.position.z = Math.max(\n this.minZ,\n Math.min(this.maxZ, object.position.z)\n )\n } else if (mode === 'scale') {\n if (axis.search('XYZ') !== -1) {\n let d = this.pointEnd.length() / this.pointStart.length()\n\n if (this.pointEnd.dot(this.pointStart) < 0) d *= -1\n\n _tempVector2.set(d, d, d)\n } else {\n _tempVector.copy(this.pointStart)\n _tempVector2.copy(this.pointEnd)\n\n _tempVector.applyQuaternion(this._worldQuaternionInv)\n _tempVector2.applyQuaternion(this._worldQuaternionInv)\n\n _tempVector2.divide(_tempVector)\n\n if (axis.search('X') === -1) {\n _tempVector2.x = 1\n }\n\n if (axis.search('Y') === -1) {\n _tempVector2.y = 1\n }\n\n if (axis.search('Z') === -1) {\n _tempVector2.z = 1\n }\n }\n\n // Apply scale\n\n object.scale.copy(this._scaleStart).multiply(_tempVector2)\n\n if (this.scaleSnap) {\n if (axis.search('X') !== -1) {\n object.scale.x =\n Math.round(object.scale.x / this.scaleSnap) * this.scaleSnap ||\n this.scaleSnap\n }\n\n if (axis.search('Y') !== -1) {\n object.scale.y =\n Math.round(object.scale.y / this.scaleSnap) * this.scaleSnap ||\n this.scaleSnap\n }\n\n if (axis.search('Z') !== -1) {\n object.scale.z =\n Math.round(object.scale.z / this.scaleSnap) * this.scaleSnap ||\n this.scaleSnap\n }\n }\n } else if (mode === 'rotate') {\n this._offset.copy(this.pointEnd).sub(this.pointStart)\n\n const ROTATION_SPEED =\n 20 /\n this.worldPosition.distanceTo(\n _tempVector.setFromMatrixPosition(this.camera.matrixWorld)\n )\n\n let _inPlaneRotation = false\n\n if (axis === 'XYZE') {\n this.rotationAxis.copy(this._offset).cross(this.eye).normalize()\n this.rotationAngle =\n this._offset.dot(\n _tempVector.copy(this.rotationAxis).cross(this.eye)\n ) * ROTATION_SPEED\n } else if (axis === 'X' || axis === 'Y' || axis === 'Z') {\n this.rotationAxis.copy(_unit[axis])\n\n _tempVector.copy(_unit[axis])\n\n if (space === 'local') {\n _tempVector.applyQuaternion(this.worldQuaternion)\n }\n\n _tempVector.cross(this.eye)\n\n // When _tempVector is 0 after cross with this.eye the vectors are parallel and should use in-plane rotation logic.\n if (_tempVector.length() === 0) {\n _inPlaneRotation = true\n } else {\n this.rotationAngle =\n this._offset.dot(_tempVector.normalize()) * ROTATION_SPEED\n }\n }\n\n if (axis === 'E' || _inPlaneRotation) {\n this.rotationAxis.copy(this.eye)\n this.rotationAngle = this.pointEnd.angleTo(this.pointStart)\n\n this._startNorm.copy(this.pointStart).normalize()\n this._endNorm.copy(this.pointEnd).normalize()\n\n this.rotationAngle *=\n this._endNorm.cross(this._startNorm).dot(this.eye) < 0 ? 1 : -1\n }\n\n // Apply rotation snap\n\n if (this.rotationSnap)\n this.rotationAngle =\n Math.round(this.rotationAngle / this.rotationSnap) * this.rotationSnap\n\n // Clamp rotation angle to min/max limits\n this.rotationAngle = Math.max(\n this.minRotation,\n Math.min(this.maxRotation, this.rotationAngle)\n )\n\n // Apply rotate\n if (space === 'local' && axis !== 'E' && axis !== 'XYZE') {\n object.quaternion.copy(this._quaternionStart)\n object.quaternion\n .multiply(\n _tempQuaternion.setFromAxisAngle(\n this.rotationAxis,\n this.rotationAngle\n )\n )\n .normalize()\n } else {\n this.rotationAxis.applyQuaternion(this._parentQuaternionInv)\n object.quaternion.copy(\n _tempQuaternion.setFromAxisAngle(\n this.rotationAxis,\n this.rotationAngle\n )\n )\n object.quaternion.multiply(this._quaternionStart).normalize()\n }\n }\n\n this.dispatchEvent(_changeEvent)\n this.dispatchEvent(_objectChangeEvent)\n this._updateDistanceOverlay()\n }\n\n pointerUp(pointer) {\n if (pointer !== null && pointer.button !== 0) return\n\n if (this.dragging && this.axis !== null) {\n _mouseUpEvent.mode = this.mode\n this.dispatchEvent(_mouseUpEvent)\n }\n\n this.dragging = false\n this.axis = null\n this._updateDistanceOverlay()\n }\n\n dispose() {\n this.disconnect()\n\n this._root.dispose()\n }\n\n /**\n * Sets the 3D object that should be transformed and ensures the controls UI is visible.\n *\n * @param {Object3D} object - The 3D object that should be transformed.\n * @return {TransformControls} A reference to this controls.\n */\n attach(object) {\n this.object = object\n this._root.visible = true\n\n return this\n }\n\n /**\n * Removes the current 3D object from the controls and makes the helper UI invisible.\n *\n * @return {TransformControls} A reference to this controls.\n */\n detach() {\n this.object = undefined\n this.axis = null\n\n this._root.visible = false\n\n return this\n }\n\n /**\n * Resets the object's position, rotation and scale to when the current transform began.\n */\n reset() {\n if (!this.enabled) return\n\n if (this.dragging) {\n this.object.position.copy(this._positionStart)\n this.object.quaternion.copy(this._quaternionStart)\n this.object.scale.copy(this._scaleStart)\n\n this.dispatchEvent(_changeEvent)\n this.dispatchEvent(_objectChangeEvent)\n\n this.pointStart.copy(this.pointEnd)\n }\n }\n\n /**\n * Returns the raycaster that is used for user interaction. This object is shared between all\n * instances of `TransformControls`.\n *\n * @returns {Raycaster} The internal raycaster.\n */\n getRaycaster() {\n return _raycaster\n }\n\n /**\n * Returns the transformation mode.\n *\n * @returns {'translate'|'rotate'|'scale'} The transformation mode.\n */\n getMode() {\n return this.mode\n }\n\n /**\n * Sets the given transformation mode.\n *\n * @param {'translate'|'rotate'|'scale'|'all'} mode - The transformation mode to set.\n */\n setMode(mode) {\n // this.mode = mode\n }\n\n /**\n * Sets the translation snap.\n *\n * @param {?number} translationSnap - The translation snap to set.\n */\n setTranslationSnap(translationSnap) {\n this.translationSnap = translationSnap\n }\n\n /**\n * Sets the rotation snap.\n *\n * @param {?number} rotationSnap - The rotation snap to set.\n */\n setRotationSnap(rotationSnap) {\n this.rotationSnap = rotationSnap\n }\n\n /**\n * Sets the minimum rotation angle limit (in radians).\n *\n * @param {number} minRotation - The minimum rotation angle to set (in radians).\n */\n setMinRotation(minRotation) {\n this.minRotation = minRotation\n }\n\n /**\n * Sets the maximum rotation angle limit (in radians).\n *\n * @param {number} maxRotation - The maximum rotation angle to set (in radians).\n */\n setMaxRotation(maxRotation) {\n this.maxRotation = maxRotation\n }\n\n /**\n * Sets the scale snap.\n *\n * @param {?number} scaleSnap - The scale snap to set.\n */\n setScaleSnap(scaleSnap) {\n this.scaleSnap = scaleSnap\n }\n\n /**\n * Sets the size of the helper UI.\n *\n * @param {number} size - The size to set.\n */\n setSize(size) {\n this.size = size\n }\n\n /**\n * Sets the coordinate space in which transformations are applied.\n *\n * @param {'world'|'local'} space - The space to set.\n */\n setSpace(space) {\n this.space = space\n }\n\n _updateDistanceOverlay() {\n if (!this.object || !this.dragging) {\n this._overlay.classList.add('hidden')\n this._distanceLabel.visible = false\n this._rotationAngleLabel.visible = false\n return\n }\n\n if (\n this.mode === 'translate' ||\n (this.mode === 'all' && this.activeMode === 'translate')\n ) {\n // Calculate the distance moved along each axis from the start position\n const xDistance = this.object.position.x - this._positionStart.x\n const yDistance = this.object.position.y - this._positionStart.y\n const zDistance = this.object.position.z - this._positionStart.z\n\n // Calculate total distance\n const totalDistance = Math.sqrt(\n xDistance * xDistance + yDistance * yDistance + zDistance * zDistance\n )\n\n // Position the label at the midpoint between start and current position\n const midPoint = new Vector3(\n (this._positionStart.x + this.object.position.x) / 2,\n (this._positionStart.y + this.object.position.y) / 2,\n (this._positionStart.z + this.object.position.z) / 2\n )\n\n this._distanceLabel.position.copy(midPoint)\n this._distanceLabel.visible = true\n this._rotationAngleLabel.visible = false\n\n // Update label text with total distance\n this._distanceLabel.element.textContent = `${totalDistance.toFixed(3)}`\n\n this._overlay.textContent = `X: ${xDistance.toFixed(2)} Y: ${yDistance.toFixed(2)} Z: ${zDistance.toFixed(2)}`\n } else if (\n this.mode === 'rotate' ||\n (this.mode === 'all' && this.activeMode === 'rotate')\n ) {\n this._distanceLabel.visible = false\n\n // Calculate angle in degrees\n const angleDegrees = (this.rotationAngle * 180) / Math.PI\n\n // Position the label along the rotation arc\n // Use a radius slightly larger than the gizmo radius\n const labelRadius = 0.55\n const labelAngle = this.rotationAngle / 2 // Position at midpoint of arc\n\n // Calculate label position based on rotation axis\n const labelPos = new Vector3()\n\n if (this.axis === 'X' || this.axis === 'Y' || this.axis === 'Z') {\n // For axis-aligned rotations, position the label on the arc\n const axisvec = _unit[this.axis]\n const perpVector = new Vector3()\n\n // Get a perpendicular vector to the rotation axis\n if (Math.abs(axisvec.dot(this.pointStart.clone().normalize())) > 0.99) {\n // If pointStart is parallel to axis, use a different reference\n perpVector.copy(this.eye).cross(axisvec).normalize()\n } else {\n perpVector.copy(this.pointStart).normalize()\n }\n\n // Rotate the perpendicular vector by half the rotation angle\n const rotQuat = new Quaternion().setFromAxisAngle(axisvec, labelAngle)\n perpVector.applyQuaternion(rotQuat)\n\n // Apply local/world orientation\n if (this.space === 'local') {\n perpVector.applyQuaternion(this.worldQuaternion)\n }\n\n perpVector.multiplyScalar(labelRadius)\n labelPos.copy(this.worldPosition).add(perpVector)\n } else {\n // For E or XYZE mode, position near the arc center\n labelPos.copy(this.worldPosition)\n const offsetDir = this.pointStart.clone().normalize()\n\n // Apply local/world orientation\n if (this.space === 'local') {\n offsetDir.applyQuaternion(this.worldQuaternion)\n }\n\n offsetDir.multiplyScalar(labelRadius)\n labelPos.add(offsetDir)\n }\n\n this._rotationAngleLabel.position.copy(labelPos)\n this._rotationAngleLabel.visible = true\n this._rotationAngleLabel.element.textContent = `${Math.abs(angleDegrees).toFixed(1)}°`\n\n this._overlay.textContent = `X: ${(this.object.rotation.x * (180 / Math.PI)).toFixed(2)}° Y: ${(this.object.rotation.y * (180 / Math.PI)).toFixed(2)}° Z: ${(this.object.rotation.z * (180 / Math.PI)).toFixed(2)}°`\n } else if (this.mode === 'scale') {\n this._distanceLabel.visible = false\n this._rotationAngleLabel.visible = false\n this._overlay.textContent = `X: ${this.object.scale.x.toFixed(2)} Y: ${this.object.scale.y.toFixed(2)} Z: ${this.object.scale.z.toFixed(2)}`\n }\n this._overlay.classList.remove('hidden')\n }\n}\n\n// mouse / touch event handlers\n\nfunction getPointer(event) {\n if (this.domElement.ownerDocument.pointerLockElement) {\n return {\n x: 0,\n y: 0,\n button: event.button,\n }\n } else {\n const rect = this.domElement.getBoundingClientRect()\n\n return {\n x: ((event.clientX - rect.left) / rect.width) * 2 - 1,\n y: (-(event.clientY - rect.top) / rect.height) * 2 + 1,\n button: event.button,\n }\n }\n}\n\nfunction onPointerHover(event) {\n if (!this.enabled) return\n\n switch (event.pointerType) {\n case 'mouse':\n case 'pen':\n this.pointerHover(this._getPointer(event))\n break\n }\n}\n\nfunction onPointerDown(event) {\n if (!this.enabled) return\n\n if (!document.pointerLockElement) {\n this.domElement.setPointerCapture(event.pointerId)\n }\n\n this.domElement.addEventListener('pointermove', this._onPointerMove)\n\n this.pointerHover(this._getPointer(event))\n this.pointerDown(this._getPointer(event))\n}\n\nfunction onPointerMove(event) {\n if (!this.enabled) return\n\n this.pointerMove(this._getPointer(event))\n}\n\nfunction onPointerUp(event) {\n if (!this.enabled) return\n\n this.domElement.releasePointerCapture(event.pointerId)\n\n this.domElement.removeEventListener('pointermove', this._onPointerMove)\n\n this.pointerUp(this._getPointer(event))\n}\n\nfunction intersectObjectWithRay(object, raycaster, includeInvisible) {\n const allIntersections = raycaster.intersectObject(object, true)\n\n for (let i = 0; i < allIntersections.length; i++) {\n if (allIntersections[i].object.visible || includeInvisible) {\n return allIntersections[i]\n }\n }\n\n return false\n}\n\n//\n\n// Reusable utility variables\n\nconst _tempEuler = new Euler()\nconst _alignVector = new Vector3(0, 1, 0)\nconst _zeroVector = new Vector3(0, 0, 0)\nconst _lookAtMatrix = new Matrix4()\nconst _tempQuaternion2 = new Quaternion()\nconst _identityQuaternion = new Quaternion()\nconst _dirVector = new Vector3()\nconst _tempMatrix = new Matrix4()\n\nconst _unitX = new Vector3(1, 0, 0)\nconst _unitY = new Vector3(0, 1, 0)\nconst _unitZ = new Vector3(0, 0, 1)\n\nconst _v1 = new Vector3()\nconst _v2 = new Vector3()\nconst _v3 = new Vector3()\n\n// Utility function to calculate the bounding box center of an object\nexport function calculateBoundingBoxCenter(object) {\n const box = new Box3()\n\n // Compute bounding box of the object and all its children\n object.traverse((child) => {\n if (child.isMesh && child.geometry) {\n child.geometry.computeBoundingBox()\n box.expandByObject(child)\n }\n })\n\n // If no geometry found, fall back to object's world position\n if (box.isEmpty()) {\n return object.getWorldPosition(new Vector3())\n }\n\n // Calculate center of bounding box\n const center = new Vector3()\n box.getCenter(center)\n\n return center\n}\n\nclass TransformControlsRoot extends Object3D {\n constructor(controls) {\n super()\n\n this.isTransformControlsRoot = true\n\n this.controls = controls\n this.visible = false\n }\n\n // updateMatrixWorld updates key transformation variables\n updateMatrixWorld(force) {\n const controls = this.controls\n\n if (controls.object !== undefined) {\n controls.object.updateMatrixWorld()\n\n if (controls.object.parent === null) {\n console.error(\n 'TransformControls: The attached 3D object must be a part of the scene graph.'\n )\n } else {\n controls.object.parent.matrixWorld.decompose(\n controls._parentPosition,\n controls._parentQuaternion,\n controls._parentScale\n )\n }\n\n // Calculate the bounding box center instead of using object's world position\n const boundingBoxCenter = calculateBoundingBoxCenter(controls.object)\n controls.worldPosition.copy(boundingBoxCenter)\n\n // Still need to get rotation and scale from the object's matrix\n controls.object.matrixWorld.decompose(\n controls._tempPosition, // Use temporary variable for position\n controls.worldQuaternion,\n controls._worldScale\n )\n\n controls._parentQuaternionInv.copy(controls._parentQuaternion).invert()\n controls._worldQuaternionInv.copy(controls.worldQuaternion).invert()\n }\n\n controls.camera.updateMatrixWorld()\n controls.camera.matrixWorld.decompose(\n controls.cameraPosition,\n controls.cameraQuaternion,\n controls._cameraScale\n )\n\n if (controls.camera.isOrthographicCamera) {\n controls.eye\n .copy(controls.cameraPosition)\n .sub(controls.worldPosition)\n .normalize()\n } else {\n controls.eye\n .copy(controls.cameraPosition)\n .sub(controls.worldPosition)\n .normalize()\n }\n\n super.updateMatrixWorld(force)\n }\n\n dispose() {\n this.traverse(function (child) {\n if (child.geometry) child.geometry.dispose()\n if (child.material) child.material.dispose()\n })\n }\n}\n\nclass TransformControlsGizmo extends Object3D {\n constructor() {\n super()\n\n this.isTransformControlsGizmo = true\n\n this.type = 'TransformControlsGizmo'\n\n // shared materials\n\n const gizmoMaterial = new MeshBasicMaterial({\n depthTest: false,\n depthWrite: false,\n fog: false,\n toneMapped: false,\n transparent: true,\n })\n\n const gizmoLineMaterial = new LineBasicMaterial({\n depthTest: false,\n depthWrite: false,\n fog: false,\n toneMapped: false,\n transparent: true,\n })\n\n // Make unique material for each axis/color\n\n const matInvisible = gizmoMaterial.clone()\n matInvisible.opacity = 0.15\n\n const matHelper = gizmoLineMaterial.clone()\n matHelper.opacity = 0.5\n\n const matRed = gizmoMaterial.clone()\n matRed.color.setHex(0xed4358)\n\n const matGreen = gizmoMaterial.clone()\n matGreen.color.setHex(0x82cc19)\n\n const matBlue = gizmoMaterial.clone()\n matBlue.color.setHex(0x3185eb)\n\n const matRedTransparent = gizmoMaterial.clone()\n matRedTransparent.color.setHex(0xed4358)\n matRedTransparent.opacity = 0.5\n\n const matGreenTransparent = gizmoMaterial.clone()\n matGreenTransparent.color.setHex(0x82cc19)\n matGreenTransparent.opacity = 0.5\n\n const matBlueTransparent = gizmoMaterial.clone()\n matBlueTransparent.color.setHex(0x3185eb)\n matBlueTransparent.opacity = 0.5\n\n const matWhiteTransparent = gizmoMaterial.clone()\n matWhiteTransparent.opacity = 0.25\n\n const matYellowTransparent = gizmoMaterial.clone()\n matYellowTransparent.color.setHex(0xffff00)\n matYellowTransparent.opacity = 0.25\n\n const matYellow = gizmoMaterial.clone()\n matYellow.color.setHex(0xffff00)\n\n const matGray = gizmoMaterial.clone()\n matGray.color.setHex(0x787878)\n\n // reusable geometry\n\n const arrowGeometry = new CylinderGeometry(0, 0.04, 0.1, 12)\n arrowGeometry.translate(0, 0.05, 0)\n\n const scaleHandleGeometry = new BoxGeometry(0.08, 0.08, 0.08)\n scaleHandleGeometry.translate(0, 0.04, 0)\n\n const lineGeometry = new BufferGeometry()\n lineGeometry.setAttribute(\n 'position',\n new Float32BufferAttribute([0, 0, 0, 1, 0, 0], 3)\n )\n\n const lineGeometry2 = new CylinderGeometry(0.02, 0.02, 0.5, 3)\n lineGeometry2.translate(0, 0.25, 0)\n\n function CircleGeometry(radius, arc) {\n const geometry = new TorusGeometry(radius, 0.02, 3, 64, arc * Math.PI * 2)\n geometry.rotateY(Math.PI / 2)\n geometry.rotateX(Math.PI / 2)\n return geometry\n }\n\n // Special geometry for transform helper. If scaled with position vector it spans from [0,0,0] to position\n\n function TranslateHelperGeometry() {\n const geometry = new BufferGeometry()\n\n geometry.setAttribute(\n 'position',\n new Float32BufferAttribute([0, 0, 0, 1, 1, 1], 3)\n )\n\n return geometry\n }\n\n // Gizmo definitions - custom hierarchy definitions for setupGizmo() function\n\n const gizmoTranslate = {\n X: [\n [new Mesh(arrowGeometry, matRed), [0.5, 0, 0], [0, 0, -Math.PI / 2]],\n [new Mesh(lineGeometry2, matRed), [0, 0, 0], [0, 0, -Math.PI / 2]],\n ],\n Y: [\n [new Mesh(arrowGeometry, matGreen), [0, 0.5, 0]],\n [new Mesh(lineGeometry2, matGreen)],\n ],\n Z: [\n [new Mesh(arrowGeometry, matBlue), [0, 0, 0.5], [Math.PI / 2, 0, 0]],\n [new Mesh(lineGeometry2, matBlue), null, [Math.PI / 2, 0, 0]],\n ],\n }\n\n const pickerTranslate = {\n X: [\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [0.3, 0, 0],\n [0, 0, -Math.PI / 2],\n ],\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [-0.3, 0, 0],\n [0, 0, Math.PI / 2],\n ],\n ],\n Y: [\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [0, 0.3, 0],\n ],\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [0, -0.3, 0],\n [0, 0, Math.PI],\n ],\n ],\n Z: [\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [0, 0, 0.3],\n [Math.PI / 2, 0, 0],\n ],\n [\n new Mesh(new CylinderGeometry(0.2, 0, 0.6, 4), matInvisible),\n [0, 0, -0.3],\n [-Math.PI / 2, 0, 0],\n ],\n ],\n }\n\n const helperTranslate = {\n START: [\n [\n new Mesh(new OctahedronGeometry(0.01, 2), matHelper),\n null,\n null,\n null,\n 'helper',\n ],\n ],\n END: [\n [\n new Mesh(new OctahedronGeometry(0.01, 2), matHelper),\n null,\n null,\n null,\n 'helper',\n ],\n ],\n DELTA: [\n [\n new Line(TranslateHelperGeometry(), matHelper),\n null,\n null,\n null,\n 'helper',\n ],\n ],\n }\n\n const gizmoRotate = {\n X: [[new Mesh(CircleGeometry(0.45, 0.25), matRed)]],\n Y: [\n [\n new Mesh(CircleGeometry(0.45, 0.25), matGreen),\n null,\n [0, 0, -Math.PI / 2],\n ],\n ],\n Z: [\n [\n new Mesh(CircleGeometry(0.45, 0.25), matBlue),\n null,\n [0, Math.PI / 2, 0],\n ],\n ],\n }\n\n const helperRotate = {\n AXIS: [],\n START: [\n [new Line(lineGeometry.clone(), matHelper), null, null, null, 'helper'],\n ],\n END: [\n [new Line(lineGeometry.clone(), matHelper), null, null, null, 'helper'],\n ],\n ARC: [\n [new Line(new BufferGeometry(), matHelper), null, null, null, 'helper'],\n ],\n }\n\n const pickerRotate = {\n X: [[new Mesh(CircleGeometry(0.45, 0.25), matRed)]],\n Y: [\n [\n new Mesh(CircleGeometry(0.45, 0.25), matGreen),\n null,\n [0, 0, -Math.PI / 2],\n ],\n ],\n Z: [\n [\n new Mesh(CircleGeometry(0.45, 0.25), matBlue),\n null,\n [0, Math.PI / 2, 0],\n ],\n ],\n }\n\n const gizmoScale = {\n X: [\n [\n new Mesh(scaleHandleGeometry, matRed),\n [0.7, 0, 0],\n [0, 0, -Math.PI / 2],\n ],\n ],\n Y: [[new Mesh(scaleHandleGeometry, matGreen), [0, 0.7, 0]]],\n Z: [\n [\n new Mesh(scaleHandleGeometry, matBlue),\n [0, 0, 0.7],\n [Math.PI / 2, 0, 0],\n ],\n ],\n }\n\n const pickerScale = {\n X: [\n [\n new Mesh(new BoxGeometry(0.2, 0.2, 0.2), matInvisible),\n [0.7, 0, 0],\n [0, 0, -Math.PI / 2],\n ],\n ],\n Y: [\n [new Mesh(new BoxGeometry(0.2, 0.2, 0.2), matInvisible), [0, 0.7, 0]],\n ],\n Z: [\n [\n new Mesh(new BoxGeometry(0.2, 0.2, 0.2), matInvisible),\n [0, 0, 0.7],\n [Math.PI / 2, 0, 0],\n ],\n ],\n }\n\n const helperScale = {\n X: [],\n Y: [],\n Z: [],\n }\n\n // Creates an Object3D with gizmos described in custom hierarchy definition.\n\n function setupGizmo(gizmoMap) {\n const gizmo = new Object3D()\n\n for (const name in gizmoMap) {\n for (let i = gizmoMap[name].length; i--; ) {\n const object = gizmoMap[name][i][0].clone()\n object.userData.type = 'gizmo'\n const position = gizmoMap[name][i][1]\n const rotation = gizmoMap[name][i][2]\n const scale = gizmoMap[name][i][3]\n const tag = gizmoMap[name][i][4]\n\n // name and tag properties are essential for picking and updating logic.\n object.name = name\n object.tag = tag\n\n if (position) {\n object.position.set(position[0], position[1], position[2])\n }\n\n if (rotation) {\n object.rotation.set(rotation[0], rotation[1], rotation[2])\n }\n\n if (scale) {\n object.scale.set(scale[0], scale[1], scale[2])\n }\n\n object.updateMatrix()\n\n const tempGeometry = object.geometry.clone()\n tempGeometry.applyMatrix4(object.matrix)\n object.geometry = tempGeometry\n object.renderOrder = Infinity\n\n object.position.set(0, 0, 0)\n object.rotation.set(0, 0, 0)\n object.scale.set(1, 1, 1)\n\n gizmo.add(object)\n }\n }\n\n return gizmo\n }\n\n // Gizmo creation\n\n this.gizmo = {}\n this.picker = {}\n this.helper = {}\n\n this.add((this.gizmo['translate'] = setupGizmo(gizmoTranslate)))\n this.add((this.gizmo['rotate'] = setupGizmo(gizmoRotate)))\n this.add((this.gizmo['scale'] = setupGizmo(gizmoScale)))\n this.add((this.picker['translate'] = setupGizmo(pickerTranslate)))\n this.add((this.picker['rotate'] = setupGizmo(pickerRotate)))\n this.add((this.picker['scale'] = setupGizmo(pickerScale)))\n this.add((this.helper['translate'] = setupGizmo(helperTranslate)))\n this.add((this.helper['rotate'] = setupGizmo(helperRotate)))\n this.add((this.helper['scale'] = setupGizmo(helperScale)))\n\n // Pickers should be hidden always\n\n this.picker['translate'].visible = false\n this.picker['rotate'].visible = false\n this.picker['scale'].visible = false\n }\n\n // updateMatrixWorld will update transformations and appearance of individual handles\n\n updateMatrixWorld(force) {\n const space = this.mode === 'scale' ? 'local' : this.space // scale always oriented to local rotation\n\n const quaternion =\n space === 'local' ? this.worldQuaternion : _identityQuaternion\n\n // Show gizmos based on mode\n if (this.mode === 'all') {\n // Show all gizmos simultaneously\n this.gizmo['translate'].visible = true\n this.gizmo['rotate'].visible = true\n this.gizmo['scale'].visible = true\n\n this.helper['translate'].visible = true\n this.helper['rotate'].visible = true\n this.helper['scale'].visible = false\n } else {\n // Show only gizmos for current transform mode\n this.gizmo['translate'].visible = this.mode === 'translate'\n this.gizmo['rotate'].visible = this.mode === 'rotate'\n this.gizmo['scale'].visible = this.mode === 'scale'\n\n this.helper['translate'].visible = this.mode === 'translate'\n this.helper['rotate'].visible = this.mode === 'rotate'\n this.helper['scale'].visible = this.mode === 'scale'\n }\n\n let handles = []\n if (this.mode === 'all') {\n // Include all pickers and gizmos\n handles = handles.concat(this.picker['translate'].children)\n handles = handles.concat(this.picker['rotate'].children)\n handles = handles.concat(this.picker['scale'].children)\n handles = handles.concat(this.gizmo['translate'].children)\n handles = handles.concat(this.gizmo['rotate'].children)\n handles = handles.concat(this.gizmo['scale'].children)\n handles = handles.concat(this.helper['translate'].children)\n handles = handles.concat(this.helper['rotate'].children)\n } else {\n handles = handles.concat(this.picker[this.mode].children)\n handles = handles.concat(this.gizmo[this.mode].children)\n handles = handles.concat(this.helper[this.mode].children)\n }\n\n for (let i = 0; i < handles.length; i++) {\n const handle = handles[i]\n\n // hide aligned to camera\n\n handle.visible = true\n handle.rotation.set(0, 0, 0)\n handle.position.copy(this.worldPosition)\n\n let factor\n\n if (this.camera.isOrthographicCamera) {\n factor = (this.camera.top - this.camera.bottom) / this.camera.zoom\n } else {\n factor =\n this.worldPosition.distanceTo(this.cameraPosition) *\n Math.min(\n (1.9 * Math.tan((Math.PI * this.camera.fov) / 360)) /\n this.camera.zoom,\n 7\n )\n }\n\n handle.scale.set(1, 1, 1).multiplyScalar((factor * this.size) / 4)\n\n // TODO: simplify helpers and consider decoupling from gizmo\n\n if (handle.tag === 'helper') {\n handle.visible = false\n\n if (handle.name === 'AXIS') {\n handle.visible = !!this.axis\n\n if (this.axis === 'X') {\n _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0))\n handle.quaternion.copy(quaternion).multiply(_tempQuaternion)\n\n if (\n Math.abs(\n _alignVector\n .copy(_unitX)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > 0.9\n ) {\n handle.visible = false\n }\n }\n\n if (this.axis === 'Y') {\n _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, Math.PI / 2))\n handle.quaternion.copy(quaternion).multiply(_tempQuaternion)\n\n if (\n Math.abs(\n _alignVector\n .copy(_unitY)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > 0.9\n ) {\n handle.visible = false\n }\n }\n\n if (this.axis === 'Z') {\n _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0))\n handle.quaternion.copy(quaternion).multiply(_tempQuaternion)\n\n if (\n Math.abs(\n _alignVector\n .copy(_unitZ)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > 0.9\n ) {\n handle.visible = false\n }\n }\n\n if (this.axis === 'XYZE') {\n _tempQuaternion.setFromEuler(_tempEuler.set(0, Math.PI / 2, 0))\n _alignVector.copy(this.rotationAxis)\n handle.quaternion.setFromRotationMatrix(\n _lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY)\n )\n handle.quaternion.multiply(_tempQuaternion)\n handle.visible = this.dragging\n }\n\n if (this.axis === 'E') {\n handle.visible = false\n }\n } else if (handle.name === 'START') {\n // For rotation mode, show a line from center to start point\n if (this.mode === 'rotate' || this.mode === 'all') {\n handle.position.copy(this.worldPosition)\n // Only show when dragging rotation\n const isRotating =\n this.mode === 'rotate' ||\n (this.mode === 'all' && this.activeMode === 'rotate')\n handle.visible = this.dragging && isRotating\n\n if (handle.visible) {\n // Respect space setting (local vs world)\n const rotSpace = this.space\n\n // Apply quaternion based on space - use START quaternion to keep line fixed\n if (rotSpace === 'local') {\n handle.quaternion.copy(this.worldQuaternionStart)\n } else {\n handle.quaternion.copy(_identityQuaternion)\n }\n\n // Get the rotation axis\n let rotAxis = new Vector3()\n if (this.axis === 'X' || this.axis === 'Y' || this.axis === 'Z') {\n rotAxis.copy(_unit[this.axis])\n } else if (this.axis === 'E' || this.axis === 'XYZE') {\n rotAxis.copy(this.rotationAxis)\n if (rotSpace === 'local') {\n rotAxis.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n }\n\n // Transform pointStart to handle's local space\n let startPoint = this.pointStart.clone()\n if (rotSpace === 'local') {\n startPoint.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n\n // Project onto the plane perpendicular to the rotation axis\n // Remove the component along the rotation axis\n const dotProduct = startPoint.dot(rotAxis)\n startPoint.sub(rotAxis.clone().multiplyScalar(dotProduct))\n startPoint.normalize()\n startPoint.multiplyScalar(0.45)\n\n // Update the line geometry to point from center to pointStart\n const startLineGeometry = new BufferGeometry()\n startLineGeometry.setAttribute(\n 'position',\n new Float32BufferAttribute(\n [0, 0, 0, startPoint.x, startPoint.y, startPoint.z],\n 3\n )\n )\n handle.geometry.dispose()\n handle.geometry = startLineGeometry\n }\n } else {\n handle.position.copy(this.worldPositionStart)\n handle.visible = this.dragging && this.mode === 'translate'\n }\n } else if (handle.name === 'ARC') {\n // Draw arc showing rotation angle\n const isRotating =\n this.mode === 'rotate' ||\n (this.mode === 'all' && this.activeMode === 'rotate')\n handle.visible = this.dragging && isRotating\n\n if (handle.visible && this.rotationAngle !== 0) {\n handle.position.copy(this.worldPosition)\n\n // Respect space setting (local vs world)\n const rotSpace = this.space\n\n // Apply quaternion based on space - use START quaternion to keep arc fixed\n if (rotSpace === 'local') {\n handle.quaternion.copy(this.worldQuaternionStart)\n } else {\n handle.quaternion.copy(_identityQuaternion)\n }\n\n // Create arc geometry\n const arcRadius = 0.45\n const segments = Math.max(\n 8,\n Math.floor(Math.abs(this.rotationAngle) * 50)\n )\n const arcPoints = []\n\n // Get the rotation axis in local space\n let rotAxis = new Vector3()\n if (this.axis === 'X' || this.axis === 'Y' || this.axis === 'Z') {\n rotAxis.copy(_unit[this.axis])\n // In local mode, axis is already in local space, no transformation needed\n // In world mode, we need to transform from world to handle space\n if (rotSpace !== 'local') {\n // Axis stays as is in world mode\n }\n } else if (this.axis === 'E' || this.axis === 'XYZE') {\n rotAxis.copy(this.rotationAxis)\n // Transform rotation axis to handle's local space\n if (rotSpace === 'local') {\n rotAxis.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n }\n\n // Transform pointStart to handle's local space\n let startDir = this.pointStart.clone()\n if (rotSpace === 'local') {\n // Transform from world space to local space\n startDir.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n\n // Project onto the plane perpendicular to the rotation axis\n const dotProduct = startDir.dot(rotAxis)\n startDir.sub(rotAxis.clone().multiplyScalar(dotProduct))\n startDir.normalize()\n\n // Create the arc by rotating the start point around the axis\n for (let j = 0; j <= segments; j++) {\n const angle = (this.rotationAngle * j) / segments\n const point = startDir.clone()\n const arcQuat = new Quaternion().setFromAxisAngle(rotAxis, angle)\n point.applyQuaternion(arcQuat)\n point.multiplyScalar(arcRadius)\n arcPoints.push(point.x, point.y, point.z)\n }\n\n const arcGeometry = new BufferGeometry()\n arcGeometry.setAttribute(\n 'position',\n new Float32BufferAttribute(arcPoints, 3)\n )\n handle.geometry.dispose()\n handle.geometry = arcGeometry\n }\n } else if (handle.name === 'END') {\n // For rotation mode, show a line from center to current rotation point\n if (this.mode === 'rotate' || this.mode === 'all') {\n handle.position.copy(this.worldPosition)\n // Only show when dragging rotation\n const isRotating =\n this.mode === 'rotate' ||\n (this.mode === 'all' && this.activeMode === 'rotate')\n handle.visible = this.dragging && isRotating\n\n if (handle.visible) {\n // Respect space setting (local vs world)\n const rotSpace = this.space\n\n // Use START quaternion to match the arc's coordinate space\n if (rotSpace === 'local') {\n handle.quaternion.copy(this.worldQuaternionStart)\n } else {\n handle.quaternion.copy(_identityQuaternion)\n }\n\n // Calculate end point by rotating start point (same as arc)\n const endLineGeometry = new BufferGeometry()\n\n // Get the rotation axis in local space\n let rotAxis = new Vector3()\n if (this.axis === 'X' || this.axis === 'Y' || this.axis === 'Z') {\n rotAxis.copy(_unit[this.axis])\n } else if (this.axis === 'E' || this.axis === 'XYZE') {\n rotAxis.copy(this.rotationAxis)\n if (rotSpace === 'local') {\n rotAxis.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n }\n\n // Transform pointStart to handle's local space\n let startDir = this.pointStart.clone()\n if (rotSpace === 'local') {\n startDir.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n }\n\n // Project onto the plane perpendicular to the rotation axis\n const dotProduct = startDir.dot(rotAxis)\n startDir.sub(rotAxis.clone().multiplyScalar(dotProduct))\n startDir.normalize()\n\n // Rotate by the full rotation angle to get end point\n const endPoint = startDir.clone()\n const arcQuat = new Quaternion().setFromAxisAngle(\n rotAxis,\n this.rotationAngle\n )\n endPoint.applyQuaternion(arcQuat)\n endPoint.multiplyScalar(0.45)\n\n endLineGeometry.setAttribute(\n 'position',\n new Float32BufferAttribute(\n [0, 0, 0, endPoint.x, endPoint.y, endPoint.z],\n 3\n )\n )\n handle.geometry.dispose()\n handle.geometry = endLineGeometry\n }\n } else {\n handle.position.copy(this.worldPosition)\n handle.visible = false\n }\n } else if (handle.name === 'DELTA') {\n handle.position.copy(this.worldPositionStart)\n handle.quaternion.copy(this.worldQuaternionStart)\n _tempVector\n .set(1e-10, 1e-10, 1e-10)\n .add(this.worldPositionStart)\n .sub(this.worldPosition)\n .multiplyScalar(-1)\n _tempVector.applyQuaternion(\n this.worldQuaternionStart.clone().invert()\n )\n handle.scale.copy(_tempVector)\n handle.visible = this.dragging\n } else {\n handle.quaternion.copy(quaternion)\n\n if (this.dragging) {\n handle.position.copy(this.worldPositionStart)\n } else {\n handle.position.copy(this.worldPosition)\n }\n\n if (this.axis) {\n handle.visible = this.axis.search(handle.name) !== -1\n }\n }\n\n // If updating helper, skip rest of the loop\n continue\n }\n\n // Align handles to current local or world rotation\n\n handle.quaternion.copy(quaternion)\n\n if (this.mode === 'translate' || this.mode === 'scale') {\n // Hide translate and scale axis facing the camera\n\n const AXIS_HIDE_THRESHOLD = 0.99\n const PLANE_HIDE_THRESHOLD = 0.2\n\n if (handle.name === 'X') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitX)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > AXIS_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n\n if (handle.name === 'Y') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitY)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > AXIS_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n\n if (handle.name === 'Z') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitZ)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) > AXIS_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n\n if (handle.name === 'XY') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitZ)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) < PLANE_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n\n if (handle.name === 'YZ') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitX)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) < PLANE_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n\n if (handle.name === 'XZ') {\n if (\n Math.abs(\n _alignVector\n .copy(_unitY)\n .applyQuaternion(quaternion)\n .dot(this.eye)\n ) < PLANE_HIDE_THRESHOLD\n ) {\n handle.scale.set(1e-10, 1e-10, 1e-10)\n handle.visible = false\n }\n }\n } else if (this.mode === 'rotate') {\n // Align handles to current local or world rotation\n\n _tempQuaternion2.copy(quaternion)\n _alignVector\n .copy(this.eye)\n .applyQuaternion(_tempQuaternion.copy(quaternion).invert())\n\n if (handle.name.search('E') !== -1) {\n handle.quaternion.setFromRotationMatrix(\n _lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY)\n )\n }\n\n if (handle.name === 'X') {\n _tempQuaternion.setFromAxisAngle(\n _unitX,\n Math.atan2(-_alignVector.y, _alignVector.z)\n )\n _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion)\n handle.quaternion.copy(_tempQuaternion)\n }\n\n if (handle.name === 'Y') {\n _tempQuaternion.setFromAxisAngle(\n _unitY,\n Math.atan2(_alignVector.x, _alignVector.z)\n )\n _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion)\n handle.quaternion.copy(_tempQuaternion)\n }\n\n if (handle.name === 'Z') {\n _tempQuaternion.setFromAxisAngle(\n _unitZ,\n Math.atan2(_alignVector.y, _alignVector.x)\n )\n _tempQuaternion.multiplyQuaternions(_tempQuaternion2, _tempQuaternion)\n handle.quaternion.copy(_tempQuaternion)\n }\n }\n\n // Hide disabled axes\n handle.visible =\n handle.visible && (handle.name.indexOf('X') === -1 || this.showX)\n handle.visible =\n handle.visible && (handle.name.indexOf('Y') === -1 || this.showY)\n handle.visible =\n handle.visible && (handle.name.indexOf('Z') === -1 || this.showZ)\n handle.visible =\n handle.visible &&\n (handle.name.indexOf('E') === -1 ||\n (this.showX && this.showY && this.showZ))\n\n // highlight selected axis\n\n handle.material._color =\n handle.material._color || handle.material.color.clone()\n handle.material._opacity =\n handle.material._opacity || handle.material.opacity\n\n handle.material.color.copy(handle.material._color)\n handle.material.opacity = handle.material._opacity\n\n // Apply transparency to all materials when dragging\n if (this.dragging) {\n handle.material.opacity = 0.2\n }\n\n if (this.enabled && this.axis) {\n if (handle.name === this.axis) {\n handle.material.color.setHex(0xffff00)\n if (!this.dragging) {\n handle.material.opacity = 1.0\n }\n } else if (\n this.axis.split('').some(function (a) {\n return handle.name === a\n })\n ) {\n handle.material.color.setHex(0xffff00)\n if (!this.dragging) {\n handle.material.opacity = 1.0\n }\n }\n }\n }\n\n super.updateMatrixWorld(force)\n }\n}\n\n//\n\nclass TransformControlsPlane extends Mesh {\n constructor() {\n super(\n new PlaneGeometry(100000, 100000, 2, 2),\n new MeshBasicMaterial({\n visible: false,\n wireframe: true,\n side: DoubleSide,\n transparent: true,\n opacity: 0.1,\n toneMapped: false,\n })\n )\n\n this.isTransformControlsPlane = true\n\n this.type = 'TransformControlsPlane'\n }\n\n updateMatrixWorld(force) {\n let space = this.space\n\n this.position.copy(this.worldPosition)\n\n if (this.mode === 'scale') space = 'local' // scale always oriented to local rotation\n\n _v1\n .copy(_unitX)\n .applyQuaternion(\n space === 'local' ? this.worldQuaternion : _identityQuaternion\n )\n _v2\n .copy(_unitY)\n .applyQuaternion(\n space === 'local' ? this.worldQuaternion : _identityQuaternion\n )\n _v3\n .copy(_unitZ)\n .applyQuaternion(\n space === 'local' ? this.worldQuaternion : _identityQuaternion\n )\n\n // Align the plane for current transform mode, axis and space.\n\n _alignVector.copy(_v2)\n\n switch (this.mode) {\n case 'translate':\n case 'scale':\n switch (this.axis) {\n case 'X':\n _alignVector.copy(this.eye).cross(_v1)\n _dirVector.copy(_v1).cross(_alignVector)\n break\n case 'Y':\n _alignVector.copy(this.eye).cross(_v2)\n _dirVector.copy(_v2).cross(_alignVector)\n break\n case 'Z':\n _alignVector.copy(this.eye).cross(_v3)\n _dirVector.copy(_v3).cross(_alignVector)\n break\n case 'XY':\n _dirVector.copy(_v3)\n break\n case 'YZ':\n _dirVector.copy(_v1)\n break\n case 'XZ':\n _alignVector.copy(_v3)\n _dirVector.copy(_v2)\n break\n case 'XYZ':\n case 'E':\n _dirVector.set(0, 0, 0)\n break\n }\n\n break\n case 'rotate':\n default:\n // special case for rotate\n _dirVector.set(0, 0, 0)\n }\n\n if (_dirVector.length() === 0) {\n // If in rotate mode, make the plane parallel to camera\n this.quaternion.copy(this.cameraQuaternion)\n } else {\n _tempMatrix.lookAt(_tempVector.set(0, 0, 0), _dirVector, _alignVector)\n\n this.quaternion.setFromRotationMatrix(_tempMatrix)\n }\n\n super.updateMatrixWorld(force)\n }\n}\n\nexport { TransformControls, TransformControlsGizmo, TransformControlsPlane }\n","import * as THREE from 'three'\n\n// Hard-coded axis colors matching TransformControls\nconst AXIS_COLORS = {\n x: '#ed4358',\n y: '#82cc19',\n z: '#3185eb',\n} as const\n\nexport interface ViewHelperCameraController {\n camera: THREE.Camera\n getPosition(target: THREE.Vector3): THREE.Vector3\n getTarget(target: THREE.Vector3): THREE.Vector3\n setLookAt(\n positionX: number,\n positionY: number,\n positionZ: number,\n targetX: number,\n targetY: number,\n targetZ: number,\n enableTransition?: boolean\n ): Promise<void> | void\n stop?(): void\n}\n\nexport interface ViewHelperOptions {\n container?: HTMLElement\n size?: number\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n offset?: { x: number; y: number }\n center?: THREE.Vector3\n labels?: {\n x?: string\n y?: string\n z?: string\n }\n controls?: ViewHelperCameraController\n}\n\n// Define event types for the view helper\ninterface ViewHelperEventMap {\n animationStart: {}\n animationEnd: {}\n}\n\nexport interface ViewHelperEvent {\n type: 'animationStart' | 'animationEnd'\n}\n\nexport class ViewHelper extends THREE.EventDispatcher<ViewHelperEventMap> {\n private camera: THREE.Camera\n private domElement: HTMLElement\n private options: Required<Omit<ViewHelperOptions, 'controls'>>\n private scene: THREE.Scene\n private orthoCamera: THREE.OrthographicCamera\n private renderer?: THREE.WebGLRenderer\n private viewport: THREE.Vector4 = new THREE.Vector4()\n private controls?: ViewHelperCameraController\n private pointerDownHandler!: (event: PointerEvent) => void\n\n // Animation properties\n public animating: boolean = false\n public center: THREE.Vector3\n private targetPosition: THREE.Vector3 = new THREE.Vector3()\n private targetQuaternion: THREE.Quaternion = new THREE.Quaternion()\n private q1: THREE.Quaternion = new THREE.Quaternion()\n private q2: THREE.Quaternion = new THREE.Quaternion()\n private dummy: THREE.Object3D = new THREE.Object3D()\n private radius: number = 0\n private turnRate: number = 2 * Math.PI // turn rate in angles per second\n private tempVecA: THREE.Vector3 = new THREE.Vector3()\n\n // Interactive elements\n private interactiveObjects: THREE.Object3D[] = []\n private raycaster: THREE.Raycaster = new THREE.Raycaster()\n private mouse: THREE.Vector2 = new THREE.Vector2()\n\n // Helper objects\n private axes!: {\n x: THREE.Mesh\n y: THREE.Mesh\n z: THREE.Mesh\n }\n private sprites!: {\n posX: THREE.Sprite\n posY: THREE.Sprite\n posZ: THREE.Sprite\n negX: THREE.Sprite\n negY: THREE.Sprite\n negZ: THREE.Sprite\n }\n\n constructor(\n camera: THREE.Camera,\n domElement?: HTMLElement,\n options: ViewHelperOptions = {}\n ) {\n super()\n this.controls = options.controls\n this.camera = this.controls?.camera ?? camera\n this.domElement = domElement || document.body\n\n const defaultCenter =\n options.center ??\n (this.controls\n ? this.controls.getTarget(new THREE.Vector3())\n : new THREE.Vector3())\n\n // Set default options\n this.options = {\n container: options.container || document.body,\n size: options.size || 128,\n position: options.position || 'bottom-right',\n offset: options.offset || { x: 20, y: 20 },\n center: defaultCenter.clone(),\n labels: {\n x: options.labels?.x || '',\n y: options.labels?.y || '',\n z: options.labels?.z || '',\n ...options.labels,\n },\n }\n\n this.center = this.options.center.clone()\n\n this.scene = new THREE.Scene()\n this.scene.background = null // Make background transparent\n this.orthoCamera = new THREE.OrthographicCamera(-2, 2, 2, -2, 0, 4)\n this.orthoCamera.position.set(0, 0, 2)\n\n this.createAxes()\n this.createSprites()\n this.setupEventListeners()\n }\n\n private syncActiveCamera(): THREE.Camera {\n if (this.controls) {\n this.camera = this.controls.camera\n }\n return this.camera\n }\n\n private getCameraPosition(target: THREE.Vector3): THREE.Vector3 {\n if (this.controls) {\n return this.controls.getPosition(target)\n }\n return target.copy(this.camera.position)\n }\n\n private createAxes(): void {\n const geometry = new THREE.CylinderGeometry(0.04, 0.04, 0.8, 5)\n .rotateZ(-Math.PI / 2)\n .translate(0.4, 0, 0)\n\n const xAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.x,\n toneMapped: false,\n })\n const yAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.y,\n toneMapped: false,\n })\n const zAxisMaterial = new THREE.MeshBasicMaterial({\n color: AXIS_COLORS.z,\n toneMapped: false,\n })\n\n this.axes = {\n x: new THREE.Mesh(geometry.clone(), xAxisMaterial),\n y: new THREE.Mesh(geometry.clone(), yAxisMaterial),\n z: new THREE.Mesh(geometry.clone(), zAxisMaterial),\n }\n\n this.axes.y.rotation.z = Math.PI / 2\n this.axes.z.rotation.y = -Math.PI / 2\n\n this.scene.add(this.axes.x)\n this.scene.add(this.axes.y)\n this.scene.add(this.axes.z)\n }\n\n private createSprites(): void {\n const posXSprite = this.createSprite(AXIS_COLORS.x, this.options.labels.x)\n const posYSprite = this.createSprite(AXIS_COLORS.y, this.options.labels.y)\n const posZSprite = this.createSprite(AXIS_COLORS.z, this.options.labels.z)\n // Use faded versions of the axis colors for negative axes\n const negXSprite = this.createSprite(AXIS_COLORS.x)\n const negYSprite = this.createSprite(AXIS_COLORS.y)\n const negZSprite = this.createSprite(AXIS_COLORS.z)\n\n this.sprites = {\n posX: posXSprite,\n posY: posYSprite,\n posZ: posZSprite,\n negX: negXSprite,\n negY: negYSprite,\n negZ: negZSprite,\n }\n\n // Position sprites\n this.sprites.posX.position.set(1, 0, 0)\n this.sprites.posY.position.set(0, 1, 0)\n this.sprites.posZ.position.set(0, 0, 1)\n this.sprites.negX.position.set(-1, 0, 0)\n this.sprites.negY.position.set(0, -1, 0)\n this.sprites.negZ.position.set(0, 0, -1)\n\n // Set opacity for negative axes\n this.sprites.negX.material.opacity = 0.2\n this.sprites.negY.material.opacity = 0.2\n this.sprites.negZ.material.opacity = 0.2\n\n // Set user data for interaction\n this.sprites.posX.userData.type = 'posX'\n this.sprites.posY.userData.type = 'posY'\n this.sprites.posZ.userData.type = 'posZ'\n this.sprites.negX.userData.type = 'negX'\n this.sprites.negY.userData.type = 'negY'\n this.sprites.negZ.userData.type = 'negZ'\n\n // Add to scene and interactive objects\n Object.values(this.sprites).forEach((sprite) => {\n this.scene.add(sprite)\n this.interactiveObjects.push(sprite)\n })\n }\n\n private createSprite(color: string, text?: string): THREE.Sprite {\n // Use higher resolution for crisp rendering\n const pixelRatio = window.devicePixelRatio || 1\n const size = 128 * pixelRatio\n const radius = 28 * pixelRatio\n\n const canvas = document.createElement('canvas')\n canvas.width = size\n canvas.height = size\n\n const context = canvas.getContext('2d')!\n\n // Enable high-quality rendering\n context.imageSmoothingEnabled = true\n context.imageSmoothingQuality = 'high'\n\n // Scale for device pixel ratio\n context.scale(pixelRatio, pixelRatio)\n\n const center = size / (2 * pixelRatio)\n const actualRadius = radius / pixelRatio\n\n // Draw circle background\n context.beginPath()\n context.arc(center, center, actualRadius, 0, 2 * Math.PI)\n context.closePath()\n context.fillStyle = color\n context.fill()\n\n if (text) {\n context.font = 'bold 48px Arial, sans-serif'\n context.textAlign = 'center'\n context.textBaseline = 'middle'\n context.fillStyle = '#ffffff'\n\n // Add text stroke for better visibility\n context.strokeStyle = '#000000'\n context.lineWidth = 2\n context.strokeText(text, center, center)\n context.fillText(text, center, center)\n }\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n texture.generateMipmaps = false\n texture.minFilter = THREE.LinearFilter\n texture.magFilter = THREE.LinearFilter\n\n return new THREE.Sprite(\n new THREE.SpriteMaterial({\n map: texture,\n toneMapped: false,\n alphaTest: 0.1,\n })\n )\n }\n\n private setupEventListeners(): void {\n this.pointerDownHandler = (event: PointerEvent) => {\n this.handleClick(event)\n }\n this.domElement.addEventListener('pointerdown', this.pointerDownHandler)\n }\n\n public render(renderer: THREE.WebGLRenderer): void {\n this.renderer = renderer\n\n const activeCamera = this.syncActiveCamera()\n\n // Update helper orientation to match camera\n this.scene.quaternion.copy(activeCamera.quaternion).invert()\n this.scene.updateMatrixWorld()\n\n const size = this.options.size\n const canvasWidth = renderer.domElement.width / renderer.getPixelRatio()\n const canvasHeight = renderer.domElement.height / renderer.getPixelRatio()\n\n let x: number, y: number\n\n switch (this.options.position) {\n case 'top-left':\n x = this.options.offset.x\n y = canvasHeight - size - this.options.offset.y\n break\n case 'top-right':\n x = canvasWidth - size - this.options.offset.x\n y = canvasHeight - size - this.options.offset.y\n break\n case 'bottom-left':\n x = this.options.offset.x\n y = this.options.offset.y\n break\n case 'bottom-right':\n default:\n x = canvasWidth - size - this.options.offset.x\n y = this.options.offset.y\n break\n }\n\n // Store current viewport and autoClear setting\n renderer.getViewport(this.viewport)\n const autoClear = renderer.autoClear\n\n // Set viewport for helper and disable autoClear\n renderer.setViewport(x, y, size, size)\n renderer.autoClear = false\n\n // Clear only depth buffer in the helper area\n renderer.setScissorTest(true)\n renderer.setScissor(x, y, size, size)\n renderer.clear(false, false, true) // clear depth only\n\n // Render helper\n renderer.render(this.scene, this.orthoCamera)\n\n // Restore settings\n renderer.setScissorTest(false)\n renderer.autoClear = autoClear\n renderer.setViewport(\n this.viewport.x,\n this.viewport.y,\n this.viewport.z,\n this.viewport.w\n )\n }\n\n public handleClick(event: PointerEvent): boolean {\n if (this.animating || !this.renderer) return false\n\n this.syncActiveCamera()\n\n const rect = this.domElement.getBoundingClientRect()\n const size = this.options.size // Use logical size for click detection\n\n // Calculate helper viewport bounds\n let offsetX: number, offsetY: number\n\n switch (this.options.position) {\n case 'top-left':\n offsetX = rect.left + this.options.offset.x\n offsetY = rect.top + this.options.offset.y\n break\n case 'top-right':\n offsetX = rect.left + rect.width - size - this.options.offset.x\n offsetY = rect.top + this.options.offset.y\n break\n case 'bottom-left':\n offsetX = rect.left + this.options.offset.x\n offsetY = rect.top + rect.height - size - this.options.offset.y\n break\n case 'bottom-right':\n default:\n offsetX = rect.left + rect.width - size - this.options.offset.x\n offsetY = rect.top + rect.height - size - this.options.offset.y\n break\n }\n\n // Convert click coordinates to helper-relative coordinates\n this.mouse.x = ((event.clientX - offsetX) / size) * 2 - 1\n this.mouse.y = -((event.clientY - offsetY) / size) * 2 + 1\n\n // Check if click is within helper bounds\n if (\n this.mouse.x < -1 ||\n this.mouse.x > 1 ||\n this.mouse.y < -1 ||\n this.mouse.y > 1\n ) {\n return false\n }\n\n this.raycaster.setFromCamera(this.mouse, this.orthoCamera)\n const intersects = this.raycaster.intersectObjects(this.interactiveObjects)\n\n if (intersects.length > 0) {\n const intersection = intersects[0]\n const object = intersection.object\n this.prepareAnimationData(object, this.center)\n if (this.controls) {\n this.startControlsAnimation(this.center)\n } else {\n this.animating = true\n this.dispatchEvent({ type: 'animationStart' })\n }\n return true\n }\n\n return false\n }\n\n private prepareAnimationData(\n object: THREE.Object3D,\n focusPoint: THREE.Vector3\n ): void {\n switch (object.userData.type) {\n case 'posX':\n this.targetPosition.set(1, 0, 0)\n this.targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI * 0.5, 0))\n break\n case 'posY':\n this.targetPosition.set(0, 1, 0)\n this.targetQuaternion.setFromEuler(\n new THREE.Euler(-Math.PI * 0.5, 0, 0)\n )\n break\n case 'posZ':\n this.targetPosition.set(0, 0, 1)\n this.targetQuaternion.setFromEuler(new THREE.Euler())\n break\n case 'negX':\n this.targetPosition.set(-1, 0, 0)\n this.targetQuaternion.setFromEuler(\n new THREE.Euler(0, -Math.PI * 0.5, 0)\n )\n break\n case 'negY':\n this.targetPosition.set(0, -1, 0)\n this.targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.5, 0, 0))\n break\n case 'negZ':\n this.targetPosition.set(0, 0, -1)\n this.targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI, 0))\n break\n default:\n console.error('ViewHelper: Invalid axis.')\n return\n }\n\n const cameraPosition = this.getCameraPosition(this.tempVecA)\n this.radius = cameraPosition.distanceTo(focusPoint)\n this.targetPosition.multiplyScalar(this.radius).add(focusPoint)\n\n this.dummy.position.copy(focusPoint)\n this.dummy.lookAt(cameraPosition)\n this.q1.copy(this.dummy.quaternion)\n\n this.dummy.lookAt(this.targetPosition)\n this.q2.copy(this.dummy.quaternion)\n }\n\n private startControlsAnimation(focusPoint: THREE.Vector3): void {\n const controls = this.controls\n if (!controls) {\n return\n }\n\n controls.stop?.()\n this.animating = true\n this.dispatchEvent({ type: 'animationStart' })\n\n const applyLookAt = () =>\n controls.setLookAt(\n this.targetPosition.x,\n this.targetPosition.y,\n this.targetPosition.z,\n focusPoint.x,\n focusPoint.y,\n focusPoint.z,\n true\n )\n\n try {\n void Promise.resolve(applyLookAt())\n .catch((error) => {\n console.warn('ViewHelper: Unable to set camera look-at.', error)\n })\n .finally(() => {\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n })\n } catch (error) {\n console.warn('ViewHelper: Unable to set camera look-at.', error)\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n }\n }\n\n public update(delta: number): void {\n this.syncActiveCamera()\n\n if (this.controls) {\n return\n }\n\n if (!this.animating) return\n\n const step = delta * this.turnRate\n\n // Animate position by doing a slerp and then scaling the position on the unit sphere\n this.q1.rotateTowards(this.q2, step)\n this.camera.position\n .set(0, 0, 1)\n .applyQuaternion(this.q1)\n .multiplyScalar(this.radius)\n .add(this.center)\n\n // Animate orientation\n this.camera.quaternion.rotateTowards(this.targetQuaternion, step)\n\n if (this.q1.angleTo(this.q2) === 0) {\n this.animating = false\n this.dispatchEvent({ type: 'animationEnd' })\n }\n }\n\n public setLabels(labelX?: string, labelY?: string, labelZ?: string): void {\n if (labelX !== undefined) this.options.labels.x = labelX\n if (labelY !== undefined) this.options.labels.y = labelY\n if (labelZ !== undefined) this.options.labels.z = labelZ\n\n this.updateLabels()\n }\n\n private updateLabels(): void {\n // Dispose old materials\n this.sprites.posX.material.map?.dispose()\n this.sprites.posY.material.map?.dispose()\n this.sprites.posZ.material.map?.dispose()\n this.sprites.posX.material.dispose()\n this.sprites.posY.material.dispose()\n this.sprites.posZ.material.dispose()\n\n // Create new sprites with updated labels\n const newPosX = this.createSprite(AXIS_COLORS.x, this.options.labels.x)\n const newPosY = this.createSprite(AXIS_COLORS.y, this.options.labels.y)\n const newPosZ = this.createSprite(AXIS_COLORS.z, this.options.labels.z)\n\n // Update sprites\n this.sprites.posX.material = newPosX.material\n this.sprites.posY.material = newPosY.material\n this.sprites.posZ.material = newPosZ.material\n }\n\n public dispose(): void {\n // Dispose geometries\n this.axes.x.geometry.dispose()\n this.axes.y.geometry.dispose()\n this.axes.z.geometry.dispose()\n\n // Dispose materials\n ;(this.axes.x.material as THREE.Material).dispose()\n ;(this.axes.y.material as THREE.Material).dispose()\n ;(this.axes.z.material as THREE.Material).dispose()\n\n // Dispose sprite materials and textures\n Object.values(this.sprites).forEach((sprite) => {\n sprite.material.map?.dispose()\n sprite.material.dispose()\n })\n\n // Remove event listeners\n if (this.pointerDownHandler) {\n this.domElement.removeEventListener(\n 'pointerdown',\n this.pointerDownHandler\n )\n }\n }\n}\n"],"mappings":"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","names":["THREE","CameraControls","THREE","THREE","THREE","SnapMode","THREE","solarAltitude","THREE","clamp","import_CSS2DRenderer","THREE"]}
|