@xingm/vmap-cesium-toolbar 0.0.1-beta.1 → 0.0.1-beta.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/libs/CesiumMapHelper.ts","../src/libs/CesiumMapToolbar.ts","../src/libs/CesiumMapLoader.ts","../src/index.ts"],"sourcesContent":["import * as Cesium from \"cesium\";\nimport type { Primitive } from \"cesium\";\nimport type { FrustumOptions } from \"./CesiumMapModel\";\n/**\n * Cesium 绘图辅助工具类\n * 支持绘制点、线、多边形、矩形,并提供编辑和删除功能\n * 适用于 Cesium 1.132.0\n */\nclass DrawHelper {\n private viewer: Cesium.Viewer;\n private scene: Cesium.Scene;\n private entities: Cesium.EntityCollection;\n private frustumPrimitives: Primitive[] = [];\n\n // 绘图状态和数据\n private drawMode: \"line\" | \"polygon\" | \"rectangle\" | null = null;\n private isDrawing: boolean = false;\n private tempPositions: Cesium.Cartesian3[] = [];\n private tempEntities: Cesium.Entity[] = []; // 临时实体,用于绘制过程中\n private finishedEntities: Cesium.Entity[] = []; // 已完成的实体\n\n // 事件处理器\n private screenSpaceEventHandler: Cesium.ScreenSpaceEventHandler | null = null;\n // 回调函数\n private onDrawStartCallback: (() => void) | null = null;\n private onDrawEndCallback: ((entity: Cesium.Entity | null) => void) | null =\n null;\n private onEntityRemovedCallback: ((entity: Cesium.Entity) => void) | null =\n null;\n\n /**\n * 构造函数\n * @param viewer Cesium Viewer 实例\n */\n constructor(viewer: Cesium.Viewer) {\n if (!viewer || !(viewer instanceof Cesium.Viewer)) {\n throw new Error(\"Invalid Cesium Viewer instance provided.\");\n }\n this.viewer = viewer;\n this.scene = viewer.scene;\n this.entities = viewer.entities;\n\n // 确保启用地形深度测试以获得正确的高度\n this.scene.globe.depthTestAgainstTerrain = true;\n }\n\n clearFrustum(): void {\n // 清理视锥体图元\n this.frustumPrimitives.forEach((primitive) => {\n if (primitive && !primitive.isDestroyed()) {\n this.viewer.scene.primitives.remove(primitive);\n }\n });\n this.frustumPrimitives = [];\n \n // 清理视锥体专用的事件处理器\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n // 视锥体功能\n drawFrustum(options: FrustumOptions = {}): void {\n try {\n this.clearFrustum();\n \n // 参数验证\n const fov = Math.max(1, Math.min(179, options.fov || 60)); // 限制FOV范围\n const aspectRatio = Math.max(0.1, options.aspectRatio || 1.0);\n const near = Math.max(0.1, options.near || 1.0);\n const far = Math.max(near + 1, options.far || 1000.0);\n \n const position = options.position || this.viewer.camera.positionWC;\n const orientation =\n options.orientation ||\n Cesium.Quaternion.fromRotationMatrix(\n Cesium.Matrix4.getRotation(\n this.viewer.camera.transform,\n new Cesium.Matrix3()\n )\n );\n\n const frustum = new Cesium.PerspectiveFrustum({\n fov: Cesium.Math.toRadians(fov),\n aspectRatio: aspectRatio,\n near: near,\n far: far,\n });\n\n // 创建视锥体填充\n const fillGeometry = new Cesium.FrustumGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n vertexFormat: Cesium.VertexFormat.POSITION_ONLY,\n });\n\n const fillInstance = new Cesium.GeometryInstance({\n geometry: fillGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.fillColor || new Cesium.Color(1.0, 0.0, 0.0, 0.3)\n ),\n },\n });\n\n const fillPrimitive = new Cesium.Primitive({\n geometryInstances: fillInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n // 创建视锥体轮廓\n const outlineGeometry = new Cesium.FrustumOutlineGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n });\n\n const outlineInstance = new Cesium.GeometryInstance({\n geometry: outlineGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.outlineColor || new Cesium.Color(1.0, 1.0, 1.0, 1.0)\n ),\n },\n });\n\n const outlinePrimitive = new Cesium.Primitive({\n geometryInstances: outlineInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n this.viewer.scene.primitives.add(fillPrimitive);\n this.viewer.scene.primitives.add(outlinePrimitive);\n this.frustumPrimitives.push(fillPrimitive, outlinePrimitive);\n\n // 右键点击事件\n if (options.onRightClick && this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.setInputAction((movement: any) => {\n if (movement.position && options.onRightClick) {\n options.onRightClick(position);\n }\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n }\n } catch (error) {\n console.error('绘制视锥体时发生错误:', error);\n // 确保在出错时也清理资源\n this.clearFrustum();\n }\n }\n\n /**\n * 开始绘制线条\n */\n startDrawingLine(): void {\n this.startDrawing(\"line\");\n }\n\n /**\n * 开始绘制多边形(仅边线)\n */\n startDrawingPolygon(): void {\n this.startDrawing(\"polygon\");\n }\n\n /**\n * 开始绘制矩形\n */\n startDrawingRectangle(): void {\n this.startDrawing(\"rectangle\");\n }\n\n /**\n * 内部统一的开始绘制方法\n * @param mode 绘制模式\n */\n private startDrawing(mode: \"line\" | \"polygon\" | \"rectangle\"): void {\n this.endDrawingInternal(false); // 结束任何正在进行的绘制,但不清空已完成的实体\n\n this.drawMode = mode;\n this.isDrawing = true;\n this.tempPositions = [];\n this.tempEntities = [];\n\n this.activateDrawingHandlers();\n\n // 触发开始绘制回调\n if (this.onDrawStartCallback) {\n this.onDrawStartCallback();\n }\n }\n\n /**\n * 激活屏幕空间事件处理器\n */\n private activateDrawingHandlers(): void {\n this.deactivateDrawingHandlers(); // 确保之前的手柄已销毁\n\n this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(\n this.scene.canvas\n );\n\n // 左键点击添加点\n this.screenSpaceEventHandler.setInputAction(\n (click: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n const cartesian = this.pickGlobePosition(click.position);\n if (cartesian) {\n this.addPoint(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_CLICK\n );\n\n // 右键删除最后一个点\n this.screenSpaceEventHandler.setInputAction(() => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n this.removeLastPoint();\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n\n // 鼠标移动更新预览\n this.screenSpaceEventHandler.setInputAction(\n (move: Cesium.ScreenSpaceEventHandler.MotionEvent) => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n const cartesian = this.pickGlobePosition(move.endPosition);\n if (cartesian) {\n this.updatePreview(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.MOUSE_MOVE\n );\n\n // 双击结束绘制\n const mapDoubleClickAct =\n this.viewer.cesiumWidget.screenSpaceEventHandler.getInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.screenSpaceEventHandler.setInputAction(\n (dblClick: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n // 阻止 Cesium 默认的双击行为(如追踪实体)\n // Cesium.ScreenSpaceEventHandler.preventDefault(dblClick);\n if (!this.isDrawing) return;\n this.finishDrawing();\n // 恢复 Cesium 默认的双击行为\n this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(\n mapDoubleClickAct,\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n },\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n\n /**\n * 拾取地形或椭球体上的位置\n * @param windowPosition 屏幕坐标\n * @returns 世界坐标 Cartesian3 或 null\n */\n private pickGlobePosition(\n windowPosition: Cesium.Cartesian2\n ): Cesium.Cartesian3 | null {\n // 首先尝试从地形拾取\n const ray = this.viewer.camera.getPickRay(windowPosition);\n if (ray) {\n const position = this.scene.globe.pick(ray, this.scene);\n if (Cesium.defined(position)) {\n return position;\n }\n }\n // 如果地形拾取失败,回退到椭球体拾取\n const ellipsoidPosition = this.viewer.camera.pickEllipsoid(\n windowPosition,\n this.scene.globe.ellipsoid\n );\n return ellipsoidPosition ?? null;\n }\n\n /**\n * 添加一个点到临时位置数组并创建点实体\n * @param position 世界坐标\n */\n private addPoint(position: Cesium.Cartesian3): void {\n this.tempPositions.push(position.clone());\n\n const pointEntity = this.entities.add({\n position: position.clone(),\n point: {\n pixelSize: 5,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(pointEntity);\n this.updateDrawingEntity();\n }\n\n /**\n * 删除最后一个添加的点及其相关的临时实体\n */\n private removeLastPoint(): void {\n if (this.tempPositions.length > 0) {\n this.tempPositions.pop();\n\n // 移除最后添加的点实体\n const lastPointEntity = this.tempEntities.pop();\n if (lastPointEntity) {\n this.entities.remove(lastPointEntity);\n }\n\n // 移除最后添加的线/面片段实体\n const lastLineEntity = this.tempEntities.pop();\n if (lastLineEntity) {\n this.entities.remove(lastLineEntity);\n }\n\n // 重新更新当前的绘制实体\n this.updateDrawingEntity();\n }\n }\n\n /**\n * 更新预览线/面\n * @param currentMousePosition 当前鼠标位置世界坐标\n */\n private updatePreview(currentMousePosition: Cesium.Cartesian3): void {\n this.updateDrawingEntity(currentMousePosition);\n }\n\n /**\n * 核心方法:根据当前点序列更新或创建临时的线/面实体\n * @param previewPoint 可选的预览点,用于显示动态效果\n */\n private updateDrawingEntity(previewPoint?: Cesium.Cartesian3): void {\n // 移除旧的活动实体(包括线和标签)\n this.tempEntities.forEach(entity => {\n if (entity && (entity.polyline || entity.polygon || entity.label)) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n\n const positions = [...this.tempPositions];\n if (previewPoint) {\n positions.push(previewPoint);\n }\n\n if (positions.length < 2) return;\n\n let activeEntity: Cesium.Entity | undefined;\n\n if (this.drawMode === \"line\") {\n // 创建主线条\n activeEntity = this.entities.add({\n polyline: {\n positions: positions,\n width: 3,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n this.tempEntities.push(activeEntity);\n\n // 为每一段添加距离标签\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n const midPoint = Cesium.Cartesian3.midpoint(startPos, endPos, new Cesium.Cartesian3());\n \n const labelEntity = this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"12px sans-serif\",\n fillColor: Cesium.Color.CYAN,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 1,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -10),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(labelEntity);\n }\n\n // 添加总距离标签(在最后一个点)\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\n }\n \n const totalLabelEntity = this.entities.add({\n position: positions[positions.length - 1],\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.tempEntities.push(totalLabelEntity);\n }\n } else if (this.drawMode === \"polygon\") {\n // 绘制填充的多边形区域\n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(positions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n\n if (activeEntity) {\n this.tempEntities.push(activeEntity);\n }\n }\n\n /**\n * 完成当前绘制操作\n */\n private finishDrawing(): void {\n if (this.tempPositions.length < (this.drawMode === \"rectangle\" ? 2 : 2)) {\n // 点数不足,取消绘制\n this.endDrawingInternal(true);\n return;\n }\n\n let finalEntity: Cesium.Entity | null = null;\n const positions = this.tempPositions.map((p) => p.clone());\n\n if (this.drawMode === \"line\") {\n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: positions,\n width: 3,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n\n // 为每一段添加距离标签\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n const midPoint = Cesium.Cartesian3.midpoint(startPos, endPos, new Cesium.Cartesian3());\n \n this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"12px sans-serif\",\n fillColor: Cesium.Color.CYAN,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 1,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -10),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n\n // 添加总距离标签\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\n }\n \n this.entities.add({\n position: positions[positions.length - 1],\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"polygon\") {\n // 绘制填充的多边形区域\n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(positions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n // 添加面积标签\n const area = this.calculatePolygonArea(positions);\n if (area > 0) {\n const center = this.calculatePolygonCenter(positions);\n this.entities.add({\n position: center,\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n // 添加面积标签\n const area = this.calculateRectangleArea(rect);\n if (area > 0) {\n const rectCenter = Cesium.Rectangle.center(rect);\n this.entities.add({\n position: Cesium.Cartesian3.fromRadians(\n rectCenter.longitude,\n rectCenter.latitude\n ),\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n }\n\n // 将完成的实体存入列表\n if (finalEntity) {\n this.finishedEntities.push(finalEntity);\n }\n\n // 清理临时数据和状态\n this.endDrawingInternal(true);\n\n // 触发结束绘制回调\n if (this.onDrawEndCallback) {\n this.onDrawEndCallback(finalEntity);\n }\n }\n\n /**\n * 内部方法:重置绘图状态和清理临时数据\n * @param resetMode 是否重置绘图模式和状态标志\n */\n private endDrawingInternal(resetMode: boolean): void {\n // 清理临时实体\n this.tempEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempEntities = [];\n this.tempPositions = [];\n\n if (resetMode) {\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n }\n\n /**\n * 公共方法:结束当前绘制(如果正在进行)\n */\n endDrawing(): void {\n if (this.isDrawing) {\n this.finishDrawing();\n } else {\n // 如果没有在绘制,也执行一次清理\n this.endDrawingInternal(true);\n }\n }\n\n /**\n * 销毁事件处理器\n */\n private deactivateDrawingHandlers(): void {\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n\n /**\n * 清除所有已绘制的实体\n */\n clearAll(): void {\n // 先结束可能的绘制\n this.endDrawing();\n // 清除所有已完成的实体\n this.finishedEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.finishedEntities = [];\n }\n\n /**\n * 删除一个指定的已完成实体\n * @param entity 要删除的实体\n */\n removeEntity(entity: Cesium.Entity): void {\n const index = this.finishedEntities.indexOf(entity);\n if (index > -1) {\n this.entities.remove(entity);\n this.finishedEntities.splice(index, 1);\n if (this.onEntityRemovedCallback) {\n this.onEntityRemovedCallback(entity);\n }\n }\n }\n\n /**\n * 获取所有已完成的实体\n * @returns 实体数组\n */\n getFinishedEntities(): Cesium.Entity[] {\n return [...this.finishedEntities];\n }\n\n // --- 辅助计算函数 ---\n private calculateRectangle(\n p1: Cesium.Cartesian3,\n p2: Cesium.Cartesian3\n ): Cesium.Rectangle {\n const cartographic1 = Cesium.Cartographic.fromCartesian(p1);\n const cartographic2 = Cesium.Cartographic.fromCartesian(p2);\n const west = Math.min(cartographic1.longitude, cartographic2.longitude);\n const east = Math.max(cartographic1.longitude, cartographic2.longitude);\n const south = Math.min(cartographic1.latitude, cartographic2.latitude);\n const north = Math.max(cartographic1.latitude, cartographic2.latitude);\n return new Cesium.Rectangle(west, south, east, north);\n }\n\n private calculateRectangleArea(rect: Cesium.Rectangle): number {\n const west = rect.west;\n const south = rect.south;\n const east = rect.east;\n const north = rect.north;\n\n const width = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(east, south)\n );\n const height = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(west, north)\n );\n\n return (width * height) / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonArea(positions: Cesium.Cartesian3[]): number {\n if (positions.length < 3) return 0;\n const ellipsoid = this.scene.globe.ellipsoid;\n let area = 0;\n const len = positions.length;\n for (let i = 0; i < len; i++) {\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\n area +=\n (p2.longitude - p1.longitude) *\n (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\n }\n area = Math.abs((area * 6378137.0 * 6378137.0) / 2.0); // WGS84半径\n return area / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonCenter(\n positions: Cesium.Cartesian3[]\n ): Cesium.Cartesian3 {\n if (positions.length === 0) return Cesium.Cartesian3.ZERO;\n let x = 0,\n y = 0,\n z = 0;\n for (let i = 0; i < positions.length; i++) {\n x += positions[i].x;\n y += positions[i].y;\n z += positions[i].z;\n }\n return new Cesium.Cartesian3(\n x / positions.length,\n y / positions.length,\n z / positions.length\n );\n }\n\n // --- 回调注册 ---\n\n /**\n * 设置开始绘制时的回调函数\n * @param callback 回调函数\n */\n onDrawStart(callback: () => void): void {\n this.onDrawStartCallback = callback;\n }\n\n /**\n * 设置结束绘制时的回调函数\n * @param callback 回调函数,参数为完成的实体或null\n */\n onDrawEnd(callback: (entity: Cesium.Entity | null) => void): void {\n this.onDrawEndCallback = callback;\n }\n\n /**\n * 设置实体被移除时的回调函数\n * @param callback 回调函数,参数为被移除的实体\n */\n onEntityRemoved(callback: (entity: Cesium.Entity) => void): void {\n this.onEntityRemovedCallback = callback;\n }\n\n /**\n * 绘制监控圆形区域\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param radius 监控范围半径(米)\n * @param options 可选配置\n */\n public drawMonitoringCircle(\n longitude: number,\n latitude: number,\n height: number,\n radius: number,\n options?: {\n borderColor?: string;\n fillColor?: string;\n borderWidth?: number;\n name?: string;\n }\n ): Cesium.Entity {\n const borderColor = options?.borderColor || '#0062FF';\n const fillColor = options?.fillColor || '#0062FF';\n const borderWidth = options?.borderWidth || 2;\n const name = options?.name || '监控区域';\n\n // 创建圆形区域\n const entity = this.entities.add({\n name: name,\n position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),\n ellipse: {\n semiMajorAxis: radius,\n semiMinorAxis: radius,\n material: Cesium.Color.fromCssColorString(fillColor).withAlpha(0.27),\n outline: true,\n outlineColor: Cesium.Color.fromCssColorString(borderColor),\n outlineWidth: borderWidth,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n\n return entity;\n }\n\n /**\n * 绘制垂直线条\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param options 可选配置\n */\n public drawVerticalLine(\n longitude: number,\n latitude: number,\n height: number,\n options?: {\n color?: string;\n width?: number;\n dashPattern?: number;\n name?: string;\n groundHeight?: number;\n }\n ): Cesium.Entity {\n const color = options?.color || '#0062FF';\n const width = options?.width || 2;\n const dashPattern = options?.dashPattern || 0x00FF00FF;\n const name = options?.name || '垂直线条';\n const groundHeight = options?.groundHeight || 0;\n\n // 计算地面位置\n const groundPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, groundHeight);\n const topPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);\n\n // 创建垂直线条\n const entity = this.entities.add({\n name: name,\n polyline: {\n positions: [groundPosition, topPosition],\n width: width,\n material: new Cesium.PolylineDashMaterialProperty({\n color: Cesium.Color.fromCssColorString(color),\n }),\n clampToGround: false,\n },\n });\n\n return entity;\n }\n\n /**\n * 销毁工具,清理所有事件监听器\n */\n destroy(): void {\n this.deactivateDrawingHandlers();\n this.clearFrustum(); // 清理视锥体相关资源\n // 可以选择不清除实体,由用户决定\n // this.clearAll();\n }\n}\n\n// 为了在 HTML 中通过 <script type=\"module\"> 或打包工具使用\n// @ts-ignore\nwindow.DrawHelper = DrawHelper;\n\nexport default DrawHelper;\n","import * as Cesium from 'cesium';\r\nimport type { Viewer, Cartesian3, Cartographic } from 'cesium';\r\nimport DrawHelper from './CesiumMapHelper';\r\n\r\n// 工具栏配置接口\r\nexport interface ToolbarConfig {\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\r\n buttonSize?: number;\r\n buttonSpacing?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderRadius?: number;\r\n borderWidth?: number;\r\n boxShadow?: string;\r\n zIndex?: number;\r\n buttons?: CustomButtonConfig[];\r\n}\r\n\r\n// 按钮配置接口\r\nexport interface ButtonConfig {\r\n id: string;\r\n icon: string;\r\n title: string;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n}\r\n\r\n// 自定义按钮配置接口\r\nexport interface CustomButtonConfig {\r\n id: string;\r\n icon: string | HTMLElement;\r\n title: string;\r\n enabled?: boolean;\r\n visible?: boolean;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n onClick?: (buttonId: string, buttonElement: HTMLElement) => void;\r\n}\r\n\r\n// 搜索回调接口\r\nexport interface SearchCallback {\r\n onSearch?: (query: string) => Promise<SearchResult[]>;\r\n onSelect?: (result: SearchResult) => void;\r\n onSearchInput?: (query: string, container: HTMLElement) => void;\r\n onSearchResults?: (results: SearchResult[], container: HTMLElement) => void;\r\n}\r\n\r\n// 搜索结果接口\r\nexport interface SearchResult {\r\n name: string;\r\n address: string;\r\n longitude: number;\r\n latitude: number;\r\n height?: number;\r\n}\r\n\r\n// 测量回调接口\r\nexport interface MeasurementCallback {\r\n onDistanceComplete?: (positions: Cartesian3[], distance: number) => void;\r\n onAreaComplete?: (positions: Cartesian3[], area: number) => void;\r\n onClear?: () => void;\r\n}\r\n\r\n// 缩放回调接口\r\nexport interface ZoomCallback {\r\n onZoomIn?: (beforeLevel: number, afterLevel: number) => void;\r\n onZoomOut?: (beforeLevel: number, afterLevel: number) => void;\r\n}\r\n\r\n// 地图类型接口\r\nexport interface MapType {\r\n id: string;\r\n name: string;\r\n thumbnail: string;\r\n provider: Cesium.ImageryProvider;\r\n}\r\n\r\n/**\r\n * Cesium地图工具栏类\r\n * 提供搜索、测量、2D/3D切换、图层切换、定位、缩放、全屏等功能\r\n */\r\nexport class CesiumMapToolbar {\r\n private viewer: Viewer;\r\n private drawHelper: DrawHelper;\r\n private container: HTMLElement;\r\n private toolbarElement!: HTMLElement;\r\n private config: ToolbarConfig;\r\n private searchCallback?: SearchCallback;\r\n private measurementCallback?: MeasurementCallback;\r\n private zoomCallback?: ZoomCallback;\r\n private initialCenter?: { longitude: number; latitude: number; height: number };\r\n private isFullscreen: boolean = false;\r\n private currentMapType: string = 'imagery';\r\n\r\n // 地图类型配置\r\n private mapTypes: MapType[] = [\r\n {\r\n id: 'normal',\r\n name: '天地图-普通',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: '3d',\r\n name: '天地图-三维',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'imagery',\r\n name: '天地图-影像',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'terrain',\r\n name: '天地图-地形',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n }\r\n ];\r\n\r\n constructor(\r\n viewer: Viewer,\r\n container: HTMLElement,\r\n config: ToolbarConfig = {},\r\n callbacks?: {\r\n search?: SearchCallback;\r\n measurement?: MeasurementCallback;\r\n zoom?: ZoomCallback;\r\n },\r\n initialCenter?: { longitude: number; latitude: number; height: number }\r\n ) {\r\n this.viewer = viewer;\r\n this.container = container;\r\n this.config = {\r\n position: 'bottom-right',\r\n buttonSize: 40,\r\n buttonSpacing: 8,\r\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\r\n borderColor: '#e0e0e0',\r\n borderRadius: 6,\r\n boxShadow: '0 2px 10px rgba(0, 0, 0, 0.1)',\r\n zIndex: 1000,\r\n ...config\r\n };\r\n this.searchCallback = callbacks?.search;\r\n this.measurementCallback = callbacks?.measurement;\r\n this.zoomCallback = callbacks?.zoom;\r\n\r\n // 设置初始中心点\r\n this.initialCenter = initialCenter;\r\n\r\n // 初始化绘图助手\r\n this.drawHelper = new DrawHelper(viewer);\r\n this.setupDrawHelperCallbacks();\r\n\r\n // 创建工具栏\r\n this.createToolbar();\r\n }\r\n\r\n /**\r\n * 设置初始中心点\r\n */\r\n public setInitialCenter(center: { longitude: number; latitude: number; height: number }): void {\r\n this.initialCenter = center;\r\n }\r\n\r\n /**\r\n * 获取初始中心点\r\n */\r\n public getInitialCenter(): { longitude: number; latitude: number; height: number } | undefined {\r\n return this.initialCenter;\r\n }\r\n\r\n /**\r\n * 复位到初始位置(公共方法)\r\n */\r\n public resetToInitialLocation(): void {\r\n this.resetLocation();\r\n }\r\n\r\n /**\r\n * 更新按钮配置\r\n */\r\n public updateButtonConfig(buttonId: string, config: Partial<CustomButtonConfig>): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (!button) return;\r\n\r\n // 更新按钮属性\r\n if (config.title) button.title = config.title;\r\n if (config.icon) this.setButtonIcon(button, config.icon);\r\n if (config.size) {\r\n button.style.width = `${config.size}px`;\r\n button.style.height = `${config.size}px`;\r\n }\r\n if (config.color) button.style.background = config.color;\r\n }\r\n\r\n /**\r\n * 添加自定义按钮\r\n */\r\n public addCustomButton(config: CustomButtonConfig): void {\r\n const buttonConfig: ButtonConfig = {\r\n id: config.id,\r\n icon: typeof config.icon === 'string' ? config.icon : '',\r\n title: config.title,\r\n size: config.size,\r\n color: config.color,\r\n hoverColor: config.hoverColor,\r\n activeColor: config.activeColor\r\n };\r\n\r\n const buttonElement = this.createButton(buttonConfig);\r\n this.toolbarElement.appendChild(buttonElement);\r\n\r\n // 更新配置\r\n if (!this.config.buttons) {\r\n this.config.buttons = [];\r\n }\r\n this.config.buttons.push(config);\r\n }\r\n\r\n /**\r\n * 移除按钮\r\n */\r\n public removeButton(buttonId: string): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (button && button.parentNode) {\r\n button.parentNode.removeChild(button);\r\n }\r\n\r\n // 从配置中移除\r\n if (this.config.buttons) {\r\n this.config.buttons = this.config.buttons.filter(btn => btn.id !== buttonId);\r\n }\r\n }\r\n\r\n /**\r\n * 获取按钮元素\r\n */\r\n public getButtonElement(buttonId: string): HTMLElement | null {\r\n return this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n }\r\n\r\n /**\r\n * 设置绘图助手回调\r\n */\r\n private setupDrawHelperCallbacks(): void {\r\n this.drawHelper.onDrawStart(() => {\r\n console.log('开始绘制');\r\n });\r\n\r\n this.drawHelper.onDrawEnd((entity) => {\r\n if (entity) {\r\n console.log('绘制完成', entity);\r\n // 根据绘制类型触发相应回调\r\n if (entity.polyline) {\r\n // 测距完成\r\n const positions = entity.polyline.positions?.getValue(Cesium.JulianDate.now()) as Cartesian3[];\r\n if (positions && this.measurementCallback?.onDistanceComplete) {\r\n let totalDistance = 0;\r\n for (let i = 1; i < positions.length; i++) {\r\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\r\n }\r\n this.measurementCallback.onDistanceComplete(positions, totalDistance);\r\n }\r\n } else if (entity.polygon) {\r\n // 测面积完成\r\n const positions = entity.polygon.hierarchy?.getValue(Cesium.JulianDate.now()) as Cesium.PolygonHierarchy;\r\n if (positions && this.measurementCallback?.onAreaComplete) {\r\n // 计算面积\r\n const area = this.calculatePolygonArea(positions.positions);\r\n this.measurementCallback.onAreaComplete(positions.positions, area);\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.drawHelper.onEntityRemoved((entity) => {\r\n console.log('实体被移除', entity);\r\n });\r\n }\r\n\r\n /**\r\n * 计算多边形面积\r\n */\r\n private calculatePolygonArea(positions: Cartesian3[]): number {\r\n if (positions.length < 3) return 0;\r\n \r\n const ellipsoid = this.viewer.scene.globe.ellipsoid;\r\n let area = 0;\r\n const len = positions.length;\r\n \r\n for (let i = 0; i < len; i++) {\r\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\r\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\r\n area += (p2.longitude - p1.longitude) * (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\r\n }\r\n \r\n area = Math.abs(area * 6378137.0 * 6378137.0 / 2.0);\r\n return area / 1e6; // 转换为平方公里\r\n }\r\n\r\n /**\r\n * 创建工具栏\r\n */\r\n private createToolbar(): void {\r\n this.toolbarElement = document.createElement('div');\r\n this.toolbarElement.className = 'cesium-map-toolbar';\r\n this.toolbarElement.style.cssText = `\r\n position: absolute;\r\n ${this.config.position?.includes('right') ? 'right' : 'left'}: 10px;\r\n ${this.config.position?.includes('bottom') ? 'bottom' : 'top'}: 10px;\r\n background: ${this.config.backgroundColor};\r\n border: ${this.config.borderWidth}px solid ${this.config.borderColor};\r\n border-radius: ${this.config.borderRadius}px;\r\n box-shadow: ${this.config.boxShadow};\r\n padding: 8px;\r\n z-index: ${this.config.zIndex};\r\n display: flex;\r\n flex-direction: column;\r\n gap: ${this.config.buttonSpacing}px;\r\n `;\r\n\r\n // 获取按钮配置\r\n const buttons = this.getButtonConfigs();\r\n\r\n buttons.forEach(button => {\r\n const buttonElement = this.createButton(button);\r\n this.toolbarElement.appendChild(buttonElement);\r\n });\r\n\r\n this.container.appendChild(this.toolbarElement);\r\n }\r\n\r\n /**\r\n * 获取按钮配置\r\n */\r\n private getButtonConfigs(): ButtonConfig[] {\r\n // 默认按钮配置\r\n const defaultButtons: ButtonConfig[] = [\r\n { id: 'search', icon: '🔍', title: '搜索' },\r\n { id: 'measure', icon: '📏', title: '测量' },\r\n { id: 'view2d3d', icon: '2D', title: '2D或3D' },\r\n { id: 'layers', icon: '📚', title: '图层切换' },\r\n { id: 'location', icon: '🎯', title: '定位' },\r\n { id: 'zoom-in', icon: '🔍+', title: '放大' },\r\n { id: 'zoom-out', icon: '🔍-', title: '缩小' },\r\n { id: 'fullscreen', icon: '⛶', title: '全屏' }\r\n ];\r\n\r\n // 如果用户提供了自定义按钮配置,则使用自定义配置\r\n if (this.config.buttons && this.config.buttons.length > 0) {\r\n return this.config.buttons.map(customButton => ({\r\n id: customButton.id,\r\n icon: typeof customButton.icon === 'string' ? customButton.icon : '',\r\n title: customButton.title,\r\n size: customButton.size,\r\n color: customButton.color,\r\n hoverColor: customButton.hoverColor,\r\n activeColor: customButton.activeColor\r\n }));\r\n }\r\n\r\n return defaultButtons;\r\n }\r\n\r\n /**\r\n * 创建按钮\r\n */\r\n private createButton(config: ButtonConfig): HTMLElement {\r\n const button = document.createElement('div');\r\n button.className = 'cesium-toolbar-button';\r\n button.setAttribute('data-tool', config.id);\r\n button.title = config.title;\r\n \r\n const buttonSize = config.size || this.config.buttonSize;\r\n const buttonColor = config.color || 'rgba(66, 133, 244, 0.4)';\r\n const buttonHoverColor = config.hoverColor || 'rgba(51, 103, 214, 0.9)';\r\n \r\n button.style.cssText = `\r\n width: ${buttonSize}px;\r\n height: ${buttonSize}px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: ${buttonColor};\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: bold;\r\n transition: all 0.2s ease;\r\n user-select: none;\r\n position: relative;\r\n `;\r\n\r\n // 设置图标内容\r\n this.setButtonIcon(button, config.icon);\r\n\r\n // 悬停效果\r\n button.addEventListener('mouseenter', () => {\r\n button.style.background = buttonHoverColor;\r\n button.style.transform = 'scale(1.05)';\r\n });\r\n\r\n button.addEventListener('mouseleave', () => {\r\n button.style.background = buttonColor;\r\n button.style.transform = 'scale(1)';\r\n });\r\n\r\n // 处理点击事件\r\n this.setupButtonEvents(button, config);\r\n\r\n return button;\r\n }\r\n\r\n /**\r\n * 设置按钮图标\r\n */\r\n private setButtonIcon(button: HTMLElement, icon: string | HTMLElement): void {\r\n if (typeof icon === 'string') {\r\n button.innerHTML = icon;\r\n } else if (icon instanceof HTMLElement) {\r\n button.innerHTML = '';\r\n button.appendChild(icon);\r\n }\r\n }\r\n\r\n /**\r\n * 设置按钮事件\r\n */\r\n private setupButtonEvents(button: HTMLElement, config: ButtonConfig): void {\r\n // 查找自定义按钮配置\r\n const customButton = this.config.buttons?.find(btn => btn.id === config.id);\r\n \r\n if (customButton?.onClick) {\r\n // 自定义按钮点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n customButton.onClick!(config.id, button);\r\n });\r\n } else if (!['search', 'measure', 'layers'].includes(config.id)) {\r\n // 默认按钮点击事件(除了搜索、测量、图层切换按钮)\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else {\r\n // 搜索、测量、图层切换按钮使用hover事件\r\n button.addEventListener('mouseenter', () => {\r\n this.handleButtonClick(config.id, button);\r\n });\r\n \r\n // 添加鼠标离开事件来关闭菜单\r\n button.addEventListener('mouseleave', () => {\r\n this.closeMenuOnButtonLeave(config.id);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 按钮鼠标离开时关闭菜单\r\n */\r\n private closeMenuOnButtonLeave(buttonId: string): void {\r\n // 延迟关闭,给用户时间移动到菜单上\r\n setTimeout(() => {\r\n switch (buttonId) {\r\n case 'search':\r\n const searchContainer = this.toolbarElement.querySelector('.search-container');\r\n if (searchContainer && !searchContainer.matches(':hover')) {\r\n searchContainer.remove();\r\n }\r\n break;\r\n case 'measure':\r\n const measureMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (measureMenu && !measureMenu.matches(':hover')) {\r\n measureMenu.remove();\r\n }\r\n break;\r\n case 'layers':\r\n const layersMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (layersMenu && !layersMenu.matches(':hover')) {\r\n layersMenu.remove();\r\n }\r\n break;\r\n }\r\n }, 100); // 100ms延迟,给用户时间移动到菜单\r\n }\r\n\r\n /**\r\n * 处理按钮点击\r\n */\r\n private handleButtonClick(buttonId: string, buttonElement: HTMLElement): void {\r\n switch (buttonId) {\r\n case 'search':\r\n this.toggleSearch(buttonElement);\r\n break;\r\n case 'measure':\r\n this.toggleMeasurement(buttonElement);\r\n break;\r\n case 'view2d3d':\r\n this.toggle2D3D(buttonElement);\r\n break;\r\n case 'layers':\r\n this.toggleLayers(buttonElement);\r\n break;\r\n case 'location':\r\n this.resetLocation();\r\n break;\r\n case 'zoom-in':\r\n this.zoomIn();\r\n break;\r\n case 'zoom-out':\r\n this.zoomOut();\r\n break;\r\n case 'fullscreen':\r\n this.toggleFullscreen();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换搜索功能\r\n */\r\n private toggleSearch(buttonElement: HTMLElement): void {\r\n const existingSearch = this.toolbarElement.querySelector('.search-container');\r\n if (existingSearch) {\r\n return; // 如果搜索框已存在,不重复创建\r\n }\r\n\r\n const searchContainer = document.createElement('div');\r\n searchContainer.className = 'search-container';\r\n searchContainer.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 8px;\r\n min-width: 200px;\r\n z-index: 1001;\r\n `;\r\n\r\n const searchInput = document.createElement('input');\r\n searchInput.type = 'text';\r\n searchInput.placeholder = '请输入地址';\r\n searchInput.style.cssText = `\r\n padding: 6px 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n outline: none;\r\n `;\r\n\r\n const resultsContainer = document.createElement('div');\r\n resultsContainer.className = 'search-results';\r\n resultsContainer.style.cssText = `\r\n margin-top: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n `;\r\n\r\n searchContainer.appendChild(searchInput);\r\n searchContainer.appendChild(resultsContainer);\r\n\r\n // 插入到按钮前面\r\n this.toolbarElement.insertBefore(searchContainer, buttonElement);\r\n\r\n // 搜索功能\r\n let searchTimeout: ReturnType<typeof setTimeout>;\r\n searchInput.addEventListener('input', () => {\r\n clearTimeout(searchTimeout);\r\n const query = searchInput.value.trim();\r\n \r\n // 如果用户提供了自定义搜索输入处理逻辑\r\n if (this.searchCallback?.onSearchInput) {\r\n this.searchCallback.onSearchInput(query, resultsContainer);\r\n return;\r\n }\r\n \r\n if (query.length < 2) {\r\n resultsContainer.innerHTML = '';\r\n return;\r\n }\r\n\r\n searchTimeout = setTimeout(async () => {\r\n if (this.searchCallback?.onSearch) {\r\n try {\r\n const results = await this.searchCallback.onSearch(query);\r\n this.displaySearchResults(results, resultsContainer);\r\n } catch (error) {\r\n console.error('搜索失败:', error);\r\n resultsContainer.innerHTML = '<div style=\"padding: 8px; color: #666;\">搜索失败</div>';\r\n }\r\n } else {\r\n // 默认搜索逻辑\r\n this.performDefaultSearch(query, resultsContainer);\r\n }\r\n }, 300);\r\n });\r\n\r\n // 鼠标离开搜索框区域时关闭\r\n const closeSearch = () => {\r\n searchContainer.remove();\r\n };\r\n \r\n // 监听搜索框的鼠标离开事件\r\n searchContainer.addEventListener('mouseleave', closeSearch);\r\n }\r\n\r\n /**\r\n * 显示搜索结果\r\n */\r\n private displaySearchResults(results: SearchResult[], container: HTMLElement): void {\r\n // 如果用户提供了自定义搜索结果处理逻辑\r\n if (this.searchCallback?.onSearchResults) {\r\n this.searchCallback.onSearchResults(results, container);\r\n return;\r\n }\r\n\r\n // 默认搜索结果显示逻辑\r\n container.innerHTML = '';\r\n \r\n if (results.length === 0) {\r\n container.innerHTML = '<div style=\"padding: 8px; color: #666;\">未找到相关地址</div>';\r\n return;\r\n }\r\n\r\n results.forEach(result => {\r\n const resultItem = document.createElement('div');\r\n resultItem.style.cssText = `\r\n padding: 8px;\r\n border-bottom: 1px solid #f0f0f0;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n resultItem.innerHTML = `\r\n <div style=\"font-weight: bold; margin-bottom: 2px;\">${result.name}</div>\r\n <div style=\"font-size: 12px; color: #666;\">${result.address}</div>\r\n `;\r\n\r\n resultItem.addEventListener('mouseenter', () => {\r\n resultItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n resultItem.addEventListener('mouseleave', () => {\r\n resultItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n resultItem.addEventListener('click', () => {\r\n this.selectSearchResult(result);\r\n container.parentElement?.remove();\r\n });\r\n\r\n container.appendChild(resultItem);\r\n });\r\n }\r\n\r\n /**\r\n * 选择搜索结果\r\n */\r\n private selectSearchResult(result: SearchResult): void {\r\n // 飞行到指定位置\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n result.longitude,\r\n result.latitude,\r\n result.height || 1000\r\n ),\r\n duration: 1.0\r\n });\r\n\r\n // 触发回调\r\n if (this.searchCallback?.onSelect) {\r\n this.searchCallback.onSelect(result);\r\n }\r\n }\r\n\r\n /**\r\n * 默认搜索逻辑\r\n */\r\n private performDefaultSearch(query: string, container: HTMLElement): void {\r\n // 模拟搜索结果\r\n const mockResults: SearchResult[] = [\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n }\r\n ];\r\n\r\n this.displaySearchResults(mockResults, container);\r\n }\r\n\r\n /**\r\n * 切换测量功能\r\n */\r\n private toggleMeasurement(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'measurement-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 4px 0;\r\n min-width: 120px;\r\n z-index: 1001;\r\n `;\r\n\r\n const menuItems = [\r\n { id: 'measure-area', text: '测面积', icon: '📐' },\r\n { id: 'measure-distance', text: '测距', icon: '📏' },\r\n { id: 'clear-measurement', text: '清除', icon: '🗑️' }\r\n ];\r\n\r\n menuItems.forEach(item => {\r\n const menuItem = document.createElement('div');\r\n menuItem.style.cssText = `\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n menuItem.innerHTML = `${item.icon} ${item.text}`;\r\n\r\n menuItem.addEventListener('mouseenter', () => {\r\n menuItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n menuItem.addEventListener('mouseleave', () => {\r\n menuItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n menuItem.addEventListener('click', () => {\r\n this.handleMeasurementAction(item.id);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(menuItem);\r\n });\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 处理测量操作\r\n */\r\n private handleMeasurementAction(action: string): void {\r\n switch (action) {\r\n case 'measure-area':\r\n this.drawHelper.startDrawingPolygon();\r\n break;\r\n case 'measure-distance':\r\n this.drawHelper.startDrawingLine();\r\n break;\r\n case 'clear-measurement':\r\n this.drawHelper.clearAll();\r\n if (this.measurementCallback?.onClear) {\r\n this.measurementCallback.onClear();\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换2D/3D视图\r\n */\r\n private toggle2D3D(buttonElement: HTMLElement): void {\r\n const currentMode = this.viewer.scene.mode;\r\n const targetMode = currentMode === Cesium.SceneMode.SCENE3D \r\n ? Cesium.SceneMode.SCENE2D \r\n : Cesium.SceneMode.SCENE3D;\r\n \r\n this.viewer.scene.mode = targetMode;\r\n \r\n // 更新按钮文本\r\n buttonElement.innerHTML = targetMode === Cesium.SceneMode.SCENE3D ? '3D' : '2D';\r\n }\r\n\r\n /**\r\n * 切换图层\r\n */\r\n private toggleLayers(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'layers-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n padding: 12px;\r\n min-width: 220px;\r\n max-width: 280px;\r\n z-index: 1001;\r\n display: flex;\r\n flex-direction: column;\r\n `;\r\n\r\n // 地图类型选择\r\n const mapTypeSection = document.createElement('div');\r\n mapTypeSection.style.cssText = `\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n `;\r\n mapTypeSection.innerHTML = '<div style=\"font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;\">地图类型</div>';\r\n \r\n this.mapTypes.forEach(mapType => {\r\n const mapTypeItem = document.createElement('div');\r\n mapTypeItem.style.cssText = `\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n width: 100%;\r\n box-sizing: border-box;\r\n ${mapType.id === this.currentMapType ? 'background-color: #e3f2fd;' : ''}\r\n `;\r\n\r\n const thumbnail = document.createElement('img');\r\n thumbnail.src = mapType.thumbnail;\r\n thumbnail.style.cssText = `\r\n width: 24px; \r\n height: 24px; \r\n border-radius: 3px;\r\n flex-shrink: 0;\r\n `;\r\n\r\n const label = document.createElement('span');\r\n label.textContent = mapType.name;\r\n label.style.cssText = `\r\n font-size: 14px;\r\n color: #333;\r\n flex: 1;\r\n `;\r\n\r\n const checkmark = document.createElement('span');\r\n if (mapType.id === this.currentMapType) {\r\n checkmark.textContent = '✓';\r\n checkmark.style.cssText = `\r\n color: #1976d2; \r\n font-weight: bold; \r\n font-size: 16px;\r\n flex-shrink: 0;\r\n `;\r\n }\r\n\r\n mapTypeItem.appendChild(thumbnail);\r\n mapTypeItem.appendChild(label);\r\n mapTypeItem.appendChild(checkmark);\r\n\r\n mapTypeItem.addEventListener('mouseenter', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = '#f5f5f5';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('mouseleave', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = 'transparent';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('click', () => {\r\n this.switchMapType(mapType.id);\r\n menu.remove();\r\n });\r\n\r\n mapTypeSection.appendChild(mapTypeItem);\r\n });\r\n\r\n menu.appendChild(mapTypeSection);\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 切换地图类型\r\n */\r\n private switchMapType(mapTypeId: string): void {\r\n const mapType = this.mapTypes.find(mt => mt.id === mapTypeId);\r\n if (!mapType) return;\r\n\r\n // 移除当前图层\r\n this.viewer.imageryLayers.removeAll();\r\n \r\n // 添加新图层\r\n this.viewer.imageryLayers.addImageryProvider(mapType.provider);\r\n \r\n this.currentMapType = mapTypeId;\r\n }\r\n\r\n /**\r\n * 复位到初始位置\r\n */\r\n private resetLocation(): void {\r\n if (!this.initialCenter) {\r\n console.warn('未设置初始中心点,无法执行复位操作');\r\n return;\r\n }\r\n\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n this.initialCenter.longitude,\r\n this.initialCenter.latitude,\r\n this.initialCenter.height\r\n ),\r\n duration: 1.0\r\n });\r\n }\r\n\r\n /**\r\n * 放大\r\n */\r\n private zoomIn(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomIn(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomIn) {\r\n this.zoomCallback.onZoomIn(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 缩小\r\n */\r\n private zoomOut(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomOut(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomOut) {\r\n this.zoomCallback.onZoomOut(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 切换全屏\r\n */\r\n private toggleFullscreen(): void {\r\n if (!this.isFullscreen) {\r\n this.enterFullscreen();\r\n } else {\r\n this.exitFullscreen();\r\n }\r\n }\r\n\r\n /**\r\n * 进入全屏\r\n */\r\n private enterFullscreen(): void {\r\n const container = this.viewer.container;\r\n \r\n if (container.requestFullscreen) {\r\n container.requestFullscreen();\r\n } else if ((container as any).webkitRequestFullscreen) {\r\n (container as any).webkitRequestFullscreen();\r\n } else if ((container as any).msRequestFullscreen) {\r\n (container as any).msRequestFullscreen();\r\n }\r\n\r\n this.isFullscreen = true;\r\n \r\n // 监听全屏状态变化\r\n const fullscreenChange = () => {\r\n if (!document.fullscreenElement && \r\n !(document as any).webkitFullscreenElement && \r\n !(document as any).msFullscreenElement) {\r\n this.isFullscreen = false;\r\n document.removeEventListener('fullscreenchange', fullscreenChange);\r\n document.removeEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.removeEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n };\r\n\r\n document.addEventListener('fullscreenchange', fullscreenChange);\r\n document.addEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.addEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n\r\n /**\r\n * 退出全屏\r\n */\r\n private exitFullscreen(): void {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if ((document as any).webkitExitFullscreen) {\r\n (document as any).webkitExitFullscreen();\r\n } else if ((document as any).msExitFullscreen) {\r\n (document as any).msExitFullscreen();\r\n }\r\n\r\n this.isFullscreen = false;\r\n }\r\n\r\n /**\r\n * 销毁工具栏\r\n */\r\n destroy(): void {\r\n if (this.toolbarElement && this.toolbarElement.parentNode) {\r\n this.toolbarElement.parentNode.removeChild(this.toolbarElement);\r\n }\r\n this.drawHelper.destroy();\r\n }\r\n}\r\n","import * as Cesium from 'cesium'\nimport { Ion, Viewer, createWorldTerrainAsync, Terrain, Cartesian3, SampledPositionProperty, TerrainProvider } from 'cesium'\nimport type { Entity, Viewer as CesiumViewer, EntityCollection } from 'cesium'\n\n\ninterface InitOptions {\n terrain: Terrain, // 地形\n terrainProvider?: TerrainProvider // 地形提供者\n mapType?: string // 地图类型,默认为天地图\n imageryProvider?: Cesium.UrlTemplateImageryProvider // 自定义影像图层提供r\n imageryLayers?: Cesium.ImageryLayerCollection // 自定义影像图层集合\n terrainShadows?: Cesium.ShadowMode // 地形阴影\n contextOptions?: Cesium.ContextOptions // 上下文选项\n scene3DOnly?: boolean // 是否只使用3D场景\n selectionIndicator?: boolean // 选择指示器\n navigationHelpButton?: boolean // 导航帮助按钮\n fullscreenButton?: boolean // 全屏按钮\n geocoder?: boolean // 地理编码器\n homeButton?: boolean // 主页按钮\n infoBox?: boolean // 信息框\n vrButton?: boolean // VR按钮\n sceneModePicker?: boolean // 场景模式选择器\n timeline?: boolean // 时间轴\n animation?: boolean // 动画\n baseLayerPicker?: boolean // 基础图层选择器\n navigationInstructionsInitiallyVisible?: boolean // 导航指令初始可见\n clock?: Cesium.Clock // 时钟\n sceneMode?: Cesium.SceneMode // 场景模式\n screenSpaceEventHandler?: Cesium.ScreenSpaceEventHandler // 屏幕空间事件处理器\n useDefaultRenderLoop?: boolean // 使用默认渲染循环\n targetFrameRate?: number // 目标帧率\n showRenderLoopErrors?: boolean // 显示渲染循环错误\n automaticallyTrackDataSourceClocks?: boolean // 自动跟踪数据源时钟\n dataSources?: Cesium.DataSourceCollection // 数据源集合\n creationTime?: number // 创建时间\n useBrowserRecommendedResolution?: boolean // 使用浏览器推荐分辨率\n resolutionScale?: number // 分辨率缩放\n orderIndependentTransparency?: boolean // 无序透明度\n shadows?: boolean // 阴影\n terrainExaggeration?: number // 地形夸张系数\n maximumScreenSpaceError?: number // 最大屏幕空间误差\n maximumNumberOfLoadedTiles?: number // 最大加载瓦片数量\n}\n\ninterface MapCenter {\n latitude: number\n longitude: number\n height: number,\n pitch?: number\n heading?: number\n}\n\ninterface TianDiMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\ninterface GaoDeMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\n\nexport function createTianDiMap(): TianDiMap {\n return {\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n }\n}\n\nexport function createGaoDeMap(): Cesium.UrlTemplateImageryProvider {\n return new Cesium.UrlTemplateImageryProvider({\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n })\n}\n\nexport async function initCesium(\n containerId: string,\n options: InitOptions,\n mapCenter: MapCenter = { longitude: 120.2052342, latitude: 30.2489634, height: 1000, pitch: -60, heading: 0 }\n): Promise<{ viewer: CesiumViewer; initialCenter: MapCenter }> {\n Ion.defaultAccessToken = (import.meta as any).env.VITE_CESIUM_TOKEN\n const viewer = new Viewer(containerId, {\n timeline: false,\n animation: false,\n baseLayerPicker: false,\n ...options\n })\n // 地形提供者\n if (!options.terrainProvider && !options.terrain) {\n viewer.terrainProvider = await createWorldTerrainAsync()\n }\n // 添加高德图影像图层\n if (options.mapType === 'gaode') {\n viewer.imageryLayers.removeAll();\n viewer.imageryLayers.addImageryProvider(createGaoDeMap());\n }\n if (mapCenter) {\n // 设置初始视角为中国区域 (经度, 纬度, 高度)\n viewer.camera.flyTo({\n destination: Cesium.Cartesian3.fromDegrees(mapCenter.longitude, mapCenter.latitude, mapCenter.height), // 中国中心坐标\n orientation: {\n heading: Cesium.Math.toRadians(mapCenter.heading || 0), // 方向角度\n pitch: Cesium.Math.toRadians(mapCenter.pitch || -30), // 俯\n }\n });\n }\n (viewer.cesiumWidget.creditContainer as HTMLElement).style.display = 'none';\n return { viewer, initialCenter: mapCenter }\n}","// VMap Cesium Toolbar Plugin\r\n// 导出主要类和接口\r\n\r\n// 核心类\r\nexport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nexport { default as DrawHelper } from './libs/CesiumMapHelper';\r\nexport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 类型定义\r\nexport type {\r\n ToolbarConfig,\r\n ButtonConfig,\r\n CustomButtonConfig,\r\n SearchCallback,\r\n SearchResult,\r\n MeasurementCallback,\r\n ZoomCallback,\r\n MapType\r\n} from './libs/CesiumMapToolbar';\r\n\r\nexport type {\r\n FrustumOptions,\r\n OverlayOptions\r\n} from './libs/CesiumMapModel';\r\n\r\n// 导入用于默认导出\r\nimport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nimport DrawHelper from './libs/CesiumMapHelper';\r\nimport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 默认导出\r\nexport default {\r\n CesiumMapToolbar,\r\n DrawHelper,\r\n initCesium\r\n};\r\n"],"names":["DrawHelper","viewer","Cesium","primitive","options","fov","aspectRatio","near","far","position","orientation","frustum","fillGeometry","fillInstance","fillPrimitive","outlineGeometry","outlineInstance","outlinePrimitive","movement","error","mode","click","cartesian","move","mapDoubleClickAct","dblClick","windowPosition","ray","pointEntity","lastPointEntity","lastLineEntity","currentMousePosition","previewPoint","entity","positions","activeEntity","i","startPos","endPos","distance","midPoint","labelEntity","totalDistance","totalLabelEntity","rect","finalEntity","p","area","center","rectCenter","resetMode","index","p1","p2","cartographic1","cartographic2","west","east","south","north","width","height","ellipsoid","len","x","y","z","callback","longitude","latitude","radius","borderColor","fillColor","borderWidth","name","color","groundHeight","groundPosition","topPosition","CesiumMapToolbar","container","config","callbacks","initialCenter","buttonId","button","buttonConfig","buttonElement","btn","defaultButtons","customButton","buttonSize","buttonColor","buttonHoverColor","icon","e","searchContainer","measureMenu","layersMenu","searchInput","resultsContainer","searchTimeout","query","results","closeSearch","result","resultItem","mockResults","menu","item","menuItem","closeMenu","action","targetMode","mapTypeSection","mapType","mapTypeItem","thumbnail","label","checkmark","mapTypeId","mt","beforeLevel","afterLevel","fullscreenChange","createGaoDeMap","initCesium","containerId","mapCenter","Ion","Viewer","createWorldTerrainAsync"],"mappings":"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"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/libs/CesiumMapHelper.ts","../src/libs/CesiumMapToolbar.ts","../src/libs/CesiumMapLoader.ts","../src/index.ts"],"sourcesContent":["import * as Cesium from \"cesium\";\nimport type { Primitive } from \"cesium\";\nimport type { FrustumOptions } from \"./CesiumMapModel\";\n/**\n * Cesium 绘图辅助工具类\n * 支持绘制点、线、多边形、矩形,并提供编辑和删除功能\n * 适用于 Cesium 1.132.0\n */\nclass DrawHelper {\n private viewer: Cesium.Viewer;\n private scene: Cesium.Scene;\n private entities: Cesium.EntityCollection;\n private frustumPrimitives: Primitive[] = [];\n\n // 绘图状态和数据\n private drawMode: \"line\" | \"polygon\" | \"rectangle\" | null = null;\n private isDrawing: boolean = false;\n private tempPositions: Cesium.Cartesian3[] = [];\n private tempEntities: Cesium.Entity[] = []; // 临时实体,用于绘制过程中\n private tempLabelEntities: Cesium.Entity[] = []; // 临时标签实体\n private finishedEntities: Cesium.Entity[] = []; // 已完成的实体\n private finishedLabelEntities: Cesium.Entity[] = []; // 已完成的标签实体\n private finishedPointEntities: Cesium.Entity[] = []; // 已完成的点实体\n private publicEntities: Cesium.Entity[] = []; // 通过公共方法创建的实体\n private _doubleClickPending: boolean = false; // 双击判断\n // 事件处理器\n private screenSpaceEventHandler: Cesium.ScreenSpaceEventHandler | null = null;\n // 回调函数\n private onDrawStartCallback: (() => void) | null = null;\n private onDrawEndCallback: ((entity: Cesium.Entity | null) => void) | null =\n null;\n private onEntityRemovedCallback: ((entity: Cesium.Entity) => void) | null =\n null;\n private offsetHeight: number = 2;\n\n /**\n * 构造函数\n * @param viewer Cesium Viewer 实例\n */\n constructor(viewer: Cesium.Viewer) {\n if (!viewer || !(viewer instanceof Cesium.Viewer)) {\n throw new Error(\"Invalid Cesium Viewer instance provided.\");\n }\n this.viewer = viewer;\n this.scene = viewer.scene;\n this.entities = viewer.entities;\n\n // 根据地图模式设置偏移高度\n this.updateOffsetHeight();\n \n // 监听场景模式变化\n this.scene.morphComplete.addEventListener(() => {\n this.updateOffsetHeight();\n });\n\n // 确保启用地形深度测试以获得正确的高度\n this.scene.globe.depthTestAgainstTerrain = true;\n }\n\n /**\n * 根据场景模式更新偏移高度\n */\n private updateOffsetHeight(): void {\n if (this.scene.mode === Cesium.SceneMode.SCENE3D) {\n this.offsetHeight = 100; // 3D模式使用100米偏移,所有元素都浮动\n } else {\n this.offsetHeight = 0; // 2D模式使用0米偏移,所有元素都贴近地面\n }\n }\n\n /**\n * 手动设置偏移高度\n * @param height 偏移高度(米)\n */\n public setOffsetHeight(height: number): void {\n this.offsetHeight = height;\n }\n\n /**\n * 获取当前偏移高度\n * @returns 当前偏移高度(米)\n */\n public getOffsetHeight(): number {\n return this.offsetHeight;\n }\n\n clearFrustum(): void {\n // 清理视锥体图元\n this.frustumPrimitives.forEach((primitive) => {\n if (primitive && !primitive.isDestroyed()) {\n this.viewer.scene.primitives.remove(primitive);\n }\n });\n this.frustumPrimitives = [];\n\n // 清理视锥体专用的事件处理器\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n // 视锥体功能\n drawFrustum(options: FrustumOptions = {}): void {\n try {\n this.clearFrustum();\n\n // 参数验证\n const fov = Math.max(1, Math.min(179, options.fov || 60)); // 限制FOV范围\n const aspectRatio = Math.max(0.1, options.aspectRatio || 1.0);\n const near = Math.max(0.1, options.near || 1.0);\n const far = Math.max(near + 1, options.far || 1000.0);\n\n const position = options.position || this.viewer.camera.positionWC;\n const orientation =\n options.orientation ||\n Cesium.Quaternion.fromRotationMatrix(\n Cesium.Matrix4.getRotation(\n this.viewer.camera.transform,\n new Cesium.Matrix3()\n )\n );\n\n const frustum = new Cesium.PerspectiveFrustum({\n fov: Cesium.Math.toRadians(fov),\n aspectRatio: aspectRatio,\n near: near,\n far: far,\n });\n\n // 创建视锥体填充\n const fillGeometry = new Cesium.FrustumGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n vertexFormat: Cesium.VertexFormat.POSITION_ONLY,\n });\n\n const fillInstance = new Cesium.GeometryInstance({\n geometry: fillGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.fillColor || new Cesium.Color(1.0, 0.0, 0.0, 0.3)\n ),\n },\n });\n\n const fillPrimitive = new Cesium.Primitive({\n geometryInstances: fillInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n // 创建视锥体轮廓\n const outlineGeometry = new Cesium.FrustumOutlineGeometry({\n frustum: frustum,\n origin: position,\n orientation: orientation,\n });\n\n const outlineInstance = new Cesium.GeometryInstance({\n geometry: outlineGeometry,\n attributes: {\n color: Cesium.ColorGeometryInstanceAttribute.fromColor(\n options.outlineColor || new Cesium.Color(1.0, 1.0, 1.0, 1.0)\n ),\n },\n });\n\n const outlinePrimitive = new Cesium.Primitive({\n geometryInstances: outlineInstance,\n appearance: new Cesium.PerInstanceColorAppearance({\n closed: true,\n flat: true,\n }),\n });\n\n this.viewer.scene.primitives.add(fillPrimitive);\n this.viewer.scene.primitives.add(outlinePrimitive);\n this.frustumPrimitives.push(fillPrimitive, outlinePrimitive);\n\n // 右键点击事件\n if (options.onRightClick && this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.setInputAction((movement: any) => {\n if (movement.position && options.onRightClick) {\n options.onRightClick(position);\n }\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n }\n } catch (error) {\n console.error(\"绘制视锥体时发生错误:\", error);\n // 确保在出错时也清理资源\n this.clearFrustum();\n }\n }\n\n /**\n * 开始绘制线条\n */\n startDrawingLine(): void {\n this.startDrawing(\"line\");\n }\n\n /**\n * 开始绘制多边形(仅边线)\n */\n startDrawingPolygon(): void {\n this.startDrawing(\"polygon\");\n }\n\n /**\n * 开始绘制矩形\n */\n startDrawingRectangle(): void {\n this.startDrawing(\"rectangle\");\n }\n\n /**\n * 内部统一的开始绘制方法\n * @param mode 绘制模式\n */\n private startDrawing(mode: \"line\" | \"polygon\" | \"rectangle\"): void {\n this.endDrawingInternal(false); // 结束任何正在进行的绘制,但不清空已完成的实体\n\n this.drawMode = mode;\n this.isDrawing = true;\n this.tempPositions = [];\n this.tempEntities = [];\n\n this.activateDrawingHandlers();\n\n // 触发开始绘制回调\n if (this.onDrawStartCallback) {\n this.onDrawStartCallback();\n }\n }\n\n /**\n * 激活屏幕空间事件处理器\n */\n private activateDrawingHandlers(): void {\n this.deactivateDrawingHandlers(); // 确保之前的手柄已销毁\n\n this.screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(\n this.scene.canvas\n );\n\n // 左键点击添加点\n this.screenSpaceEventHandler.setInputAction(\n (click: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n if (this._doubleClickPending) {\n this._doubleClickPending = false;\n return;\n }\n const cartesian = this.pickGlobePosition(click.position);\n if (cartesian) {\n this.addPoint(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_CLICK\n );\n\n // 右键删除最后一个点\n this.screenSpaceEventHandler.setInputAction(() => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n this.removeLastPoint();\n }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);\n\n // 鼠标移动更新预览\n this.screenSpaceEventHandler.setInputAction(\n (move: Cesium.ScreenSpaceEventHandler.MotionEvent) => {\n if (!this.isDrawing || this.tempPositions.length === 0) return;\n const cartesian = this.pickGlobePosition(move.endPosition);\n if (cartesian) {\n this.updatePreview(cartesian);\n }\n },\n Cesium.ScreenSpaceEventType.MOUSE_MOVE\n );\n\n // 双击结束绘制\n const mapDoubleClickAct =\n this.viewer.cesiumWidget.screenSpaceEventHandler.getInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n this.screenSpaceEventHandler.setInputAction(\n (dblClick: Cesium.ScreenSpaceEventHandler.PositionedEvent) => {\n if (!this.isDrawing) return;\n this._doubleClickPending = true;\n this.finishDrawing();\n // 恢复 Cesium 默认的双击行为(如果存在的话)\n if (mapDoubleClickAct) {\n this.viewer.cesiumWidget.screenSpaceEventHandler.setInputAction(\n mapDoubleClickAct,\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n },\n Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK\n );\n }\n\n /**\n * 拾取地形或椭球体上的位置\n * @param windowPosition 屏幕坐标\n * @returns 世界坐标 Cartesian3 或 null\n */\n private pickGlobePosition(\n windowPosition: Cesium.Cartesian2\n ): Cesium.Cartesian3 | null {\n // 首先尝试从地形拾取\n const ray = this.viewer.camera.getPickRay(windowPosition);\n if (ray) {\n const position = this.scene.globe.pick(ray, this.scene);\n if (Cesium.defined(position)) {\n return position;\n }\n }\n // 如果地形拾取失败,回退到椭球体拾取\n const ellipsoidPosition = this.viewer.camera.pickEllipsoid(\n windowPosition,\n this.scene.globe.ellipsoid\n );\n return ellipsoidPosition ?? null;\n }\n\n /**\n * 添加一个点到临时位置数组并创建点实体\n * @param position 世界坐标\n */\n private addPoint(position: Cesium.Cartesian3): void {\n this.tempPositions.push(position.clone());\n\n // 根据2D/3D模式设置点的高度\n const carto = Cesium.Cartographic.fromCartesian(position);\n const elevatedPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + (this.drawMode !== \"line\" ? 0 : this.offsetHeight)\n );\n\n const pointEntity = this.entities.add({\n position: elevatedPosition,\n point: {\n pixelSize: 8,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 3,\n heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,\n scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),\n },\n });\n this.tempEntities.push(pointEntity);\n this.updateDrawingEntity();\n }\n\n /**\n * 删除最后一个添加的点及其相关的临时实体\n */\n private removeLastPoint(): void {\n if (this.tempPositions.length > 0) {\n // 移除最后一个位置\n this.tempPositions.pop();\n\n // 移除所有临时实体(包括点实体和线/面实体)\n this.tempEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n\n // 移除所有临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n\n // 重新创建剩余的点实体和绘制实体\n this.recreateRemainingEntities();\n }\n }\n\n /**\n * 重新创建剩余的点实体和绘制实体\n * 用于右键删除点后的重建\n */\n private recreateRemainingEntities(): void {\n // 重新创建所有剩余的点实体\n this.tempPositions.forEach((position) => {\n const carto = Cesium.Cartographic.fromCartesian(position);\n const elevatedPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n\n const pointEntity = this.entities.add({\n position: elevatedPosition,\n point: {\n pixelSize: 8,\n color: Cesium.Color.RED,\n outlineColor: Cesium.Color.WHITE,\n outlineWidth: 3,\n heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,\n scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.0, 1.5e7, 0.5),\n },\n });\n this.tempEntities.push(pointEntity);\n });\n\n // 重新创建绘制实体(线/面)\n this.updateDrawingEntity();\n }\n\n /**\n * 更新预览线/面\n * @param currentMousePosition 当前鼠标位置世界坐标\n */\n private updatePreview(currentMousePosition: Cesium.Cartesian3): void {\n this.updateDrawingEntity(currentMousePosition);\n }\n\n /**\n * 核心方法:根据当前点序列更新或创建临时的线/面实体\n * @param previewPoint 可选的预览点,用于显示动态效果\n */\n private updateDrawingEntity(previewPoint?: Cesium.Cartesian3): void {\n // 移除旧的活动实体(只移除线和面,保留点实体)\n const entitiesToRemove: Cesium.Entity[] = [];\n this.tempEntities.forEach((entity) => {\n if (entity && (entity.polyline || entity.polygon || entity.rectangle)) {\n entitiesToRemove.push(entity);\n }\n });\n \n // 移除线/面实体\n entitiesToRemove.forEach((entity) => {\n this.entities.remove(entity);\n const index = this.tempEntities.indexOf(entity);\n if (index > -1) {\n this.tempEntities.splice(index, 1);\n }\n });\n \n // 移除旧的临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n const positions = [...this.tempPositions];\n if (previewPoint) {\n positions.push(previewPoint);\n }\n\n if (positions.length < 2) return;\n\n let activeEntity: Cesium.Entity | undefined;\n\n if (this.drawMode === \"line\") {\n // 根据2D/3D模式创建线条\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n activeEntity = this.entities.add({\n polyline: {\n positions: elevatedPositions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: false,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n polyline: {\n positions: positions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n }\n this.tempEntities.push(activeEntity);\n\n // 为每一段添加距离标签(只显示距离大于1米的标签)\n for (let i = 0; i < positions.length - 1; i++) {\n const startPos = positions[i];\n const endPos = positions[i + 1];\n const distance = Cesium.Cartesian3.distance(startPos, endPos);\n \n // 只显示距离大于5米的标签,避免显示过小的距离\n if (distance > 5.0) {\n const midPoint = Cesium.Cartesian3.midpoint(\n startPos,\n endPos,\n new Cesium.Cartesian3()\n );\n // 计算标签位置,避免重叠\n const labelOffset = i % 2 === 0 ? -25 : 25; // 交替显示在线的上方和下方\n const labelEntity = this.entities.add({\n position: midPoint,\n label: {\n text: `${distance.toFixed(2)} m`,\n font: \"16px Arial\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 3,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, labelOffset),\n heightReference: this.offsetHeight > 0 ? Cesium.HeightReference.RELATIVE_TO_GROUND : Cesium.HeightReference.CLAMP_TO_GROUND,\n scale: 1.0,\n showBackground: true,\n backgroundColor: Cesium.Color.BLACK.withAlpha(0.8),\n backgroundPadding: new Cesium.Cartesian2(6, 3),\n },\n });\n this.tempLabelEntities.push(labelEntity);\n }\n }\n\n // 添加总距离标签(在最后一个点)\n if (positions.length > 1) {\n let totalDistance = 0;\n for (let i = 1; i < positions.length; i++) {\n totalDistance += Cesium.Cartesian3.distance(\n positions[i - 1],\n positions[i]\n );\n }\n // 根据offsetHeight计算标签位置,与line的绘制方式保持一致\n let labelPosition = positions[positions.length - 1];\n if (this.offsetHeight > 0) {\n // 3D模式:抬高标签位置\n const carto = Cesium.Cartographic.fromCartesian(labelPosition);\n labelPosition = Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n }\n \n const totalLabelEntity = this.entities.add({\n position: labelPosition,\n label: {\n text: `总长: ${totalDistance.toFixed(2)} m`,\n font: \"18px Arial\",\n fillColor: Cesium.Color.YELLOW,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 3,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, 40),\n heightReference: this.offsetHeight > 0 ? Cesium.HeightReference.NONE : Cesium.HeightReference.CLAMP_TO_GROUND,\n scale: 1.0,\n showBackground: true,\n backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),\n backgroundPadding: new Cesium.Cartesian2(8, 4),\n },\n });\n this.tempLabelEntities.push(totalLabelEntity);\n }\n } else if (this.drawMode === \"polygon\") {\n // 根据2D/3D模式绘制多边形区域\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(elevatedPositions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.NONE,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n polygon: {\n hierarchy: new Cesium.CallbackProperty(() => {\n return new Cesium.PolygonHierarchy(positions);\n }, false),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n if (this.offsetHeight > 0) {\n // 3D模式:使用挤压高度\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.NONE,\n extrudedHeight: this.offsetHeight,\n },\n });\n } else {\n // 2D模式:贴近地面\n activeEntity = this.entities.add({\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n }\n\n if (activeEntity) {\n this.tempEntities.push(activeEntity);\n }\n }\n\n /**\n * 完成当前绘制操作\n */\n private finishDrawing(): void {\n if (this.tempPositions.length < (this.drawMode === \"rectangle\" ? 2 : 2)) {\n // 点数不足,取消绘制\n this.endDrawingInternal(true);\n return;\n }\n let finalEntity: Cesium.Entity | null = null;\n const positions = this.tempPositions.map((p) => p.clone());\n\n if (this.drawMode === \"line\") {\n // 根据2D/3D模式创建最终线条\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: elevatedPositions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: false,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的线\",\n polyline: {\n positions: positions,\n width: 5,\n material: Cesium.Color.YELLOW,\n clampToGround: true,\n },\n });\n }\n\n // 标签已经在 updateDrawingEntity 中创建,这里不需要重复创建\n } else if (this.drawMode === \"polygon\") {\n // 根据2D/3D模式绘制最终多边形区域\n if (this.offsetHeight > 0) {\n // 3D模式:使用抬高的位置\n const elevatedPositions = positions.map(pos => {\n const carto = Cesium.Cartographic.fromCartesian(pos);\n return Cesium.Cartesian3.fromRadians(\n carto.longitude,\n carto.latitude,\n (carto.height || 0) + this.offsetHeight\n );\n });\n \n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(elevatedPositions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.NONE,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的多边形区域\",\n polygon: {\n hierarchy: new Cesium.PolygonHierarchy(positions),\n material: Cesium.Color.LIGHTGREEN.withAlpha(0.3), // 淡绿色填充\n outline: true,\n outlineColor: Cesium.Color.GREEN,\n outlineWidth: 2,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n // 添加面积标签\n const area = this.calculatePolygonArea(positions);\n if (area > 0) {\n const center = this.calculatePolygonCenter(positions);\n const areaLabelEntity = this.entities.add({\n position: center,\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.finishedLabelEntities.push(areaLabelEntity);\n }\n } else if (this.drawMode === \"rectangle\" && positions.length >= 2) {\n const rect = this.calculateRectangle(positions[0], positions[1]);\n if (this.offsetHeight > 0) {\n // 3D模式:使用挤压高度\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.NONE,\n extrudedHeight: this.offsetHeight,\n },\n });\n } else {\n // 2D模式:贴近地面\n finalEntity = this.entities.add({\n name: \"绘制的矩形\",\n rectangle: {\n coordinates: rect,\n material: Cesium.Color.GREEN.withAlpha(0.5),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n }\n // 添加面积标签\n const area = this.calculateRectangleArea(rect);\n if (area > 0) {\n const rectCenter = Cesium.Rectangle.center(rect);\n const rectAreaLabelEntity = this.entities.add({\n position: Cesium.Cartesian3.fromRadians(\n rectCenter.longitude,\n rectCenter.latitude\n ),\n label: {\n text: `面积: ${area.toFixed(2)} km²`,\n font: \"14px sans-serif\",\n fillColor: Cesium.Color.WHITE,\n outlineColor: Cesium.Color.BLACK,\n outlineWidth: 2,\n style: Cesium.LabelStyle.FILL_AND_OUTLINE,\n pixelOffset: new Cesium.Cartesian2(0, -20),\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n this.finishedLabelEntities.push(rectAreaLabelEntity);\n }\n }\n\n // 将完成的实体存入列表\n if (finalEntity) {\n this.finishedEntities.push(finalEntity);\n }\n\n // 将临时标签实体转移到已完成标签实体数组中\n this.tempLabelEntities.forEach((entity) => {\n this.finishedLabelEntities.push(entity);\n });\n this.tempLabelEntities = [];\n\n // 将临时点实体转移到已完成点实体数组中\n this.tempEntities.forEach((entity) => {\n if (entity && entity.point) {\n this.finishedPointEntities.push(entity);\n } else {\n // 非点实体直接移除\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n this.tempPositions = [];\n\n if (true) { // resetMode\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n\n // 触发结束绘制回调\n if (this.onDrawEndCallback) {\n this.onDrawEndCallback(finalEntity);\n }\n }\n\n /**\n * 内部方法:重置绘图状态和清理临时数据\n * @param resetMode 是否重置绘图模式和状态标志\n */\n private endDrawingInternal(resetMode: boolean): void {\n // 清理临时实体\n this.tempEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempEntities = [];\n this.tempPositions = [];\n // 清理临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.tempLabelEntities = [];\n\n if (resetMode) {\n this.drawMode = null;\n this.isDrawing = false;\n this.deactivateDrawingHandlers();\n }\n }\n\n /**\n * 公共方法:结束当前绘制(如果正在进行)\n */\n endDrawing(): void {\n if (this.isDrawing) {\n this.finishDrawing();\n } else {\n // 如果没有在绘制,也执行一次清理\n this.endDrawingInternal(true);\n }\n }\n\n /**\n * 销毁事件处理器\n */\n private deactivateDrawingHandlers(): void {\n if (this.screenSpaceEventHandler) {\n this.screenSpaceEventHandler.destroy();\n this.screenSpaceEventHandler = null;\n }\n }\n\n /**\n * 清除所有已绘制的实体\n */\n clearAll(): void {\n // 先结束可能的绘制\n this.endDrawing();\n \n // 强制清除所有点实体\n this.clearAllPoints();\n \n // 清除所有已完成的实体\n this.finishedEntities.forEach((entity) => {\n this.entities.remove(entity);\n });\n this.finishedEntities = [];\n \n // 清除所有已完成的标签实体\n this.finishedLabelEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.finishedLabelEntities = [];\n \n // 清除所有通过公共方法创建的实体\n this.publicEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.publicEntities = [];\n \n // 清理临时实体(包括绘制过程中的点实体)\n this.tempEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.tempEntities = [];\n \n // 清理临时标签实体\n this.tempLabelEntities.forEach((entity) => {\n if (entity && entity.label) {\n this.entities.remove(entity);\n }\n });\n this.tempLabelEntities = [];\n \n // 确保清理所有可能残留的实体\n this.tempPositions = [];\n }\n\n /**\n * 清除所有实体(包括未跟踪的实体)\n * 这是一个更彻底的清理方法,会清除场景中的所有实体\n */\n clearAllEntities(): void {\n // 先结束可能的绘制\n this.endDrawing();\n // 清除场景中的所有实体\n this.entities.removeAll();\n // 重置所有跟踪数组\n this.finishedEntities = [];\n this.finishedLabelEntities = [];\n this.finishedPointEntities = [];\n this.publicEntities = [];\n this.tempEntities = [];\n this.tempLabelEntities = [];\n this.tempPositions = [];\n }\n\n /**\n * 强制清除所有点实体\n * 用于解决点实体无法删除的问题\n */\n clearAllPoints(): void {\n // 清除所有已完成的点实体\n this.finishedPointEntities.forEach((entity) => {\n if (entity) {\n this.entities.remove(entity);\n }\n });\n this.finishedPointEntities = [];\n \n // 清除临时点实体\n this.tempEntities.forEach((entity) => {\n if (entity && entity.point) {\n this.entities.remove(entity);\n }\n });\n \n // 清除所有可能的点实体(通过实体名称查找)\n const allEntities = this.entities.values;\n for (let i = allEntities.length - 1; i >= 0; i--) {\n const entity = allEntities[i];\n if (entity && entity.point) {\n this.entities.remove(entity);\n }\n }\n }\n\n /**\n * 删除一个指定的已完成实体\n * @param entity 要删除的实体\n */\n removeEntity(entity: Cesium.Entity): void {\n const index = this.finishedEntities.indexOf(entity);\n if (index > -1) {\n this.entities.remove(entity);\n this.finishedEntities.splice(index, 1);\n if (this.onEntityRemovedCallback) {\n this.onEntityRemovedCallback(entity);\n }\n }\n }\n\n /**\n * 获取所有已完成的实体\n * @returns 实体数组\n */\n getFinishedEntities(): Cesium.Entity[] {\n return [...this.finishedEntities];\n }\n\n // --- 辅助计算函数 ---\n private calculateRectangle(\n p1: Cesium.Cartesian3,\n p2: Cesium.Cartesian3\n ): Cesium.Rectangle {\n const cartographic1 = Cesium.Cartographic.fromCartesian(p1);\n const cartographic2 = Cesium.Cartographic.fromCartesian(p2);\n const west = Math.min(cartographic1.longitude, cartographic2.longitude);\n const east = Math.max(cartographic1.longitude, cartographic2.longitude);\n const south = Math.min(cartographic1.latitude, cartographic2.latitude);\n const north = Math.max(cartographic1.latitude, cartographic2.latitude);\n return new Cesium.Rectangle(west, south, east, north);\n }\n\n private calculateRectangleArea(rect: Cesium.Rectangle): number {\n const west = rect.west;\n const south = rect.south;\n const east = rect.east;\n const north = rect.north;\n\n const width = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(east, south)\n );\n const height = Cesium.Cartesian3.distance(\n Cesium.Cartesian3.fromRadians(west, south),\n Cesium.Cartesian3.fromRadians(west, north)\n );\n\n return (width * height) / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonArea(positions: Cesium.Cartesian3[]): number {\n if (positions.length < 3) return 0;\n const ellipsoid = this.scene.globe.ellipsoid;\n let area = 0;\n const len = positions.length;\n for (let i = 0; i < len; i++) {\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\n area +=\n (p2.longitude - p1.longitude) *\n (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\n }\n area = Math.abs((area * 6378137.0 * 6378137.0) / 2.0); // WGS84半径\n return area / 1e6; // 转换为平方公里\n }\n\n private calculatePolygonCenter(\n positions: Cesium.Cartesian3[]\n ): Cesium.Cartesian3 {\n if (positions.length === 0) return Cesium.Cartesian3.ZERO;\n let x = 0,\n y = 0,\n z = 0;\n for (let i = 0; i < positions.length; i++) {\n x += positions[i].x;\n y += positions[i].y;\n z += positions[i].z;\n }\n return new Cesium.Cartesian3(\n x / positions.length,\n y / positions.length,\n z / positions.length\n );\n }\n\n // --- 回调注册 ---\n\n /**\n * 设置开始绘制时的回调函数\n * @param callback 回调函数\n */\n onDrawStart(callback: () => void): void {\n this.onDrawStartCallback = callback;\n }\n\n /**\n * 设置结束绘制时的回调函数\n * @param callback 回调函数,参数为完成的实体或null\n */\n onDrawEnd(callback: (entity: Cesium.Entity | null) => void): void {\n this.onDrawEndCallback = callback;\n }\n\n /**\n * 设置实体被移除时的回调函数\n * @param callback 回调函数,参数为被移除的实体\n */\n onEntityRemoved(callback: (entity: Cesium.Entity) => void): void {\n this.onEntityRemovedCallback = callback;\n }\n\n /**\n * 绘制监控圆形区域\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param radius 监控范围半径(米)\n * @param options 可选配置\n */\n public drawMonitoringCircle(\n longitude: number,\n latitude: number,\n height: number,\n radius: number,\n options?: {\n borderColor?: string;\n fillColor?: string;\n borderWidth?: number;\n name?: string;\n }\n ): Cesium.Entity {\n const borderColor = options?.borderColor || \"#0062FF\";\n const fillColor = options?.fillColor || \"#0062FF\";\n const borderWidth = options?.borderWidth || 2;\n const name = options?.name || \"监控区域\";\n\n // 创建圆形区域\n const entity = this.entities.add({\n name: name,\n position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),\n ellipse: {\n semiMajorAxis: radius,\n semiMinorAxis: radius,\n material: Cesium.Color.fromCssColorString(fillColor).withAlpha(0.27),\n outline: true,\n outlineColor: Cesium.Color.fromCssColorString(borderColor),\n outlineWidth: borderWidth,\n heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,\n },\n });\n\n // 将实体添加到跟踪数组中\n this.publicEntities.push(entity);\n\n return entity;\n }\n\n /**\n * 绘制垂直线条\n * @param longitude 经度\n * @param latitude 纬度\n * @param height 高度\n * @param options 可选配置\n */\n public drawVerticalLine(\n longitude: number,\n latitude: number,\n height: number,\n options?: {\n color?: string;\n width?: number;\n dashPattern?: number;\n name?: string;\n groundHeight?: number;\n }\n ): Cesium.Entity {\n const color = options?.color || \"#0062FF\";\n const width = options?.width || 2;\n const dashPattern = options?.dashPattern || 0x00ff00ff;\n const name = options?.name || \"垂直线条\";\n const groundHeight = options?.groundHeight || 0;\n\n // 计算地面位置\n const groundPosition = Cesium.Cartesian3.fromDegrees(\n longitude,\n latitude,\n groundHeight\n );\n const topPosition = Cesium.Cartesian3.fromDegrees(\n longitude,\n latitude,\n height\n );\n\n // 创建垂直线条\n const entity = this.entities.add({\n name: name,\n polyline: {\n positions: [groundPosition, topPosition],\n width: width,\n material: new Cesium.PolylineDashMaterialProperty({\n color: Cesium.Color.fromCssColorString(color),\n }),\n clampToGround: false,\n },\n });\n\n // 将实体添加到跟踪数组中\n this.publicEntities.push(entity);\n\n return entity;\n }\n\n /**\n * 销毁工具,清理所有事件监听器\n */\n destroy(): void {\n this.deactivateDrawingHandlers();\n this.clearFrustum(); // 清理视锥体相关资源\n // 可以选择不清除实体,由用户决定\n // this.clearAll();\n }\n}\n\n// 为了在 HTML 中通过 <script type=\"module\"> 或打包工具使用\n// @ts-ignore\nwindow.DrawHelper = DrawHelper;\n\nexport default DrawHelper;\n","import * as Cesium from 'cesium';\r\nimport type { Viewer, Cartesian3, Cartographic } from 'cesium';\r\nimport DrawHelper from './CesiumMapHelper';\r\n\r\n// 工具栏配置接口\r\nexport interface ToolbarConfig {\r\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';\r\n buttonSize?: number;\r\n buttonSpacing?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderRadius?: number;\r\n borderWidth?: number;\r\n boxShadow?: string;\r\n zIndex?: number;\r\n buttons?: CustomButtonConfig[];\r\n}\r\n\r\n// 按钮配置接口\r\nexport interface ButtonConfig {\r\n id: string;\r\n icon: string;\r\n title: string;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n}\r\n\r\n// 自定义按钮配置接口\r\nexport interface CustomButtonConfig {\r\n id: string;\r\n icon: string | HTMLElement;\r\n title: string;\r\n enabled?: boolean;\r\n visible?: boolean;\r\n size?: number;\r\n color?: string;\r\n hoverColor?: string;\r\n activeColor?: string;\r\n onClick?: (buttonId: string, buttonElement: HTMLElement) => void;\r\n}\r\n\r\n// 搜索回调接口\r\nexport interface SearchCallback {\r\n onSearch?: (query: string) => Promise<SearchResult[]>;\r\n onSelect?: (result: SearchResult) => void;\r\n onSearchInput?: (query: string, container: HTMLElement) => void;\r\n onSearchResults?: (results: SearchResult[], container: HTMLElement) => void;\r\n}\r\n\r\n// 搜索结果接口\r\nexport interface SearchResult {\r\n name: string;\r\n address: string;\r\n longitude: number;\r\n latitude: number;\r\n height?: number;\r\n}\r\n\r\n// 测量回调接口\r\nexport interface MeasurementCallback {\r\n onDistanceComplete?: (positions: Cartesian3[], distance: number) => void;\r\n onAreaComplete?: (positions: Cartesian3[], area: number) => void;\r\n onClear?: () => void;\r\n}\r\n\r\n// 缩放回调接口\r\nexport interface ZoomCallback {\r\n onZoomIn?: (beforeLevel: number, afterLevel: number) => void;\r\n onZoomOut?: (beforeLevel: number, afterLevel: number) => void;\r\n}\r\n\r\n// 地图类型接口\r\nexport interface MapType {\r\n id: string;\r\n name: string;\r\n thumbnail: string;\r\n provider: Cesium.ImageryProvider;\r\n}\r\n\r\n/**\r\n * Cesium地图工具栏类\r\n * 提供搜索、测量、2D/3D切换、图层切换、定位、缩放、全屏等功能\r\n */\r\nexport class CesiumMapToolbar {\r\n private viewer: Viewer;\r\n private drawHelper: DrawHelper;\r\n private container: HTMLElement;\r\n private toolbarElement!: HTMLElement;\r\n private config: ToolbarConfig;\r\n private searchCallback?: SearchCallback;\r\n private measurementCallback?: MeasurementCallback;\r\n private zoomCallback?: ZoomCallback;\r\n private initialCenter?: { longitude: number; latitude: number; height: number };\r\n private isFullscreen: boolean = false;\r\n private currentMapType: string = 'imagery';\r\n\r\n // 地图类型配置\r\n private mapTypes: MapType[] = [\r\n {\r\n id: 'normal',\r\n name: '天地图-普通',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: '3d',\r\n name: '天地图-三维',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'imagery',\r\n name: '天地图-影像',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n },\r\n {\r\n id: 'terrain',\r\n name: '天地图-地形',\r\n thumbnail: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHZpZXdCb3g9IjAgMCA0MCA0MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQwIiBoZWlnaHQ9IjQwIiBmaWxsPSIjZjBmMGYwIi8+CjxwYXRoIGQ9Ik0xMCAxMEgzMFYzMEgxMFYxMFoiIGZpbGw9IiNlMGUwZTAiLz4KPC9zdmc+',\r\n provider: new Cesium.UrlTemplateImageryProvider({\r\n url: 'https://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=your_token',\r\n subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],\r\n minimumLevel: 1,\r\n maximumLevel: 18,\r\n credit: '© 天地图'\r\n })\r\n }\r\n ];\r\n\r\n constructor(\r\n viewer: Viewer,\r\n container: HTMLElement,\r\n config: ToolbarConfig = {},\r\n callbacks?: {\r\n search?: SearchCallback;\r\n measurement?: MeasurementCallback;\r\n zoom?: ZoomCallback;\r\n },\r\n initialCenter?: { longitude: number; latitude: number; height: number }\r\n ) {\r\n this.viewer = viewer;\r\n this.container = container;\r\n this.config = {\r\n position: 'bottom-right',\r\n buttonSize: 40,\r\n buttonSpacing: 8,\r\n backgroundColor: 'rgba(255, 255, 255, 0.9)',\r\n borderColor: '#e0e0e0',\r\n borderRadius: 6,\r\n boxShadow: '0 2px 10px rgba(0, 0, 0, 0.1)',\r\n zIndex: 1000,\r\n ...config\r\n };\r\n this.searchCallback = callbacks?.search;\r\n this.measurementCallback = callbacks?.measurement;\r\n this.zoomCallback = callbacks?.zoom;\r\n\r\n // 设置初始中心点\r\n this.initialCenter = initialCenter;\r\n\r\n // 初始化绘图助手\r\n this.drawHelper = new DrawHelper(viewer);\r\n this.setupDrawHelperCallbacks();\r\n\r\n // 创建工具栏\r\n this.createToolbar();\r\n }\r\n\r\n /**\r\n * 设置初始中心点\r\n */\r\n public setInitialCenter(center: { longitude: number; latitude: number; height: number }): void {\r\n this.initialCenter = center;\r\n }\r\n\r\n /**\r\n * 获取初始中心点\r\n */\r\n public getInitialCenter(): { longitude: number; latitude: number; height: number } | undefined {\r\n return this.initialCenter;\r\n }\r\n\r\n /**\r\n * 复位到初始位置(公共方法)\r\n */\r\n public resetToInitialLocation(): void {\r\n this.resetLocation();\r\n }\r\n\r\n /**\r\n * 更新按钮配置\r\n */\r\n public updateButtonConfig(buttonId: string, config: Partial<CustomButtonConfig>): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (!button) return;\r\n\r\n // 更新按钮属性\r\n if (config.title) button.title = config.title;\r\n if (config.icon) this.setButtonIcon(button, config.icon);\r\n if (config.size) {\r\n button.style.width = `${config.size}px`;\r\n button.style.height = `${config.size}px`;\r\n }\r\n if (config.color) button.style.background = config.color;\r\n }\r\n\r\n /**\r\n * 添加自定义按钮\r\n */\r\n public addCustomButton(config: CustomButtonConfig): void {\r\n const buttonConfig: ButtonConfig = {\r\n id: config.id,\r\n icon: typeof config.icon === 'string' ? config.icon : '',\r\n title: config.title,\r\n size: config.size,\r\n color: config.color,\r\n hoverColor: config.hoverColor,\r\n activeColor: config.activeColor\r\n };\r\n\r\n const buttonElement = this.createButton(buttonConfig);\r\n this.toolbarElement.appendChild(buttonElement);\r\n\r\n // 更新配置\r\n if (!this.config.buttons) {\r\n this.config.buttons = [];\r\n }\r\n this.config.buttons.push(config);\r\n }\r\n\r\n /**\r\n * 移除按钮\r\n */\r\n public removeButton(buttonId: string): void {\r\n const button = this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n if (button && button.parentNode) {\r\n button.parentNode.removeChild(button);\r\n }\r\n\r\n // 从配置中移除\r\n if (this.config.buttons) {\r\n this.config.buttons = this.config.buttons.filter(btn => btn.id !== buttonId);\r\n }\r\n }\r\n\r\n /**\r\n * 获取按钮元素\r\n */\r\n public getButtonElement(buttonId: string): HTMLElement | null {\r\n return this.toolbarElement.querySelector(`[data-tool=\"${buttonId}\"]`) as HTMLElement;\r\n }\r\n\r\n /**\r\n * 设置绘图助手回调\r\n */\r\n private setupDrawHelperCallbacks(): void {\r\n this.drawHelper.onDrawStart(() => {\r\n console.log('开始绘制');\r\n });\r\n\r\n this.drawHelper.onDrawEnd((entity) => {\r\n if (entity) {\r\n console.log('绘制完成', entity);\r\n // 根据绘制类型触发相应回调\r\n if (entity.polyline) {\r\n // 测距完成\r\n const positions = entity.polyline.positions?.getValue(Cesium.JulianDate.now()) as Cartesian3[];\r\n if (positions && this.measurementCallback?.onDistanceComplete) {\r\n let totalDistance = 0;\r\n for (let i = 1; i < positions.length; i++) {\r\n totalDistance += Cesium.Cartesian3.distance(positions[i-1], positions[i]);\r\n }\r\n this.measurementCallback.onDistanceComplete(positions, totalDistance);\r\n }\r\n } else if (entity.polygon) {\r\n // 测面积完成\r\n const positions = entity.polygon.hierarchy?.getValue(Cesium.JulianDate.now()) as Cesium.PolygonHierarchy;\r\n if (positions && this.measurementCallback?.onAreaComplete) {\r\n // 计算面积\r\n const area = this.calculatePolygonArea(positions.positions);\r\n this.measurementCallback.onAreaComplete(positions.positions, area);\r\n }\r\n }\r\n }\r\n });\r\n\r\n this.drawHelper.onEntityRemoved((entity) => {\r\n console.log('实体被移除', entity);\r\n });\r\n }\r\n\r\n /**\r\n * 计算多边形面积\r\n */\r\n private calculatePolygonArea(positions: Cartesian3[]): number {\r\n if (positions.length < 3) return 0;\r\n \r\n const ellipsoid = this.viewer.scene.globe.ellipsoid;\r\n let area = 0;\r\n const len = positions.length;\r\n \r\n for (let i = 0; i < len; i++) {\r\n const p1 = ellipsoid.cartesianToCartographic(positions[i]);\r\n const p2 = ellipsoid.cartesianToCartographic(positions[(i + 1) % len]);\r\n area += (p2.longitude - p1.longitude) * (2 + Math.sin(p1.latitude) + Math.sin(p2.latitude));\r\n }\r\n \r\n area = Math.abs(area * 6378137.0 * 6378137.0 / 2.0);\r\n return area / 1e6; // 转换为平方公里\r\n }\r\n\r\n /**\r\n * 创建工具栏\r\n */\r\n private createToolbar(): void {\r\n this.toolbarElement = document.createElement('div');\r\n this.toolbarElement.className = 'cesium-map-toolbar';\r\n this.toolbarElement.style.cssText = `\r\n position: absolute;\r\n ${this.config.position?.includes('right') ? 'right' : 'left'}: 10px;\r\n ${this.config.position?.includes('bottom') ? 'bottom' : 'top'}: 10px;\r\n background: ${this.config.backgroundColor};\r\n border: ${this.config.borderWidth}px solid ${this.config.borderColor};\r\n border-radius: ${this.config.borderRadius}px;\r\n box-shadow: ${this.config.boxShadow};\r\n padding: 8px;\r\n z-index: ${this.config.zIndex};\r\n display: flex;\r\n flex-direction: column;\r\n gap: ${this.config.buttonSpacing}px;\r\n `;\r\n\r\n // 获取按钮配置\r\n const buttons = this.getButtonConfigs();\r\n\r\n buttons.forEach(button => {\r\n const buttonElement = this.createButton(button);\r\n this.toolbarElement.appendChild(buttonElement);\r\n });\r\n\r\n this.container.appendChild(this.toolbarElement);\r\n }\r\n\r\n /**\r\n * 获取按钮配置\r\n */\r\n private getButtonConfigs(): ButtonConfig[] {\r\n // 默认按钮配置\r\n const defaultButtons: ButtonConfig[] = [\r\n { id: 'search', icon: '🔍', title: '搜索' },\r\n { id: 'measure', icon: '📏', title: '测量' },\r\n { id: 'view2d3d', icon: '2D', title: '2D或3D' },\r\n { id: 'layers', icon: '📚', title: '图层切换' },\r\n { id: 'location', icon: '🎯', title: '定位' },\r\n { id: 'zoom-in', icon: '🔍+', title: '放大' },\r\n { id: 'zoom-out', icon: '🔍-', title: '缩小' },\r\n { id: 'fullscreen', icon: '⛶', title: '全屏' }\r\n ];\r\n\r\n // 如果用户提供了自定义按钮配置,则使用自定义配置\r\n if (this.config.buttons && this.config.buttons.length > 0) {\r\n return this.config.buttons.map(customButton => ({\r\n id: customButton.id,\r\n icon: typeof customButton.icon === 'string' ? customButton.icon : '',\r\n title: customButton.title,\r\n size: customButton.size,\r\n color: customButton.color,\r\n hoverColor: customButton.hoverColor,\r\n activeColor: customButton.activeColor\r\n }));\r\n }\r\n\r\n return defaultButtons;\r\n }\r\n\r\n /**\r\n * 创建按钮\r\n */\r\n private createButton(config: ButtonConfig): HTMLElement {\r\n const button = document.createElement('div');\r\n button.className = 'cesium-toolbar-button';\r\n button.setAttribute('data-tool', config.id);\r\n button.title = config.title;\r\n \r\n const buttonSize = config.size || this.config.buttonSize;\r\n const buttonColor = config.color || 'rgba(66, 133, 244, 0.4)';\r\n const buttonHoverColor = config.hoverColor || 'rgba(51, 103, 214, 0.9)';\r\n \r\n button.style.cssText = `\r\n width: ${buttonSize}px;\r\n height: ${buttonSize}px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: ${buttonColor};\r\n color: white;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: bold;\r\n transition: all 0.2s ease;\r\n user-select: none;\r\n position: relative;\r\n `;\r\n\r\n // 设置图标内容\r\n this.setButtonIcon(button, config.icon);\r\n\r\n // 悬停效果\r\n button.addEventListener('mouseenter', () => {\r\n button.style.background = buttonHoverColor;\r\n button.style.transform = 'scale(1.05)';\r\n });\r\n\r\n button.addEventListener('mouseleave', () => {\r\n button.style.background = buttonColor;\r\n button.style.transform = 'scale(1)';\r\n });\r\n\r\n // 处理点击事件\r\n this.setupButtonEvents(button, config);\r\n\r\n return button;\r\n }\r\n\r\n /**\r\n * 设置按钮图标\r\n */\r\n private setButtonIcon(button: HTMLElement, icon: string | HTMLElement): void {\r\n if (typeof icon === 'string') {\r\n button.innerHTML = icon;\r\n } else if (icon instanceof HTMLElement) {\r\n button.innerHTML = '';\r\n button.appendChild(icon);\r\n }\r\n }\r\n\r\n /**\r\n * 设置按钮事件\r\n */\r\n private setupButtonEvents(button: HTMLElement, config: ButtonConfig): void {\r\n // 查找自定义按钮配置\r\n const customButton = this.config.buttons?.find(btn => btn.id === config.id);\r\n \r\n if (customButton?.onClick) {\r\n // 自定义按钮点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n customButton.onClick!(config.id, button);\r\n });\r\n } else if (!['search', 'measure', 'layers'].includes(config.id)) {\r\n // 默认按钮点击事件(除了搜索、测量、图层切换按钮)\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else if (config.id === 'search') {\r\n // 搜索按钮使用点击事件\r\n button.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.handleButtonClick(config.id, button);\r\n });\r\n } else {\r\n // 测量、图层切换按钮使用hover事件\r\n button.addEventListener('mouseenter', () => {\r\n this.handleButtonClick(config.id, button);\r\n });\r\n \r\n // 添加鼠标离开事件来关闭菜单\r\n button.addEventListener('mouseleave', () => {\r\n this.closeMenuOnButtonLeave(config.id);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 按钮鼠标离开时关闭菜单\r\n */\r\n private closeMenuOnButtonLeave(buttonId: string): void {\r\n // 延迟关闭,给用户时间移动到菜单上\r\n setTimeout(() => {\r\n switch (buttonId) {\r\n case 'measure':\r\n const measureMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (measureMenu && !measureMenu.matches(':hover')) {\r\n measureMenu.remove();\r\n }\r\n break;\r\n case 'layers':\r\n const layersMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (layersMenu && !layersMenu.matches(':hover')) {\r\n layersMenu.remove();\r\n }\r\n break;\r\n }\r\n }, 100); // 100ms延迟,给用户时间移动到菜单\r\n }\r\n\r\n /**\r\n * 处理按钮点击\r\n */\r\n private handleButtonClick(buttonId: string, buttonElement: HTMLElement): void {\r\n switch (buttonId) {\r\n case 'search':\r\n this.toggleSearch(buttonElement);\r\n break;\r\n case 'measure':\r\n this.toggleMeasurement(buttonElement);\r\n break;\r\n case 'view2d3d':\r\n this.toggle2D3D(buttonElement);\r\n break;\r\n case 'layers':\r\n this.toggleLayers(buttonElement);\r\n break;\r\n case 'location':\r\n this.resetLocation();\r\n break;\r\n case 'zoom-in':\r\n this.zoomIn();\r\n break;\r\n case 'zoom-out':\r\n this.zoomOut();\r\n break;\r\n case 'fullscreen':\r\n this.toggleFullscreen();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换搜索功能\r\n */\r\n private toggleSearch(buttonElement: HTMLElement): void {\r\n const existingSearch = this.toolbarElement.querySelector('.search-container');\r\n if (existingSearch) {\r\n // 如果搜索框已存在,关闭它\r\n existingSearch.remove();\r\n return;\r\n }\r\n\r\n const searchContainer = document.createElement('div');\r\n searchContainer.className = 'search-container';\r\n searchContainer.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 8px;\r\n min-width: 200px;\r\n z-index: 1001;\r\n `;\r\n\r\n const searchInput = document.createElement('input');\r\n searchInput.type = 'text';\r\n searchInput.placeholder = '请输入地址';\r\n searchInput.style.cssText = `\r\n padding: 6px 8px;\r\n border: 1px solid #ddd;\r\n border-radius: 3px;\r\n font-size: 14px;\r\n outline: none;\r\n `;\r\n\r\n const resultsContainer = document.createElement('div');\r\n resultsContainer.className = 'search-results';\r\n resultsContainer.style.cssText = `\r\n margin-top: 8px;\r\n max-height: 200px;\r\n overflow-y: auto;\r\n `;\r\n\r\n searchContainer.appendChild(searchInput);\r\n searchContainer.appendChild(resultsContainer);\r\n\r\n // 插入到按钮前面\r\n this.toolbarElement.insertBefore(searchContainer, buttonElement);\r\n\r\n // 搜索功能\r\n let searchTimeout: ReturnType<typeof setTimeout>;\r\n searchInput.addEventListener('input', () => {\r\n clearTimeout(searchTimeout);\r\n const query = searchInput.value.trim();\r\n \r\n // 如果用户提供了自定义搜索输入处理逻辑\r\n if (this.searchCallback?.onSearchInput) {\r\n this.searchCallback.onSearchInput(query, resultsContainer);\r\n return;\r\n }\r\n \r\n if (query.length < 2) {\r\n resultsContainer.innerHTML = '';\r\n return;\r\n }\r\n\r\n searchTimeout = setTimeout(async () => {\r\n if (this.searchCallback?.onSearch) {\r\n try {\r\n const results = await this.searchCallback.onSearch(query);\r\n this.displaySearchResults(results, resultsContainer);\r\n } catch (error) {\r\n console.error('搜索失败:', error);\r\n resultsContainer.innerHTML = '<div style=\"padding: 8px; color: #666;\">搜索失败</div>';\r\n }\r\n } else {\r\n // 默认搜索逻辑\r\n this.performDefaultSearch(query, resultsContainer);\r\n }\r\n }, 300);\r\n });\r\n\r\n // 添加点击外部区域关闭搜索框的逻辑\r\n const closeSearchOnClickOutside = (event: MouseEvent) => {\r\n if (!searchContainer.contains(event.target as Node) && \r\n !buttonElement.contains(event.target as Node)) {\r\n searchContainer.remove();\r\n document.removeEventListener('click', closeSearchOnClickOutside);\r\n document.removeEventListener('keydown', closeSearchOnEscape);\r\n }\r\n };\r\n\r\n // 添加ESC键关闭搜索框的逻辑\r\n const closeSearchOnEscape = (event: KeyboardEvent) => {\r\n if (event.key === 'Escape') {\r\n searchContainer.remove();\r\n document.removeEventListener('click', closeSearchOnClickOutside);\r\n document.removeEventListener('keydown', closeSearchOnEscape);\r\n }\r\n };\r\n\r\n // 延迟添加事件监听器,避免立即触发\r\n setTimeout(() => {\r\n document.addEventListener('click', closeSearchOnClickOutside);\r\n document.addEventListener('keydown', closeSearchOnEscape);\r\n // 自动聚焦到搜索输入框\r\n searchInput.focus();\r\n }, 100);\r\n }\r\n\r\n /**\r\n * 显示搜索结果\r\n */\r\n private displaySearchResults(results: SearchResult[], container: HTMLElement): void {\r\n // 如果用户提供了自定义搜索结果处理逻辑\r\n if (this.searchCallback?.onSearchResults) {\r\n this.searchCallback.onSearchResults(results, container);\r\n return;\r\n }\r\n\r\n // 默认搜索结果显示逻辑\r\n container.innerHTML = '';\r\n \r\n if (results.length === 0) {\r\n container.innerHTML = '<div style=\"padding: 8px; color: #666;\">未找到相关地址</div>';\r\n return;\r\n }\r\n\r\n results.forEach(result => {\r\n const resultItem = document.createElement('div');\r\n resultItem.style.cssText = `\r\n padding: 8px;\r\n border-bottom: 1px solid #f0f0f0;\r\n cursor: pointer;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n resultItem.innerHTML = `\r\n <div style=\"font-weight: bold; margin-bottom: 2px;\">${result.name}</div>\r\n <div style=\"font-size: 12px; color: #666;\">${result.address}</div>\r\n `;\r\n\r\n resultItem.addEventListener('mouseenter', () => {\r\n resultItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n resultItem.addEventListener('mouseleave', () => {\r\n resultItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n resultItem.addEventListener('click', () => {\r\n this.selectSearchResult(result);\r\n container.parentElement?.remove();\r\n });\r\n\r\n container.appendChild(resultItem);\r\n });\r\n }\r\n\r\n /**\r\n * 选择搜索结果\r\n */\r\n private selectSearchResult(result: SearchResult): void {\r\n // 飞行到指定位置\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n result.longitude,\r\n result.latitude,\r\n result.height || 1000\r\n ),\r\n duration: 1.0\r\n });\r\n\r\n // 触发回调\r\n if (this.searchCallback?.onSelect) {\r\n this.searchCallback.onSelect(result);\r\n }\r\n }\r\n\r\n /**\r\n * 默认搜索逻辑\r\n */\r\n private performDefaultSearch(query: string, container: HTMLElement): void {\r\n // 模拟搜索结果\r\n const mockResults: SearchResult[] = [\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n },\r\n {\r\n name: '人工智能产业园',\r\n address: '浙江省杭州市西湖区',\r\n longitude: 120.16,\r\n latitude: 30.28,\r\n height: 100\r\n }\r\n ];\r\n\r\n this.displaySearchResults(mockResults, container);\r\n }\r\n\r\n /**\r\n * 切换测量功能\r\n */\r\n private toggleMeasurement(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.measurement-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'measurement-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 4px;\r\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\r\n padding: 4px 0;\r\n min-width: 120px;\r\n z-index: 1001;\r\n `;\r\n\r\n const menuItems = [\r\n { id: 'measure-area', text: '测面积', icon: '📐' },\r\n { id: 'measure-distance', text: '测距', icon: '📏' },\r\n { id: 'clear-measurement', text: '清除', icon: '🗑️' }\r\n ];\r\n\r\n menuItems.forEach(item => {\r\n const menuItem = document.createElement('div');\r\n menuItem.style.cssText = `\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n transition: background-color 0.2s;\r\n `;\r\n \r\n menuItem.innerHTML = `${item.icon} ${item.text}`;\r\n\r\n menuItem.addEventListener('mouseenter', () => {\r\n menuItem.style.backgroundColor = '#f5f5f5';\r\n });\r\n\r\n menuItem.addEventListener('mouseleave', () => {\r\n menuItem.style.backgroundColor = 'transparent';\r\n });\r\n\r\n menuItem.addEventListener('click', () => {\r\n this.handleMeasurementAction(item.id);\r\n menu.remove();\r\n });\r\n\r\n menu.appendChild(menuItem);\r\n });\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 处理测量操作\r\n */\r\n private handleMeasurementAction(action: string): void {\r\n switch (action) {\r\n case 'measure-area':\r\n this.drawHelper.startDrawingPolygon();\r\n break;\r\n case 'measure-distance':\r\n this.drawHelper.startDrawingLine();\r\n break;\r\n case 'clear-measurement':\r\n this.drawHelper.clearAll();\r\n if (this.measurementCallback?.onClear) {\r\n this.measurementCallback.onClear();\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 切换2D/3D视图\r\n */\r\n private toggle2D3D(buttonElement: HTMLElement): void {\r\n const currentMode = this.viewer.scene.mode;\r\n const targetMode = currentMode === Cesium.SceneMode.SCENE3D \r\n ? Cesium.SceneMode.SCENE2D \r\n : Cesium.SceneMode.SCENE3D;\r\n \r\n this.viewer.scene.mode = targetMode;\r\n \r\n // 更新按钮文本\r\n buttonElement.innerHTML = targetMode === Cesium.SceneMode.SCENE3D ? '3D' : '2D';\r\n }\r\n\r\n /**\r\n * 切换图层\r\n */\r\n private toggleLayers(buttonElement: HTMLElement): void {\r\n const existingMenu = this.toolbarElement.querySelector('.layers-menu');\r\n if (existingMenu) {\r\n return; // 如果菜单已存在,不重复创建\r\n }\r\n\r\n const menu = document.createElement('div');\r\n menu.className = 'layers-menu';\r\n menu.style.cssText = `\r\n position: absolute;\r\n right: 100%;\r\n top: 0;\r\n margin-right: 8px;\r\n background: white;\r\n border: 1px solid #e0e0e0;\r\n border-radius: 6px;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n padding: 12px;\r\n min-width: 220px;\r\n max-width: 280px;\r\n z-index: 1001;\r\n display: flex;\r\n flex-direction: column;\r\n `;\r\n\r\n // 地图类型选择\r\n const mapTypeSection = document.createElement('div');\r\n mapTypeSection.style.cssText = `\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n `;\r\n mapTypeSection.innerHTML = '<div style=\"font-weight: bold; margin-bottom: 8px; color: #333; font-size: 14px;\">地图类型</div>';\r\n \r\n this.mapTypes.forEach(mapType => {\r\n const mapTypeItem = document.createElement('div');\r\n mapTypeItem.style.cssText = `\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 8px 12px;\r\n cursor: pointer;\r\n border-radius: 4px;\r\n transition: background-color 0.2s;\r\n width: 100%;\r\n box-sizing: border-box;\r\n ${mapType.id === this.currentMapType ? 'background-color: #e3f2fd;' : ''}\r\n `;\r\n\r\n const thumbnail = document.createElement('img');\r\n thumbnail.src = mapType.thumbnail;\r\n thumbnail.style.cssText = `\r\n width: 24px; \r\n height: 24px; \r\n border-radius: 3px;\r\n flex-shrink: 0;\r\n `;\r\n\r\n const label = document.createElement('span');\r\n label.textContent = mapType.name;\r\n label.style.cssText = `\r\n font-size: 14px;\r\n color: #333;\r\n flex: 1;\r\n `;\r\n\r\n const checkmark = document.createElement('span');\r\n if (mapType.id === this.currentMapType) {\r\n checkmark.textContent = '✓';\r\n checkmark.style.cssText = `\r\n color: #1976d2; \r\n font-weight: bold; \r\n font-size: 16px;\r\n flex-shrink: 0;\r\n `;\r\n }\r\n\r\n mapTypeItem.appendChild(thumbnail);\r\n mapTypeItem.appendChild(label);\r\n mapTypeItem.appendChild(checkmark);\r\n\r\n mapTypeItem.addEventListener('mouseenter', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = '#f5f5f5';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('mouseleave', () => {\r\n if (mapType.id !== this.currentMapType) {\r\n mapTypeItem.style.backgroundColor = 'transparent';\r\n }\r\n });\r\n\r\n mapTypeItem.addEventListener('click', () => {\r\n this.switchMapType(mapType.id);\r\n menu.remove();\r\n });\r\n\r\n mapTypeSection.appendChild(mapTypeItem);\r\n });\r\n\r\n menu.appendChild(mapTypeSection);\r\n\r\n this.toolbarElement.insertBefore(menu, buttonElement);\r\n\r\n // 鼠标离开菜单区域时关闭\r\n const closeMenu = () => {\r\n menu.remove();\r\n };\r\n \r\n // 监听菜单的鼠标离开事件\r\n menu.addEventListener('mouseleave', closeMenu);\r\n }\r\n\r\n /**\r\n * 切换地图类型\r\n */\r\n private switchMapType(mapTypeId: string): void {\r\n const mapType = this.mapTypes.find(mt => mt.id === mapTypeId);\r\n if (!mapType) return;\r\n\r\n // 移除当前图层\r\n this.viewer.imageryLayers.removeAll();\r\n \r\n // 添加新图层\r\n this.viewer.imageryLayers.addImageryProvider(mapType.provider);\r\n \r\n this.currentMapType = mapTypeId;\r\n }\r\n\r\n /**\r\n * 复位到初始位置\r\n */\r\n private resetLocation(): void {\r\n if (!this.initialCenter) {\r\n console.warn('未设置初始中心点,无法执行复位操作');\r\n return;\r\n }\r\n\r\n this.viewer.camera.flyTo({\r\n destination: Cesium.Cartesian3.fromDegrees(\r\n this.initialCenter.longitude,\r\n this.initialCenter.latitude,\r\n this.initialCenter.height\r\n ),\r\n duration: 1.0\r\n });\r\n }\r\n\r\n /**\r\n * 放大\r\n */\r\n private zoomIn(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomIn(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomIn) {\r\n this.zoomCallback.onZoomIn(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 缩小\r\n */\r\n private zoomOut(): void {\r\n const beforeLevel = this.viewer.camera.positionCartographic.height;\r\n this.viewer.camera.zoomOut(this.viewer.camera.positionCartographic.height * 0.5);\r\n const afterLevel = this.viewer.camera.positionCartographic.height;\r\n \r\n if (this.zoomCallback?.onZoomOut) {\r\n this.zoomCallback.onZoomOut(beforeLevel, afterLevel);\r\n }\r\n }\r\n\r\n /**\r\n * 切换全屏\r\n */\r\n private toggleFullscreen(): void {\r\n if (!this.isFullscreen) {\r\n this.enterFullscreen();\r\n } else {\r\n this.exitFullscreen();\r\n }\r\n }\r\n\r\n /**\r\n * 进入全屏\r\n */\r\n private enterFullscreen(): void {\r\n const container = this.viewer.container;\r\n \r\n if (container.requestFullscreen) {\r\n container.requestFullscreen();\r\n } else if ((container as any).webkitRequestFullscreen) {\r\n (container as any).webkitRequestFullscreen();\r\n } else if ((container as any).msRequestFullscreen) {\r\n (container as any).msRequestFullscreen();\r\n }\r\n\r\n this.isFullscreen = true;\r\n \r\n // 监听全屏状态变化\r\n const fullscreenChange = () => {\r\n if (!document.fullscreenElement && \r\n !(document as any).webkitFullscreenElement && \r\n !(document as any).msFullscreenElement) {\r\n this.isFullscreen = false;\r\n document.removeEventListener('fullscreenchange', fullscreenChange);\r\n document.removeEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.removeEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n };\r\n\r\n document.addEventListener('fullscreenchange', fullscreenChange);\r\n document.addEventListener('webkitfullscreenchange', fullscreenChange);\r\n document.addEventListener('msfullscreenchange', fullscreenChange);\r\n }\r\n\r\n /**\r\n * 退出全屏\r\n */\r\n private exitFullscreen(): void {\r\n if (document.exitFullscreen) {\r\n document.exitFullscreen();\r\n } else if ((document as any).webkitExitFullscreen) {\r\n (document as any).webkitExitFullscreen();\r\n } else if ((document as any).msExitFullscreen) {\r\n (document as any).msExitFullscreen();\r\n }\r\n\r\n this.isFullscreen = false;\r\n }\r\n\r\n /**\r\n * 销毁工具栏\r\n */\r\n destroy(): void {\r\n if (this.toolbarElement && this.toolbarElement.parentNode) {\r\n this.toolbarElement.parentNode.removeChild(this.toolbarElement);\r\n }\r\n this.drawHelper.destroy();\r\n }\r\n}\r\n","import * as Cesium from 'cesium'\nimport { Ion, Viewer, createWorldTerrainAsync, Terrain, Cartesian3, SampledPositionProperty, TerrainProvider } from 'cesium'\nimport type { Entity, Viewer as CesiumViewer, EntityCollection } from 'cesium'\n\n\ninterface InitOptions {\n terrain: Terrain, // 地形\n terrainProvider?: TerrainProvider // 地形提供者\n mapType?: string // 地图类型,默认为天地图\n imageryProvider?: Cesium.UrlTemplateImageryProvider // 自定义影像图层提供r\n imageryLayers?: Cesium.ImageryLayerCollection // 自定义影像图层集合\n terrainShadows?: Cesium.ShadowMode // 地形阴影\n contextOptions?: Cesium.ContextOptions // 上下文选项\n scene3DOnly?: boolean // 是否只使用3D场景\n selectionIndicator?: boolean // 选择指示器\n navigationHelpButton?: boolean // 导航帮助按钮\n fullscreenButton?: boolean // 全屏按钮\n geocoder?: boolean // 地理编码器\n homeButton?: boolean // 主页按钮\n infoBox?: boolean // 信息框\n vrButton?: boolean // VR按钮\n sceneModePicker?: boolean // 场景模式选择器\n timeline?: boolean // 时间轴\n animation?: boolean // 动画\n baseLayerPicker?: boolean // 基础图层选择器\n navigationInstructionsInitiallyVisible?: boolean // 导航指令初始可见\n clock?: Cesium.Clock // 时钟\n sceneMode?: Cesium.SceneMode // 场景模式\n screenSpaceEventHandler?: Cesium.ScreenSpaceEventHandler // 屏幕空间事件处理器\n useDefaultRenderLoop?: boolean // 使用默认渲染循环\n targetFrameRate?: number // 目标帧率\n showRenderLoopErrors?: boolean // 显示渲染循环错误\n automaticallyTrackDataSourceClocks?: boolean // 自动跟踪数据源时钟\n dataSources?: Cesium.DataSourceCollection // 数据源集合\n creationTime?: number // 创建时间\n useBrowserRecommendedResolution?: boolean // 使用浏览器推荐分辨率\n resolutionScale?: number // 分辨率缩放\n orderIndependentTransparency?: boolean // 无序透明度\n shadows?: boolean // 阴影\n terrainExaggeration?: number // 地形夸张系数\n maximumScreenSpaceError?: number // 最大屏幕空间误差\n maximumNumberOfLoadedTiles?: number // 最大加载瓦片数量\n}\n\ninterface MapCenter {\n latitude: number\n longitude: number\n height: number,\n pitch?: number\n heading?: number\n}\n\ninterface TianDiMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\ninterface GaoDeMap {\n url: string,\n subdomains: string[],\n minimumLevel: number,\n maximumLevel: number,\n credit: string\n}\n\nexport function createTianDiMap(): TianDiMap {\n return {\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n }\n}\n\nexport function createGaoDeMap(): Cesium.UrlTemplateImageryProvider {\n return new Cesium.UrlTemplateImageryProvider({\n url: 'https://webst0{s}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}',\n subdomains: ['1', '2', '3', '4'], // 必须使用数字子域\n minimumLevel: 3,\n maximumLevel: 18,\n credit: '© 高德地图'\n })\n}\n\nexport async function initCesium(\n containerId: string,\n options: InitOptions,\n mapCenter: MapCenter = { longitude: 120.2052342, latitude: 30.2489634, height: 1000, pitch: -60, heading: 0 }\n): Promise<{ viewer: CesiumViewer; initialCenter: MapCenter }> {\n Ion.defaultAccessToken = (import.meta as any).env.VITE_CESIUM_TOKEN\n const viewer = new Viewer(containerId, {\n timeline: false,\n animation: false,\n baseLayerPicker: false,\n ...options\n })\n // 地形提供者\n if (!options.terrainProvider && !options.terrain) {\n viewer.terrainProvider = await createWorldTerrainAsync()\n }\n // 添加高德图影像图层\n if (options.mapType === 'gaode') {\n viewer.imageryLayers.removeAll();\n viewer.imageryLayers.addImageryProvider(createGaoDeMap());\n }\n if (mapCenter) {\n // 设置初始视角为中国区域 (经度, 纬度, 高度)\n viewer.camera.flyTo({\n destination: Cesium.Cartesian3.fromDegrees(mapCenter.longitude, mapCenter.latitude, mapCenter.height), // 中国中心坐标\n orientation: {\n heading: Cesium.Math.toRadians(mapCenter.heading || 0), // 方向角度\n pitch: Cesium.Math.toRadians(mapCenter.pitch || -30), // 俯\n }\n });\n }\n (viewer.cesiumWidget.creditContainer as HTMLElement).style.display = 'none';\n return { viewer, initialCenter: mapCenter }\n}","// VMap Cesium Toolbar Plugin\r\n// 导出主要类和接口\r\n\r\n// 核心类\r\nexport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nexport { default as DrawHelper } from './libs/CesiumMapHelper';\r\nexport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 类型定义\r\nexport type {\r\n ToolbarConfig,\r\n ButtonConfig,\r\n CustomButtonConfig,\r\n SearchCallback,\r\n SearchResult,\r\n MeasurementCallback,\r\n ZoomCallback,\r\n MapType\r\n} from './libs/CesiumMapToolbar';\r\n\r\nexport type {\r\n FrustumOptions,\r\n OverlayOptions\r\n} from './libs/CesiumMapModel';\r\n\r\n// 导入用于默认导出\r\nimport { CesiumMapToolbar } from './libs/CesiumMapToolbar';\r\nimport DrawHelper from './libs/CesiumMapHelper';\r\nimport { initCesium } from './libs/CesiumMapLoader';\r\n\r\n// 默认导出\r\nexport default {\r\n CesiumMapToolbar,\r\n DrawHelper,\r\n initCesium\r\n};\r\n"],"names":["DrawHelper","viewer","Cesium","height","primitive","options","fov","aspectRatio","near","far","position","orientation","frustum","fillGeometry","fillInstance","fillPrimitive","outlineGeometry","outlineInstance","outlinePrimitive","movement","error","mode","click","cartesian","move","mapDoubleClickAct","dblClick","windowPosition","ray","carto","elevatedPosition","pointEntity","entity","currentMousePosition","previewPoint","entitiesToRemove","index","positions","activeEntity","elevatedPositions","pos","i","startPos","endPos","distance","midPoint","labelOffset","labelEntity","totalDistance","labelPosition","totalLabelEntity","rect","finalEntity","p","area","center","areaLabelEntity","rectCenter","rectAreaLabelEntity","resetMode","allEntities","p1","p2","cartographic1","cartographic2","west","east","south","north","width","ellipsoid","len","x","y","z","callback","longitude","latitude","radius","borderColor","fillColor","borderWidth","name","color","groundHeight","groundPosition","topPosition","CesiumMapToolbar","container","config","callbacks","initialCenter","buttonId","button","buttonConfig","buttonElement","btn","defaultButtons","customButton","buttonSize","buttonColor","buttonHoverColor","icon","e","measureMenu","layersMenu","existingSearch","searchContainer","searchInput","resultsContainer","searchTimeout","query","results","closeSearchOnClickOutside","event","closeSearchOnEscape","result","resultItem","mockResults","menu","item","menuItem","closeMenu","action","targetMode","mapTypeSection","mapType","mapTypeItem","thumbnail","label","checkmark","mapTypeId","mt","beforeLevel","afterLevel","fullscreenChange","createGaoDeMap","initCesium","containerId","mapCenter","Ion","Viewer","createWorldTerrainAsync"],"mappings":"0iBAQA,MAAMA,CAAW,CACP,OACA,MACA,SACA,kBAAiC,CAAA,EAGjC,SAAoD,KACpD,UAAqB,GACrB,cAAqC,CAAA,EACrC,aAAgC,CAAA,EAChC,kBAAqC,CAAA,EACrC,iBAAoC,CAAA,EACpC,sBAAyC,CAAA,EACzC,sBAAyC,CAAA,EACzC,eAAkC,CAAA,EAClC,oBAA+B,GAE/B,wBAAiE,KAEjE,oBAA2C,KAC3C,kBACN,KACM,wBACN,KACM,aAAuB,EAM/B,YAAYC,EAAuB,CACjC,GAAI,CAACA,GAAU,EAAEA,aAAkBC,EAAO,QACxC,MAAM,IAAI,MAAM,0CAA0C,EAE5D,KAAK,OAASD,EACd,KAAK,MAAQA,EAAO,MACpB,KAAK,SAAWA,EAAO,SAGvB,KAAK,mBAAA,EAGL,KAAK,MAAM,cAAc,iBAAiB,IAAM,CAC9C,KAAK,mBAAA,CACP,CAAC,EAGD,KAAK,MAAM,MAAM,wBAA0B,EAC7C,CAKQ,oBAA2B,CAC7B,KAAK,MAAM,OAASC,EAAO,UAAU,QACvC,KAAK,aAAe,IAEpB,KAAK,aAAe,CAExB,CAMO,gBAAgBC,EAAsB,CAC3C,KAAK,aAAeA,CACtB,CAMO,iBAA0B,CAC/B,OAAO,KAAK,YACd,CAEA,cAAqB,CAEnB,KAAK,kBAAkB,QAASC,GAAc,CACxCA,GAAa,CAACA,EAAU,eAC1B,KAAK,OAAO,MAAM,WAAW,OAAOA,CAAS,CAEjD,CAAC,EACD,KAAK,kBAAoB,CAAA,EAGrB,KAAK,0BACP,KAAK,wBAAwB,QAAA,EAC7B,KAAK,wBAA0B,KAEnC,CAEA,YAAYC,EAA0B,GAAU,CAC9C,GAAI,CACF,KAAK,aAAA,EAGL,MAAMC,EAAM,KAAK,IAAI,EAAG,KAAK,IAAI,IAAKD,EAAQ,KAAO,EAAE,CAAC,EAClDE,EAAc,KAAK,IAAI,GAAKF,EAAQ,aAAe,CAAG,EACtDG,EAAO,KAAK,IAAI,GAAKH,EAAQ,MAAQ,CAAG,EACxCI,EAAM,KAAK,IAAID,EAAO,EAAGH,EAAQ,KAAO,GAAM,EAE9CK,EAAWL,EAAQ,UAAY,KAAK,OAAO,OAAO,WAClDM,EACJN,EAAQ,aACRH,EAAO,WAAW,mBAChBA,EAAO,QAAQ,YACb,KAAK,OAAO,OAAO,UACnB,IAAIA,EAAO,OAAQ,CACrB,EAGEU,EAAU,IAAIV,EAAO,mBAAmB,CAC5C,IAAKA,EAAO,KAAK,UAAUI,CAAG,EAC9B,YAAAC,EACA,KAAAC,EACA,IAAAC,CAAA,CACD,EAGKI,EAAe,IAAIX,EAAO,gBAAgB,CAC9C,QAAAU,EACA,OAAQF,EACR,YAAAC,EACA,aAAcT,EAAO,aAAa,aAAA,CACnC,EAEKY,EAAe,IAAIZ,EAAO,iBAAiB,CAC/C,SAAUW,EACV,WAAY,CACV,MAAOX,EAAO,+BAA+B,UAC3CG,EAAQ,WAAa,IAAIH,EAAO,MAAM,EAAK,EAAK,EAAK,EAAG,CAAA,CAC1D,CACF,CACD,EAEKa,EAAgB,IAAIb,EAAO,UAAU,CACzC,kBAAmBY,EACnB,WAAY,IAAIZ,EAAO,2BAA2B,CAChD,OAAQ,GACR,KAAM,EAAA,CACP,CAAA,CACF,EAGKc,EAAkB,IAAId,EAAO,uBAAuB,CACxD,QAAAU,EACA,OAAQF,EACR,YAAAC,CAAA,CACD,EAEKM,EAAkB,IAAIf,EAAO,iBAAiB,CAClD,SAAUc,EACV,WAAY,CACV,MAAOd,EAAO,+BAA+B,UAC3CG,EAAQ,cAAgB,IAAIH,EAAO,MAAM,EAAK,EAAK,EAAK,CAAG,CAAA,CAC7D,CACF,CACD,EAEKgB,EAAmB,IAAIhB,EAAO,UAAU,CAC5C,kBAAmBe,EACnB,WAAY,IAAIf,EAAO,2BAA2B,CAChD,OAAQ,GACR,KAAM,EAAA,CACP,CAAA,CACF,EAED,KAAK,OAAO,MAAM,WAAW,IAAIa,CAAa,EAC9C,KAAK,OAAO,MAAM,WAAW,IAAIG,CAAgB,EACjD,KAAK,kBAAkB,KAAKH,EAAeG,CAAgB,EAGvDb,EAAQ,cAAgB,KAAK,yBAC/B,KAAK,wBAAwB,eAAgBc,GAAkB,CACzDA,EAAS,UAAYd,EAAQ,cAC/BA,EAAQ,aAAaK,CAAQ,CAEjC,EAAGR,EAAO,qBAAqB,WAAW,CAE9C,OAASkB,EAAO,CACd,QAAQ,MAAM,cAAeA,CAAK,EAElC,KAAK,aAAA,CACP,CACF,CAKA,kBAAyB,CACvB,KAAK,aAAa,MAAM,CAC1B,CAKA,qBAA4B,CAC1B,KAAK,aAAa,SAAS,CAC7B,CAKA,uBAA8B,CAC5B,KAAK,aAAa,WAAW,CAC/B,CAMQ,aAAaC,EAA8C,CACjE,KAAK,mBAAmB,EAAK,EAE7B,KAAK,SAAWA,EAChB,KAAK,UAAY,GACjB,KAAK,cAAgB,CAAA,EACrB,KAAK,aAAe,CAAA,EAEpB,KAAK,wBAAA,EAGD,KAAK,qBACP,KAAK,oBAAA,CAET,CAKQ,yBAAgC,CACtC,KAAK,0BAAA,EAEL,KAAK,wBAA0B,IAAInB,EAAO,wBACxC,KAAK,MAAM,MAAA,EAIb,KAAK,wBAAwB,eAC1BoB,GAA0D,CACzD,GAAI,CAAC,KAAK,UAAW,OACrB,GAAI,KAAK,oBAAqB,CAC5B,KAAK,oBAAsB,GAC3B,MACF,CACA,MAAMC,EAAY,KAAK,kBAAkBD,EAAM,QAAQ,EACnDC,GACF,KAAK,SAASA,CAAS,CAE3B,EACArB,EAAO,qBAAqB,UAAA,EAI9B,KAAK,wBAAwB,eAAe,IAAM,CAC5C,CAAC,KAAK,WAAa,KAAK,cAAc,SAAW,GACrD,KAAK,gBAAA,CACP,EAAGA,EAAO,qBAAqB,WAAW,EAG1C,KAAK,wBAAwB,eAC1BsB,GAAqD,CACpD,GAAI,CAAC,KAAK,WAAa,KAAK,cAAc,SAAW,EAAG,OACxD,MAAMD,EAAY,KAAK,kBAAkBC,EAAK,WAAW,EACrDD,GACF,KAAK,cAAcA,CAAS,CAEhC,EACArB,EAAO,qBAAqB,UAAA,EAI9B,MAAMuB,EACJ,KAAK,OAAO,aAAa,wBAAwB,eAC/CvB,EAAO,qBAAqB,iBAAA,EAEhC,KAAK,OAAO,aAAa,wBAAwB,kBAC/CA,EAAO,qBAAqB,iBAAA,EAE9B,KAAK,wBAAwB,eAC1BwB,GAA6D,CACvD,KAAK,YACV,KAAK,oBAAsB,GAC3B,KAAK,cAAA,EAEDD,GACF,KAAK,OAAO,aAAa,wBAAwB,eAC/CA,EACAvB,EAAO,qBAAqB,iBAAA,EAGlC,EACAA,EAAO,qBAAqB,iBAAA,CAEhC,CAOQ,kBACNyB,EAC0B,CAE1B,MAAMC,EAAM,KAAK,OAAO,OAAO,WAAWD,CAAc,EACxD,GAAIC,EAAK,CACP,MAAMlB,EAAW,KAAK,MAAM,MAAM,KAAKkB,EAAK,KAAK,KAAK,EACtD,GAAI1B,EAAO,QAAQQ,CAAQ,EACzB,OAAOA,CAEX,CAMA,OAJ0B,KAAK,OAAO,OAAO,cAC3CiB,EACA,KAAK,MAAM,MAAM,SAAA,GAES,IAC9B,CAMQ,SAASjB,EAAmC,CAClD,KAAK,cAAc,KAAKA,EAAS,MAAA,CAAO,EAGxC,MAAMmB,EAAQ3B,EAAO,aAAa,cAAcQ,CAAQ,EAClDoB,EAAmB5B,EAAO,WAAW,YACzC2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,IAAM,KAAK,WAAa,OAAS,EAAI,KAAK,aAAA,EAGvDE,EAAc,KAAK,SAAS,IAAI,CACpC,SAAUD,EACV,MAAO,CACL,UAAW,EACX,MAAO5B,EAAO,MAAM,IACpB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,mBACxC,gBAAiB,IAAIA,EAAO,cAAc,IAAO,EAAK,KAAO,EAAG,CAAA,CAClE,CACD,EACD,KAAK,aAAa,KAAK6B,CAAW,EAClC,KAAK,oBAAA,CACP,CAKQ,iBAAwB,CAC1B,KAAK,cAAc,OAAS,IAE9B,KAAK,cAAc,IAAA,EAGnB,KAAK,aAAa,QAASC,GAAW,CAChCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,aAAe,CAAA,EAGpB,KAAK,kBAAkB,QAASA,GAAW,CACrCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,kBAAoB,CAAA,EAGzB,KAAK,0BAAA,EAET,CAMQ,2BAAkC,CAExC,KAAK,cAAc,QAAStB,GAAa,CACvC,MAAMmB,EAAQ3B,EAAO,aAAa,cAAcQ,CAAQ,EAClDoB,EAAmB5B,EAAO,WAAW,YACzC2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,EAGvBE,EAAc,KAAK,SAAS,IAAI,CACpC,SAAUD,EACV,MAAO,CACL,UAAW,EACX,MAAO5B,EAAO,MAAM,IACpB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,mBACxC,gBAAiB,IAAIA,EAAO,cAAc,IAAO,EAAK,KAAO,EAAG,CAAA,CAClE,CACD,EACD,KAAK,aAAa,KAAK6B,CAAW,CACpC,CAAC,EAGD,KAAK,oBAAA,CACP,CAMQ,cAAcE,EAA+C,CACnE,KAAK,oBAAoBA,CAAoB,CAC/C,CAMQ,oBAAoBC,EAAwC,CAElE,MAAMC,EAAoC,CAAA,EAC1C,KAAK,aAAa,QAASH,GAAW,CAChCA,IAAWA,EAAO,UAAYA,EAAO,SAAWA,EAAO,YACzDG,EAAiB,KAAKH,CAAM,CAEhC,CAAC,EAGDG,EAAiB,QAASH,GAAW,CACnC,KAAK,SAAS,OAAOA,CAAM,EAC3B,MAAMI,EAAQ,KAAK,aAAa,QAAQJ,CAAM,EAC1CI,EAAQ,IACV,KAAK,aAAa,OAAOA,EAAO,CAAC,CAErC,CAAC,EAGD,KAAK,kBAAkB,QAASJ,GAAW,CACrCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,kBAAoB,CAAA,EACzB,MAAMK,EAAY,CAAC,GAAG,KAAK,aAAa,EAKxC,GAJIH,GACFG,EAAU,KAAKH,CAAY,EAGzBG,EAAU,OAAS,EAAG,OAE1B,IAAIC,EAEJ,GAAI,KAAK,WAAa,OAAQ,CAE5B,GAAI,KAAK,aAAe,EAAG,CAEzB,MAAMC,EAAoBF,EAAU,IAAIG,GAAO,CAC7C,MAAMX,EAAQ3B,EAAO,aAAa,cAAcsC,CAAG,EACnD,OAAOtC,EAAO,WAAW,YACvB2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,CAE/B,CAAC,EAEDS,EAAe,KAAK,SAAS,IAAI,CAC/B,SAAU,CACR,UAAWC,EACX,MAAO,EACP,SAAUrC,EAAO,MAAM,OACvB,cAAe,EAAA,CACjB,CACD,CACH,MAEEoC,EAAe,KAAK,SAAS,IAAI,CAC/B,SAAU,CACR,UAAAD,EACA,MAAO,EACP,SAAUnC,EAAO,MAAM,OACvB,cAAe,EAAA,CACjB,CACD,EAEH,KAAK,aAAa,KAAKoC,CAAY,EAGnC,QAASG,EAAI,EAAGA,EAAIJ,EAAU,OAAS,EAAGI,IAAK,CAC7C,MAAMC,EAAWL,EAAUI,CAAC,EACtBE,EAASN,EAAUI,EAAI,CAAC,EACxBG,EAAW1C,EAAO,WAAW,SAASwC,EAAUC,CAAM,EAG5D,GAAIC,EAAW,EAAK,CAClB,MAAMC,EAAW3C,EAAO,WAAW,SACjCwC,EACAC,EACA,IAAIzC,EAAO,UAAW,EAGlB4C,EAAcL,EAAI,IAAM,EAAI,IAAM,GAClCM,EAAc,KAAK,SAAS,IAAI,CACpC,SAAUF,EACV,MAAO,CACL,KAAM,GAAGD,EAAS,QAAQ,CAAC,CAAC,KAC5B,KAAM,aACN,UAAW1C,EAAO,MAAM,MACxB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,MAAOA,EAAO,WAAW,iBACzB,YAAa,IAAIA,EAAO,WAAW,EAAG4C,CAAW,EACjD,gBAAiB,KAAK,aAAe,EAAI5C,EAAO,gBAAgB,mBAAqBA,EAAO,gBAAgB,gBAC5G,MAAO,EACP,eAAgB,GAChB,gBAAiBA,EAAO,MAAM,MAAM,UAAU,EAAG,EACjD,kBAAmB,IAAIA,EAAO,WAAW,EAAG,CAAC,CAAA,CAC/C,CACD,EACD,KAAK,kBAAkB,KAAK6C,CAAW,CACzC,CACF,CAGA,GAAIV,EAAU,OAAS,EAAG,CACxB,IAAIW,EAAgB,EACpB,QAASP,EAAI,EAAGA,EAAIJ,EAAU,OAAQI,IACpCO,GAAiB9C,EAAO,WAAW,SACjCmC,EAAUI,EAAI,CAAC,EACfJ,EAAUI,CAAC,CAAA,EAIf,IAAIQ,EAAgBZ,EAAUA,EAAU,OAAS,CAAC,EAClD,GAAI,KAAK,aAAe,EAAG,CAEzB,MAAMR,EAAQ3B,EAAO,aAAa,cAAc+C,CAAa,EAC7DA,EAAgB/C,EAAO,WAAW,YAChC2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,CAE/B,CAEA,MAAMqB,EAAmB,KAAK,SAAS,IAAI,CACzC,SAAUD,EACV,MAAO,CACL,KAAM,OAAOD,EAAc,QAAQ,CAAC,CAAC,KACrC,KAAM,aACN,UAAW9C,EAAO,MAAM,OACxB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,MAAOA,EAAO,WAAW,iBACzB,YAAa,IAAIA,EAAO,WAAW,EAAG,EAAE,EACxC,gBAAiB,KAAK,aAAe,EAAIA,EAAO,gBAAgB,KAAOA,EAAO,gBAAgB,gBAC9F,MAAO,EACP,eAAgB,GAChB,gBAAiBA,EAAO,MAAM,MAAM,UAAU,EAAG,EACjD,kBAAmB,IAAIA,EAAO,WAAW,EAAG,CAAC,CAAA,CAC/C,CACD,EACD,KAAK,kBAAkB,KAAKgD,CAAgB,CAC9C,CACF,SAAW,KAAK,WAAa,UAE3B,GAAI,KAAK,aAAe,EAAG,CAEzB,MAAMX,EAAoBF,EAAU,IAAIG,GAAO,CAC7C,MAAMX,EAAQ3B,EAAO,aAAa,cAAcsC,CAAG,EACnD,OAAOtC,EAAO,WAAW,YACvB2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,CAE/B,CAAC,EAEDS,EAAe,KAAK,SAAS,IAAI,CAC/B,QAAS,CACP,UAAW,IAAIpC,EAAO,iBAAiB,IAC9B,IAAIA,EAAO,iBAAiBqC,CAAiB,EACnD,EAAK,EACR,SAAUrC,EAAO,MAAM,WAAW,UAAU,EAAG,EAC/C,QAAS,GACT,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,IAAA,CAC1C,CACD,CACH,MAEEoC,EAAe,KAAK,SAAS,IAAI,CAC/B,QAAS,CACP,UAAW,IAAIpC,EAAO,iBAAiB,IAC9B,IAAIA,EAAO,iBAAiBmC,CAAS,EAC3C,EAAK,EACR,SAAUnC,EAAO,MAAM,WAAW,UAAU,EAAG,EAC/C,QAAS,GACT,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,UAEM,KAAK,WAAa,aAAemC,EAAU,QAAU,EAAG,CACjE,MAAMc,EAAO,KAAK,mBAAmBd,EAAU,CAAC,EAAGA,EAAU,CAAC,CAAC,EAC3D,KAAK,aAAe,EAEtBC,EAAe,KAAK,SAAS,IAAI,CAC/B,UAAW,CACT,YAAaa,EACb,SAAUjD,EAAO,MAAM,MAAM,UAAU,EAAG,EAC1C,gBAAiBA,EAAO,gBAAgB,KACxC,eAAgB,KAAK,YAAA,CACvB,CACD,EAGDoC,EAAe,KAAK,SAAS,IAAI,CAC/B,UAAW,CACT,YAAaa,EACb,SAAUjD,EAAO,MAAM,MAAM,UAAU,EAAG,EAC1C,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,CAEL,CAEIoC,GACF,KAAK,aAAa,KAAKA,CAAY,CAEvC,CAKQ,eAAsB,CAC5B,GAAI,KAAK,cAAc,QAAU,KAAK,WAAa,YAAc,GAAQ,CAEvE,KAAK,mBAAmB,EAAI,EAC5B,MACF,CACA,IAAIc,EAAoC,KACxC,MAAMf,EAAY,KAAK,cAAc,IAAKgB,GAAMA,EAAE,OAAO,EAEzD,GAAI,KAAK,WAAa,OAEpB,GAAI,KAAK,aAAe,EAAG,CAEzB,MAAMd,EAAoBF,EAAU,IAAIG,GAAO,CAC7C,MAAMX,EAAQ3B,EAAO,aAAa,cAAcsC,CAAG,EACnD,OAAOtC,EAAO,WAAW,YACvB2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,CAE/B,CAAC,EAEDuB,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,OACN,SAAU,CACR,UAAWb,EACX,MAAO,EACP,SAAUrC,EAAO,MAAM,OACvB,cAAe,EAAA,CACjB,CACD,CACH,MAEEkD,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,OACN,SAAU,CACR,UAAAf,EACA,MAAO,EACP,SAAUnC,EAAO,MAAM,OACvB,cAAe,EAAA,CACjB,CACD,UAIM,KAAK,WAAa,UAAW,CAEtC,GAAI,KAAK,aAAe,EAAG,CAEzB,MAAMqC,EAAoBF,EAAU,IAAIG,GAAO,CAC7C,MAAMX,EAAQ3B,EAAO,aAAa,cAAcsC,CAAG,EACnD,OAAOtC,EAAO,WAAW,YACvB2B,EAAM,UACNA,EAAM,UACLA,EAAM,QAAU,GAAK,KAAK,YAAA,CAE/B,CAAC,EAEDuB,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,WACN,QAAS,CACP,UAAW,IAAIlD,EAAO,iBAAiBqC,CAAiB,EACxD,SAAUrC,EAAO,MAAM,WAAW,UAAU,EAAG,EAC/C,QAAS,GACT,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,IAAA,CAC1C,CACD,CACH,MAEEkD,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,WACN,QAAS,CACP,UAAW,IAAIlD,EAAO,iBAAiBmC,CAAS,EAChD,SAAUnC,EAAO,MAAM,WAAW,UAAU,EAAG,EAC/C,QAAS,GACT,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,EAGH,MAAMoD,EAAO,KAAK,qBAAqBjB,CAAS,EAChD,GAAIiB,EAAO,EAAG,CACZ,MAAMC,EAAS,KAAK,uBAAuBlB,CAAS,EAC9CmB,EAAkB,KAAK,SAAS,IAAI,CACxC,SAAUD,EACV,MAAO,CACL,KAAM,OAAOD,EAAK,QAAQ,CAAC,CAAC,OAC5B,KAAM,kBACN,UAAWpD,EAAO,MAAM,MACxB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,MAAOA,EAAO,WAAW,iBACzB,YAAa,IAAIA,EAAO,WAAW,EAAG,GAAG,EACzC,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,EACD,KAAK,sBAAsB,KAAKsD,CAAe,CACjD,CACF,SAAW,KAAK,WAAa,aAAenB,EAAU,QAAU,EAAG,CACjE,MAAMc,EAAO,KAAK,mBAAmBd,EAAU,CAAC,EAAGA,EAAU,CAAC,CAAC,EAC3D,KAAK,aAAe,EAEtBe,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,QACN,UAAW,CACT,YAAaD,EACb,SAAUjD,EAAO,MAAM,MAAM,UAAU,EAAG,EAC1C,gBAAiBA,EAAO,gBAAgB,KACxC,eAAgB,KAAK,YAAA,CACvB,CACD,EAGDkD,EAAc,KAAK,SAAS,IAAI,CAC9B,KAAM,QACN,UAAW,CACT,YAAaD,EACb,SAAUjD,EAAO,MAAM,MAAM,UAAU,EAAG,EAC1C,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,EAGH,MAAMoD,EAAO,KAAK,uBAAuBH,CAAI,EAC7C,GAAIG,EAAO,EAAG,CACZ,MAAMG,EAAavD,EAAO,UAAU,OAAOiD,CAAI,EACzCO,EAAsB,KAAK,SAAS,IAAI,CAC5C,SAAUxD,EAAO,WAAW,YAC1BuD,EAAW,UACXA,EAAW,QAAA,EAEb,MAAO,CACL,KAAM,OAAOH,EAAK,QAAQ,CAAC,CAAC,OAC5B,KAAM,kBACN,UAAWpD,EAAO,MAAM,MACxB,aAAcA,EAAO,MAAM,MAC3B,aAAc,EACd,MAAOA,EAAO,WAAW,iBACzB,YAAa,IAAIA,EAAO,WAAW,EAAG,GAAG,EACzC,gBAAiBA,EAAO,gBAAgB,eAAA,CAC1C,CACD,EACD,KAAK,sBAAsB,KAAKwD,CAAmB,CACrD,CACF,CAGIN,GACF,KAAK,iBAAiB,KAAKA,CAAW,EAIxC,KAAK,kBAAkB,QAASpB,GAAW,CACzC,KAAK,sBAAsB,KAAKA,CAAM,CACxC,CAAC,EACD,KAAK,kBAAoB,CAAA,EAGzB,KAAK,aAAa,QAASA,GAAW,CAChCA,GAAUA,EAAO,MACnB,KAAK,sBAAsB,KAAKA,CAAM,EAGtC,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,aAAe,CAAA,EACpB,KAAK,cAAgB,CAAA,EAGnB,KAAK,SAAW,KAChB,KAAK,UAAY,GACjB,KAAK,0BAAA,EAIH,KAAK,mBACP,KAAK,kBAAkBoB,CAAW,CAEtC,CAMQ,mBAAmBO,EAA0B,CAEnD,KAAK,aAAa,QAAS3B,GAAW,CACpC,KAAK,SAAS,OAAOA,CAAM,CAC7B,CAAC,EACD,KAAK,aAAe,CAAA,EACpB,KAAK,cAAgB,CAAA,EAErB,KAAK,kBAAkB,QAASA,GAAW,CACzC,KAAK,SAAS,OAAOA,CAAM,CAC7B,CAAC,EACD,KAAK,kBAAoB,CAAA,EAErB2B,IACF,KAAK,SAAW,KAChB,KAAK,UAAY,GACjB,KAAK,0BAAA,EAET,CAKA,YAAmB,CACb,KAAK,UACP,KAAK,cAAA,EAGL,KAAK,mBAAmB,EAAI,CAEhC,CAKQ,2BAAkC,CACpC,KAAK,0BACP,KAAK,wBAAwB,QAAA,EAC7B,KAAK,wBAA0B,KAEnC,CAKA,UAAiB,CAEf,KAAK,WAAA,EAGL,KAAK,eAAA,EAGL,KAAK,iBAAiB,QAAS3B,GAAW,CACxC,KAAK,SAAS,OAAOA,CAAM,CAC7B,CAAC,EACD,KAAK,iBAAmB,CAAA,EAGxB,KAAK,sBAAsB,QAASA,GAAW,CACzCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,sBAAwB,CAAA,EAG7B,KAAK,eAAe,QAASA,GAAW,CAClCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,eAAiB,CAAA,EAGtB,KAAK,aAAa,QAASA,GAAW,CAChCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,aAAe,CAAA,EAGpB,KAAK,kBAAkB,QAASA,GAAW,CACrCA,GAAUA,EAAO,OACnB,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,kBAAoB,CAAA,EAGzB,KAAK,cAAgB,CAAA,CACvB,CAMA,kBAAyB,CAEvB,KAAK,WAAA,EAEL,KAAK,SAAS,UAAA,EAEd,KAAK,iBAAmB,CAAA,EACxB,KAAK,sBAAwB,CAAA,EAC7B,KAAK,sBAAwB,CAAA,EAC7B,KAAK,eAAiB,CAAA,EACtB,KAAK,aAAe,CAAA,EACpB,KAAK,kBAAoB,CAAA,EACzB,KAAK,cAAgB,CAAA,CACvB,CAMA,gBAAuB,CAErB,KAAK,sBAAsB,QAASA,GAAW,CACzCA,GACF,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EACD,KAAK,sBAAwB,CAAA,EAG7B,KAAK,aAAa,QAASA,GAAW,CAChCA,GAAUA,EAAO,OACnB,KAAK,SAAS,OAAOA,CAAM,CAE/B,CAAC,EAGD,MAAM4B,EAAc,KAAK,SAAS,OAClC,QAASnB,EAAImB,EAAY,OAAS,EAAGnB,GAAK,EAAGA,IAAK,CAChD,MAAMT,EAAS4B,EAAYnB,CAAC,EACxBT,GAAUA,EAAO,OACnB,KAAK,SAAS,OAAOA,CAAM,CAE/B,CACF,CAMA,aAAaA,EAA6B,CACxC,MAAMI,EAAQ,KAAK,iBAAiB,QAAQJ,CAAM,EAC9CI,EAAQ,KACV,KAAK,SAAS,OAAOJ,CAAM,EAC3B,KAAK,iBAAiB,OAAOI,EAAO,CAAC,EACjC,KAAK,yBACP,KAAK,wBAAwBJ,CAAM,EAGzC,CAMA,qBAAuC,CACrC,MAAO,CAAC,GAAG,KAAK,gBAAgB,CAClC,CAGQ,mBACN6B,EACAC,EACkB,CAClB,MAAMC,EAAgB7D,EAAO,aAAa,cAAc2D,CAAE,EACpDG,EAAgB9D,EAAO,aAAa,cAAc4D,CAAE,EACpDG,EAAO,KAAK,IAAIF,EAAc,UAAWC,EAAc,SAAS,EAChEE,EAAO,KAAK,IAAIH,EAAc,UAAWC,EAAc,SAAS,EAChEG,EAAQ,KAAK,IAAIJ,EAAc,SAAUC,EAAc,QAAQ,EAC/DI,EAAQ,KAAK,IAAIL,EAAc,SAAUC,EAAc,QAAQ,EACrE,OAAO,IAAI9D,EAAO,UAAU+D,EAAME,EAAOD,EAAME,CAAK,CACtD,CAEQ,uBAAuBjB,EAAgC,CAC7D,MAAMc,EAAOd,EAAK,KACZgB,EAAQhB,EAAK,MACbe,EAAOf,EAAK,KACZiB,EAAQjB,EAAK,MAEbkB,EAAQnE,EAAO,WAAW,SAC9BA,EAAO,WAAW,YAAY+D,EAAME,CAAK,EACzCjE,EAAO,WAAW,YAAYgE,EAAMC,CAAK,CAAA,EAErChE,EAASD,EAAO,WAAW,SAC/BA,EAAO,WAAW,YAAY+D,EAAME,CAAK,EACzCjE,EAAO,WAAW,YAAY+D,EAAMG,CAAK,CAAA,EAG3C,OAAQC,EAAQlE,EAAU,GAC5B,CAEQ,qBAAqBkC,EAAwC,CACnE,GAAIA,EAAU,OAAS,EAAG,MAAO,GACjC,MAAMiC,EAAY,KAAK,MAAM,MAAM,UACnC,IAAIhB,EAAO,EACX,MAAMiB,EAAMlC,EAAU,OACtB,QAASI,EAAI,EAAGA,EAAI8B,EAAK9B,IAAK,CAC5B,MAAMoB,EAAKS,EAAU,wBAAwBjC,EAAUI,CAAC,CAAC,EACnDqB,EAAKQ,EAAU,wBAAwBjC,GAAWI,EAAI,GAAK8B,CAAG,CAAC,EACrEjB,IACGQ,EAAG,UAAYD,EAAG,YAClB,EAAI,KAAK,IAAIA,EAAG,QAAQ,EAAI,KAAK,IAAIC,EAAG,QAAQ,EACrD,CACA,OAAAR,EAAO,KAAK,IAAKA,EAAO,QAAY,QAAa,CAAG,EAC7CA,EAAO,GAChB,CAEQ,uBACNjB,EACmB,CACnB,GAAIA,EAAU,SAAW,EAAG,OAAOnC,EAAO,WAAW,KACrD,IAAIsE,EAAI,EACNC,EAAI,EACJC,EAAI,EACN,QAASjC,EAAI,EAAGA,EAAIJ,EAAU,OAAQI,IACpC+B,GAAKnC,EAAUI,CAAC,EAAE,EAClBgC,GAAKpC,EAAUI,CAAC,EAAE,EAClBiC,GAAKrC,EAAUI,CAAC,EAAE,EAEpB,OAAO,IAAIvC,EAAO,WAChBsE,EAAInC,EAAU,OACdoC,EAAIpC,EAAU,OACdqC,EAAIrC,EAAU,MAAA,CAElB,CAQA,YAAYsC,EAA4B,CACtC,KAAK,oBAAsBA,CAC7B,CAMA,UAAUA,EAAwD,CAChE,KAAK,kBAAoBA,CAC3B,CAMA,gBAAgBA,EAAiD,CAC/D,KAAK,wBAA0BA,CACjC,CAUO,qBACLC,EACAC,EACA1E,EACA2E,EACAzE,EAMe,CACf,MAAM0E,EAAc1E,GAAS,aAAe,UACtC2E,EAAY3E,GAAS,WAAa,UAClC4E,EAAc5E,GAAS,aAAe,EACtC6E,EAAO7E,GAAS,MAAQ,OAGxB2B,EAAS,KAAK,SAAS,IAAI,CAC/B,KAAAkD,EACA,SAAUhF,EAAO,WAAW,YAAY0E,EAAWC,EAAU1E,CAAM,EACnE,QAAS,CACP,cAAe2E,EACf,cAAeA,EACf,SAAU5E,EAAO,MAAM,mBAAmB8E,CAAS,EAAE,UAAU,GAAI,EACnE,QAAS,GACT,aAAc9E,EAAO,MAAM,mBAAmB6E,CAAW,EACzD,aAAcE,EACd,gBAAiB/E,EAAO,gBAAgB,eAAA,CAC1C,CACD,EAGD,YAAK,eAAe,KAAK8B,CAAM,EAExBA,CACT,CASO,iBACL4C,EACAC,EACA1E,EACAE,EAOe,CACf,MAAM8E,EAAQ9E,GAAS,OAAS,UAC1BgE,EAAQhE,GAAS,OAAS,EACZA,GAAS,YAC7B,MAAM6E,EAAO7E,GAAS,MAAQ,OACxB+E,EAAe/E,GAAS,cAAgB,EAGxCgF,EAAiBnF,EAAO,WAAW,YACvC0E,EACAC,EACAO,CAAA,EAEIE,EAAcpF,EAAO,WAAW,YACpC0E,EACAC,EACA1E,CAAA,EAII6B,EAAS,KAAK,SAAS,IAAI,CAC/B,KAAAkD,EACA,SAAU,CACR,UAAW,CAACG,EAAgBC,CAAW,EACvC,MAAAjB,EACA,SAAU,IAAInE,EAAO,6BAA6B,CAChD,MAAOA,EAAO,MAAM,mBAAmBiF,CAAK,CAAA,CAC7C,EACD,cAAe,EAAA,CACjB,CACD,EAGD,YAAK,eAAe,KAAKnD,CAAM,EAExBA,CACT,CAKA,SAAgB,CACd,KAAK,0BAAA,EACL,KAAK,aAAA,CAGP,CACF,CAIA,OAAO,WAAahC,ECxmCb,MAAMuF,CAAiB,CACpB,OACA,WACA,UACA,eACA,OACA,eACA,oBACA,aACA,cACA,aAAwB,GACxB,eAAyB,UAGzB,SAAsB,CAC5B,CACE,GAAI,SACJ,KAAM,SACN,UAAW,iSACX,SAAU,IAAIrF,EAAO,2BAA2B,CAC9C,IAAK,oNACL,WAAY,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACnD,aAAc,EACd,aAAc,GACd,OAAQ,OAAA,CACT,CAAA,EAEH,CACE,GAAI,KACJ,KAAM,SACN,UAAW,iSACX,SAAU,IAAIA,EAAO,2BAA2B,CAC9C,IAAK,oNACL,WAAY,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACnD,aAAc,EACd,aAAc,GACd,OAAQ,OAAA,CACT,CAAA,EAEH,CACE,GAAI,UACJ,KAAM,SACN,UAAW,iSACX,SAAU,IAAIA,EAAO,2BAA2B,CAC9C,IAAK,oNACL,WAAY,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACnD,aAAc,EACd,aAAc,GACd,OAAQ,OAAA,CACT,CAAA,EAEH,CACE,GAAI,UACJ,KAAM,SACN,UAAW,iSACX,SAAU,IAAIA,EAAO,2BAA2B,CAC9C,IAAK,oNACL,WAAY,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAG,EACnD,aAAc,EACd,aAAc,GACd,OAAQ,OAAA,CACT,CAAA,CACH,EAGF,YACED,EACAuF,EACAC,EAAwB,CAAA,EACxBC,EAKAC,EACA,CACA,KAAK,OAAS1F,EACd,KAAK,UAAYuF,EACjB,KAAK,OAAS,CACZ,SAAU,eACV,WAAY,GACZ,cAAe,EACf,gBAAiB,2BACjB,YAAa,UACb,aAAc,EACd,UAAW,gCACX,OAAQ,IACR,GAAGC,CAAA,EAEL,KAAK,eAAiBC,GAAW,OACjC,KAAK,oBAAsBA,GAAW,YACtC,KAAK,aAAeA,GAAW,KAG/B,KAAK,cAAgBC,EAGrB,KAAK,WAAa,IAAI3F,EAAWC,CAAM,EACvC,KAAK,yBAAA,EAGL,KAAK,cAAA,CACP,CAKO,iBAAiBsD,EAAuE,CAC7F,KAAK,cAAgBA,CACvB,CAKO,kBAAwF,CAC7F,OAAO,KAAK,aACd,CAKO,wBAA+B,CACpC,KAAK,cAAA,CACP,CAKO,mBAAmBqC,EAAkBH,EAA2C,CACrF,MAAMI,EAAS,KAAK,eAAe,cAAc,eAAeD,CAAQ,IAAI,EACvEC,IAGDJ,EAAO,QAAOI,EAAO,MAAQJ,EAAO,OACpCA,EAAO,MAAM,KAAK,cAAcI,EAAQJ,EAAO,IAAI,EACnDA,EAAO,OACTI,EAAO,MAAM,MAAQ,GAAGJ,EAAO,IAAI,KACnCI,EAAO,MAAM,OAAS,GAAGJ,EAAO,IAAI,MAElCA,EAAO,QAAOI,EAAO,MAAM,WAAaJ,EAAO,OACrD,CAKO,gBAAgBA,EAAkC,CACvD,MAAMK,EAA6B,CACjC,GAAIL,EAAO,GACX,KAAM,OAAOA,EAAO,MAAS,SAAWA,EAAO,KAAO,GACtD,MAAOA,EAAO,MACd,KAAMA,EAAO,KACb,MAAOA,EAAO,MACd,WAAYA,EAAO,WACnB,YAAaA,EAAO,WAAA,EAGhBM,EAAgB,KAAK,aAAaD,CAAY,EACpD,KAAK,eAAe,YAAYC,CAAa,EAGxC,KAAK,OAAO,UACf,KAAK,OAAO,QAAU,CAAA,GAExB,KAAK,OAAO,QAAQ,KAAKN,CAAM,CACjC,CAKO,aAAaG,EAAwB,CAC1C,MAAMC,EAAS,KAAK,eAAe,cAAc,eAAeD,CAAQ,IAAI,EACxEC,GAAUA,EAAO,YACnBA,EAAO,WAAW,YAAYA,CAAM,EAIlC,KAAK,OAAO,UACd,KAAK,OAAO,QAAU,KAAK,OAAO,QAAQ,OAAOG,GAAOA,EAAI,KAAOJ,CAAQ,EAE/E,CAKO,iBAAiBA,EAAsC,CAC5D,OAAO,KAAK,eAAe,cAAc,eAAeA,CAAQ,IAAI,CACtE,CAKQ,0BAAiC,CACvC,KAAK,WAAW,YAAY,IAAM,CAChC,QAAQ,IAAI,MAAM,CACpB,CAAC,EAED,KAAK,WAAW,UAAW5D,GAAW,CACpC,GAAIA,GAGF,GAFA,QAAQ,IAAI,OAAQA,CAAM,EAEtBA,EAAO,SAAU,CAEnB,MAAMK,EAAYL,EAAO,SAAS,WAAW,SAAS9B,EAAO,WAAW,KAAK,EAC7E,GAAImC,GAAa,KAAK,qBAAqB,mBAAoB,CAC7D,IAAIW,EAAgB,EACpB,QAASP,EAAI,EAAGA,EAAIJ,EAAU,OAAQI,IACpCO,GAAiB9C,EAAO,WAAW,SAASmC,EAAUI,EAAE,CAAC,EAAGJ,EAAUI,CAAC,CAAC,EAE1E,KAAK,oBAAoB,mBAAmBJ,EAAWW,CAAa,CACtE,CACF,SAAWhB,EAAO,QAAS,CAEzB,MAAMK,EAAYL,EAAO,QAAQ,WAAW,SAAS9B,EAAO,WAAW,KAAK,EAC5E,GAAImC,GAAa,KAAK,qBAAqB,eAAgB,CAEzD,MAAMiB,EAAO,KAAK,qBAAqBjB,EAAU,SAAS,EAC1D,KAAK,oBAAoB,eAAeA,EAAU,UAAWiB,CAAI,CACnE,CACF,EAEJ,CAAC,EAED,KAAK,WAAW,gBAAiBtB,GAAW,CAC1C,QAAQ,IAAI,QAASA,CAAM,CAC7B,CAAC,CACH,CAKQ,qBAAqBK,EAAiC,CAC5D,GAAIA,EAAU,OAAS,EAAG,MAAO,GAEjC,MAAMiC,EAAY,KAAK,OAAO,MAAM,MAAM,UAC1C,IAAIhB,EAAO,EACX,MAAMiB,EAAMlC,EAAU,OAEtB,QAASI,EAAI,EAAGA,EAAI8B,EAAK9B,IAAK,CAC5B,MAAMoB,EAAKS,EAAU,wBAAwBjC,EAAUI,CAAC,CAAC,EACnDqB,EAAKQ,EAAU,wBAAwBjC,GAAWI,EAAI,GAAK8B,CAAG,CAAC,EACrEjB,IAASQ,EAAG,UAAYD,EAAG,YAAc,EAAI,KAAK,IAAIA,EAAG,QAAQ,EAAI,KAAK,IAAIC,EAAG,QAAQ,EAC3F,CAEA,OAAAR,EAAO,KAAK,IAAIA,EAAO,QAAY,QAAY,CAAG,EAC3CA,EAAO,GAChB,CAKQ,eAAsB,CAC5B,KAAK,eAAiB,SAAS,cAAc,KAAK,EAClD,KAAK,eAAe,UAAY,qBAChC,KAAK,eAAe,MAAM,QAAU;AAAA;AAAA,QAEhC,KAAK,OAAO,UAAU,SAAS,OAAO,EAAI,QAAU,MAAM;AAAA,QAC1D,KAAK,OAAO,UAAU,SAAS,QAAQ,EAAI,SAAW,KAAK;AAAA,oBAC/C,KAAK,OAAO,eAAe;AAAA,gBAC/B,KAAK,OAAO,WAAW,YAAY,KAAK,OAAO,WAAW;AAAA,uBACnD,KAAK,OAAO,YAAY;AAAA,oBAC3B,KAAK,OAAO,SAAS;AAAA;AAAA,iBAExB,KAAK,OAAO,MAAM;AAAA;AAAA;AAAA,aAGtB,KAAK,OAAO,aAAa;AAAA,MAIlB,KAAK,iBAAA,EAEb,QAAQuC,GAAU,CACxB,MAAME,EAAgB,KAAK,aAAaF,CAAM,EAC9C,KAAK,eAAe,YAAYE,CAAa,CAC/C,CAAC,EAED,KAAK,UAAU,YAAY,KAAK,cAAc,CAChD,CAKQ,kBAAmC,CAEzC,MAAME,EAAiC,CACrC,CAAE,GAAI,SAAU,KAAM,KAAM,MAAO,IAAA,EACnC,CAAE,GAAI,UAAW,KAAM,KAAM,MAAO,IAAA,EACpC,CAAE,GAAI,WAAY,KAAM,KAAM,MAAO,OAAA,EACrC,CAAE,GAAI,SAAU,KAAM,KAAM,MAAO,MAAA,EACnC,CAAE,GAAI,WAAY,KAAM,KAAM,MAAO,IAAA,EACrC,CAAE,GAAI,UAAW,KAAM,MAAO,MAAO,IAAA,EACrC,CAAE,GAAI,WAAY,KAAM,MAAO,MAAO,IAAA,EACtC,CAAE,GAAI,aAAc,KAAM,IAAK,MAAO,IAAA,CAAK,EAI7C,OAAI,KAAK,OAAO,SAAW,KAAK,OAAO,QAAQ,OAAS,EAC/C,KAAK,OAAO,QAAQ,IAAIC,IAAiB,CAC9C,GAAIA,EAAa,GACjB,KAAM,OAAOA,EAAa,MAAS,SAAWA,EAAa,KAAO,GAClE,MAAOA,EAAa,MACpB,KAAMA,EAAa,KACnB,MAAOA,EAAa,MACpB,WAAYA,EAAa,WACzB,YAAaA,EAAa,WAAA,EAC1B,EAGGD,CACT,CAKQ,aAAaR,EAAmC,CACtD,MAAMI,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,wBACnBA,EAAO,aAAa,YAAaJ,EAAO,EAAE,EAC1CI,EAAO,MAAQJ,EAAO,MAEtB,MAAMU,EAAaV,EAAO,MAAQ,KAAK,OAAO,WACxCW,EAAcX,EAAO,OAAS,0BAC9BY,EAAmBZ,EAAO,YAAc,0BAE9C,OAAAI,EAAO,MAAM,QAAU;AAAA,eACZM,CAAU;AAAA,gBACTA,CAAU;AAAA;AAAA;AAAA;AAAA,oBAINC,CAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAa3B,KAAK,cAAcP,EAAQJ,EAAO,IAAI,EAGtCI,EAAO,iBAAiB,aAAc,IAAM,CAC1CA,EAAO,MAAM,WAAaQ,EAC1BR,EAAO,MAAM,UAAY,aAC3B,CAAC,EAEDA,EAAO,iBAAiB,aAAc,IAAM,CAC1CA,EAAO,MAAM,WAAaO,EAC1BP,EAAO,MAAM,UAAY,UAC3B,CAAC,EAGD,KAAK,kBAAkBA,EAAQJ,CAAM,EAE9BI,CACT,CAKQ,cAAcA,EAAqBS,EAAkC,CACvE,OAAOA,GAAS,SAClBT,EAAO,UAAYS,EACVA,aAAgB,cACzBT,EAAO,UAAY,GACnBA,EAAO,YAAYS,CAAI,EAE3B,CAKQ,kBAAkBT,EAAqBJ,EAA4B,CAEzE,MAAMS,EAAe,KAAK,OAAO,SAAS,KAAKF,GAAOA,EAAI,KAAOP,EAAO,EAAE,EAEtES,GAAc,QAEhBL,EAAO,iBAAiB,QAAUU,GAAM,CACtCA,EAAE,gBAAA,EACFL,EAAa,QAAST,EAAO,GAAII,CAAM,CACzC,CAAC,EACS,CAAC,SAAU,UAAW,QAAQ,EAAE,SAASJ,EAAO,EAAE,EAMnDA,EAAO,KAAO,SAEvBI,EAAO,iBAAiB,QAAUU,GAAM,CACtCA,EAAE,gBAAA,EACF,KAAK,kBAAkBd,EAAO,GAAII,CAAM,CAC1C,CAAC,GAGDA,EAAO,iBAAiB,aAAc,IAAM,CAC1C,KAAK,kBAAkBJ,EAAO,GAAII,CAAM,CAC1C,CAAC,EAGDA,EAAO,iBAAiB,aAAc,IAAM,CAC1C,KAAK,uBAAuBJ,EAAO,EAAE,CACvC,CAAC,GAnBDI,EAAO,iBAAiB,QAAUU,GAAM,CACtCA,EAAE,gBAAA,EACF,KAAK,kBAAkBd,EAAO,GAAII,CAAM,CAC1C,CAAC,CAkBL,CAKQ,uBAAuBD,EAAwB,CAErD,WAAW,IAAM,CACf,OAAQA,EAAA,CACN,IAAK,UACH,MAAMY,EAAc,KAAK,eAAe,cAAc,mBAAmB,EACrEA,GAAe,CAACA,EAAY,QAAQ,QAAQ,GAC9CA,EAAY,OAAA,EAEd,MACF,IAAK,SACH,MAAMC,EAAa,KAAK,eAAe,cAAc,cAAc,EAC/DA,GAAc,CAACA,EAAW,QAAQ,QAAQ,GAC5CA,EAAW,OAAA,EAEb,KAAA,CAEN,EAAG,GAAG,CACR,CAKQ,kBAAkBb,EAAkBG,EAAkC,CAC5E,OAAQH,EAAA,CACN,IAAK,SACH,KAAK,aAAaG,CAAa,EAC/B,MACF,IAAK,UACH,KAAK,kBAAkBA,CAAa,EACpC,MACF,IAAK,WACH,KAAK,WAAWA,CAAa,EAC7B,MACF,IAAK,SACH,KAAK,aAAaA,CAAa,EAC/B,MACF,IAAK,WACH,KAAK,cAAA,EACL,MACF,IAAK,UACH,KAAK,OAAA,EACL,MACF,IAAK,WACH,KAAK,QAAA,EACL,MACF,IAAK,aACH,KAAK,iBAAA,EACL,KAAA,CAEN,CAKQ,aAAaA,EAAkC,CACrD,MAAMW,EAAiB,KAAK,eAAe,cAAc,mBAAmB,EAC5E,GAAIA,EAAgB,CAElBA,EAAe,OAAA,EACf,MACF,CAEA,MAAMC,EAAkB,SAAS,cAAc,KAAK,EACpDA,EAAgB,UAAY,mBAC5BA,EAAgB,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAchC,MAAMC,EAAc,SAAS,cAAc,OAAO,EAClDA,EAAY,KAAO,OACnBA,EAAY,YAAc,QAC1BA,EAAY,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQ5B,MAAMC,EAAmB,SAAS,cAAc,KAAK,EACrDA,EAAiB,UAAY,iBAC7BA,EAAiB,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA,MAMjCF,EAAgB,YAAYC,CAAW,EACvCD,EAAgB,YAAYE,CAAgB,EAG5C,KAAK,eAAe,aAAaF,EAAiBZ,CAAa,EAG/D,IAAIe,EACJF,EAAY,iBAAiB,QAAS,IAAM,CAC1C,aAAaE,CAAa,EAC1B,MAAMC,EAAQH,EAAY,MAAM,KAAA,EAGhC,GAAI,KAAK,gBAAgB,cAAe,CACtC,KAAK,eAAe,cAAcG,EAAOF,CAAgB,EACzD,MACF,CAEA,GAAIE,EAAM,OAAS,EAAG,CACpBF,EAAiB,UAAY,GAC7B,MACF,CAEAC,EAAgB,WAAW,SAAY,CACrC,GAAI,KAAK,gBAAgB,SACvB,GAAI,CACF,MAAME,EAAU,MAAM,KAAK,eAAe,SAASD,CAAK,EACxD,KAAK,qBAAqBC,EAASH,CAAgB,CACrD,OAASzF,EAAO,CACd,QAAQ,MAAM,QAASA,CAAK,EAC5ByF,EAAiB,UAAY,oDAC/B,MAGA,KAAK,qBAAqBE,EAAOF,CAAgB,CAErD,EAAG,GAAG,CACR,CAAC,EAGD,MAAMI,EAA6BC,GAAsB,CACnD,CAACP,EAAgB,SAASO,EAAM,MAAc,GAC9C,CAACnB,EAAc,SAASmB,EAAM,MAAc,IAC9CP,EAAgB,OAAA,EAChB,SAAS,oBAAoB,QAASM,CAAyB,EAC/D,SAAS,oBAAoB,UAAWE,CAAmB,EAE/D,EAGMA,EAAuBD,GAAyB,CAChDA,EAAM,MAAQ,WAChBP,EAAgB,OAAA,EAChB,SAAS,oBAAoB,QAASM,CAAyB,EAC/D,SAAS,oBAAoB,UAAWE,CAAmB,EAE/D,EAGA,WAAW,IAAM,CACf,SAAS,iBAAiB,QAASF,CAAyB,EAC5D,SAAS,iBAAiB,UAAWE,CAAmB,EAExDP,EAAY,MAAA,CACd,EAAG,GAAG,CACR,CAKQ,qBAAqBI,EAAyBxB,EAA8B,CAElF,GAAI,KAAK,gBAAgB,gBAAiB,CACxC,KAAK,eAAe,gBAAgBwB,EAASxB,CAAS,EACtD,MACF,CAKA,GAFAA,EAAU,UAAY,GAElBwB,EAAQ,SAAW,EAAG,CACxBxB,EAAU,UAAY,wDACtB,MACF,CAEAwB,EAAQ,QAAQI,GAAU,CACxB,MAAMC,EAAa,SAAS,cAAc,KAAK,EAC/CA,EAAW,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAO3BA,EAAW,UAAY;AAAA,8DACiCD,EAAO,IAAI;AAAA,qDACpBA,EAAO,OAAO;AAAA,QAG7DC,EAAW,iBAAiB,aAAc,IAAM,CAC9CA,EAAW,MAAM,gBAAkB,SACrC,CAAC,EAEDA,EAAW,iBAAiB,aAAc,IAAM,CAC9CA,EAAW,MAAM,gBAAkB,aACrC,CAAC,EAEDA,EAAW,iBAAiB,QAAS,IAAM,CACzC,KAAK,mBAAmBD,CAAM,EAC9B5B,EAAU,eAAe,OAAA,CAC3B,CAAC,EAEDA,EAAU,YAAY6B,CAAU,CAClC,CAAC,CACH,CAKQ,mBAAmBD,EAA4B,CAErD,KAAK,OAAO,OAAO,MAAM,CACvB,YAAalH,EAAO,WAAW,YAC7BkH,EAAO,UACPA,EAAO,SACPA,EAAO,QAAU,GAAA,EAEnB,SAAU,CAAA,CACX,EAGG,KAAK,gBAAgB,UACvB,KAAK,eAAe,SAASA,CAAM,CAEvC,CAKQ,qBAAqBL,EAAevB,EAA8B,CAExE,MAAM8B,EAA8B,CAClC,CACE,KAAM,UACN,QAAS,YACT,UAAW,OACX,SAAU,MACV,OAAQ,GAAA,EAEV,CACE,KAAM,UACN,QAAS,YACT,UAAW,OACX,SAAU,MACV,OAAQ,GAAA,EAEV,CACE,KAAM,UACN,QAAS,YACT,UAAW,OACX,SAAU,MACV,OAAQ,GAAA,CACV,EAGF,KAAK,qBAAqBA,EAAa9B,CAAS,CAClD,CAKQ,kBAAkBO,EAAkC,CAE1D,GADqB,KAAK,eAAe,cAAc,mBAAmB,EAExE,OAGF,MAAMwB,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,mBACjBA,EAAK,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcH,CAChB,CAAE,GAAI,eAAgB,KAAM,MAAO,KAAM,IAAA,EACzC,CAAE,GAAI,mBAAoB,KAAM,KAAM,KAAM,IAAA,EAC5C,CAAE,GAAI,oBAAqB,KAAM,KAAM,KAAM,KAAA,CAAM,EAG3C,QAAQC,GAAQ,CACxB,MAAMC,EAAW,SAAS,cAAc,KAAK,EAC7CA,EAAS,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASzBA,EAAS,UAAY,GAAGD,EAAK,IAAI,IAAIA,EAAK,IAAI,GAE9CC,EAAS,iBAAiB,aAAc,IAAM,CAC5CA,EAAS,MAAM,gBAAkB,SACnC,CAAC,EAEDA,EAAS,iBAAiB,aAAc,IAAM,CAC5CA,EAAS,MAAM,gBAAkB,aACnC,CAAC,EAEDA,EAAS,iBAAiB,QAAS,IAAM,CACvC,KAAK,wBAAwBD,EAAK,EAAE,EACpCD,EAAK,OAAA,CACP,CAAC,EAEDA,EAAK,YAAYE,CAAQ,CAC3B,CAAC,EAED,KAAK,eAAe,aAAaF,EAAMxB,CAAa,EAGpD,MAAM2B,EAAY,IAAM,CACtBH,EAAK,OAAA,CACP,EAGAA,EAAK,iBAAiB,aAAcG,CAAS,CAC/C,CAKQ,wBAAwBC,EAAsB,CACpD,OAAQA,EAAA,CACN,IAAK,eACH,KAAK,WAAW,oBAAA,EAChB,MACF,IAAK,mBACH,KAAK,WAAW,iBAAA,EAChB,MACF,IAAK,oBACH,KAAK,WAAW,SAAA,EACZ,KAAK,qBAAqB,SAC5B,KAAK,oBAAoB,QAAA,EAE3B,KAAA,CAEN,CAKQ,WAAW5B,EAAkC,CAEnD,MAAM6B,EADc,KAAK,OAAO,MAAM,OACH1H,EAAO,UAAU,QAChDA,EAAO,UAAU,QACjBA,EAAO,UAAU,QAErB,KAAK,OAAO,MAAM,KAAO0H,EAGzB7B,EAAc,UAAY6B,IAAe1H,EAAO,UAAU,QAAU,KAAO,IAC7E,CAKQ,aAAa6F,EAAkC,CAErD,GADqB,KAAK,eAAe,cAAc,cAAc,EAEnE,OAGF,MAAMwB,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,cACjBA,EAAK,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBrB,MAAMM,EAAiB,SAAS,cAAc,KAAK,EACnDA,EAAe,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA,MAK/BA,EAAe,UAAY,+FAE3B,KAAK,SAAS,QAAQC,GAAW,CAC/B,MAAMC,EAAc,SAAS,cAAc,KAAK,EAChDA,EAAY,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAUxBD,EAAQ,KAAO,KAAK,eAAiB,6BAA+B,EAAE;AAAA,QAG1E,MAAME,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,IAAMF,EAAQ,UACxBE,EAAU,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAO1B,MAAMC,EAAQ,SAAS,cAAc,MAAM,EAC3CA,EAAM,YAAcH,EAAQ,KAC5BG,EAAM,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA,QAMtB,MAAMC,EAAY,SAAS,cAAc,MAAM,EAC3CJ,EAAQ,KAAO,KAAK,iBACtBI,EAAU,YAAc,IACxBA,EAAU,MAAM,QAAU;AAAA;AAAA;AAAA;AAAA;AAAA,WAQ5BH,EAAY,YAAYC,CAAS,EACjCD,EAAY,YAAYE,CAAK,EAC7BF,EAAY,YAAYG,CAAS,EAEjCH,EAAY,iBAAiB,aAAc,IAAM,CAC3CD,EAAQ,KAAO,KAAK,iBACtBC,EAAY,MAAM,gBAAkB,UAExC,CAAC,EAEDA,EAAY,iBAAiB,aAAc,IAAM,CAC3CD,EAAQ,KAAO,KAAK,iBACtBC,EAAY,MAAM,gBAAkB,cAExC,CAAC,EAEDA,EAAY,iBAAiB,QAAS,IAAM,CAC1C,KAAK,cAAcD,EAAQ,EAAE,EAC7BP,EAAK,OAAA,CACP,CAAC,EAEDM,EAAe,YAAYE,CAAW,CACxC,CAAC,EAEDR,EAAK,YAAYM,CAAc,EAE/B,KAAK,eAAe,aAAaN,EAAMxB,CAAa,EAGpD,MAAM2B,EAAY,IAAM,CACtBH,EAAK,OAAA,CACP,EAGAA,EAAK,iBAAiB,aAAcG,CAAS,CAC/C,CAKQ,cAAcS,EAAyB,CAC7C,MAAML,EAAU,KAAK,SAAS,KAAKM,GAAMA,EAAG,KAAOD,CAAS,EACvDL,IAGL,KAAK,OAAO,cAAc,UAAA,EAG1B,KAAK,OAAO,cAAc,mBAAmBA,EAAQ,QAAQ,EAE7D,KAAK,eAAiBK,EACxB,CAKQ,eAAsB,CAC5B,GAAI,CAAC,KAAK,cAAe,CACvB,QAAQ,KAAK,mBAAmB,EAChC,MACF,CAEA,KAAK,OAAO,OAAO,MAAM,CACvB,YAAajI,EAAO,WAAW,YAC7B,KAAK,cAAc,UACnB,KAAK,cAAc,SACnB,KAAK,cAAc,MAAA,EAErB,SAAU,CAAA,CACX,CACH,CAKQ,QAAe,CACrB,MAAMmI,EAAc,KAAK,OAAO,OAAO,qBAAqB,OAC5D,KAAK,OAAO,OAAO,OAAO,KAAK,OAAO,OAAO,qBAAqB,OAAS,EAAG,EAC9E,MAAMC,EAAa,KAAK,OAAO,OAAO,qBAAqB,OAEvD,KAAK,cAAc,UACrB,KAAK,aAAa,SAASD,EAAaC,CAAU,CAEtD,CAKQ,SAAgB,CACtB,MAAMD,EAAc,KAAK,OAAO,OAAO,qBAAqB,OAC5D,KAAK,OAAO,OAAO,QAAQ,KAAK,OAAO,OAAO,qBAAqB,OAAS,EAAG,EAC/E,MAAMC,EAAa,KAAK,OAAO,OAAO,qBAAqB,OAEvD,KAAK,cAAc,WACrB,KAAK,aAAa,UAAUD,EAAaC,CAAU,CAEvD,CAKQ,kBAAyB,CAC1B,KAAK,aAGR,KAAK,eAAA,EAFL,KAAK,gBAAA,CAIT,CAKQ,iBAAwB,CAC9B,MAAM9C,EAAY,KAAK,OAAO,UAE1BA,EAAU,kBACZA,EAAU,kBAAA,EACAA,EAAkB,wBAC3BA,EAAkB,wBAAA,EACTA,EAAkB,qBAC3BA,EAAkB,oBAAA,EAGrB,KAAK,aAAe,GAGpB,MAAM+C,EAAmB,IAAM,CACzB,CAAC,SAAS,mBACV,CAAE,SAAiB,yBACnB,CAAE,SAAiB,sBACrB,KAAK,aAAe,GACpB,SAAS,oBAAoB,mBAAoBA,CAAgB,EACjE,SAAS,oBAAoB,yBAA0BA,CAAgB,EACvE,SAAS,oBAAoB,qBAAsBA,CAAgB,EAEvE,EAEA,SAAS,iBAAiB,mBAAoBA,CAAgB,EAC9D,SAAS,iBAAiB,yBAA0BA,CAAgB,EACpE,SAAS,iBAAiB,qBAAsBA,CAAgB,CAClE,CAKQ,gBAAuB,CACzB,SAAS,eACX,SAAS,eAAA,EACC,SAAiB,qBAC1B,SAAiB,qBAAA,EACR,SAAiB,kBAC1B,SAAiB,iBAAA,EAGpB,KAAK,aAAe,EACtB,CAKA,SAAgB,CACV,KAAK,gBAAkB,KAAK,eAAe,YAC7C,KAAK,eAAe,WAAW,YAAY,KAAK,cAAc,EAEhE,KAAK,WAAW,QAAA,CAClB,CACF,CCjhCO,SAASC,GAAoD,CAClE,OAAO,IAAItI,EAAO,2BAA2B,CAC3C,IAAK,yEACL,WAAY,CAAC,IAAK,IAAK,IAAK,GAAG,EAC/B,aAAc,EACd,aAAc,GACd,OAAQ,QAAA,CACT,CACH,CAEA,eAAsBuI,EACpBC,EACArI,EACAsI,EAAuB,CAAE,UAAW,YAAa,SAAU,WAAY,OAAQ,IAAM,MAAO,IAAK,QAAS,GAC7C,CAC7DC,EAAAA,IAAI,mBAAsB,wLAC1B,MAAM3I,EAAS,IAAI4I,EAAAA,OAAOH,EAAa,CACrC,SAAU,GACV,UAAW,GACX,gBAAiB,GACjB,GAAGrI,CAAA,CACJ,EAED,MAAI,CAACA,EAAQ,iBAAmB,CAACA,EAAQ,UACvCJ,EAAO,gBAAkB,MAAM6I,0BAAA,GAG7BzI,EAAQ,UAAY,UACtBJ,EAAO,cAAc,UAAA,EACrBA,EAAO,cAAc,mBAAmBuI,GAAgB,GAEtDG,GAEF1I,EAAO,OAAO,MAAM,CAClB,YAAaC,EAAO,WAAW,YAAYyI,EAAU,UAAWA,EAAU,SAAUA,EAAU,MAAM,EACpG,YAAa,CACX,QAASzI,EAAO,KAAK,UAAUyI,EAAU,SAAW,CAAC,EACrD,MAAOzI,EAAO,KAAK,UAAUyI,EAAU,OAAS,GAAG,CAAA,CACrD,CACD,EAEF1I,EAAO,aAAa,gBAAgC,MAAM,QAAU,OAC9D,CAAE,OAAAA,EAAQ,cAAe0I,CAAA,CAClC,CCzFA,MAAAvG,EAAe,CACb,iBAAAmD,EACA,WAAAvF,EACA,WAAAyI,CACF"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "vmap-cesium-toolbar",
3
- "version": "1.0.0",
2
+ "name": "@xingm/vmap-cesium-toolbar",
3
+ "version": "0.0.1-beta.2",
4
4
  "description": "A powerful Cesium map toolbar plugin with drawing, measurement, and interaction features",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -20,8 +20,8 @@
20
20
  "./style": "./style.css"
21
21
  },
22
22
  "peerDependencies": {
23
- "vue": "^3.0.0",
24
- "cesium": "^1.100.0"
23
+ "cesium": "^1.100.0",
24
+ "vue": "^3.0.0"
25
25
  },
26
26
  "keywords": [
27
27
  "cesium",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingm/vmap-cesium-toolbar",
3
- "version": "0.0.1-beta.1",
3
+ "version": "0.0.1-beta.3",
4
4
  "description": "A powerful Cesium map toolbar plugin with drawing, measurement, and interaction features",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,22 +29,21 @@
29
29
  "type-check": "vue-tsc --noEmit"
30
30
  },
31
31
  "peerDependencies": {
32
- "vue": "^3.0.0",
33
- "cesium": "^1.100.0"
32
+ "cesium": "^1.100.0",
33
+ "vue": "^3.0.0"
34
34
  },
35
35
  "dependencies": {
36
36
  "vue": "^3.5.18"
37
37
  },
38
38
  "devDependencies": {
39
- "@cesium/engine": "^19.0.0",
40
39
  "@types/cesium": "^1.70.4",
41
40
  "@vitejs/plugin-vue": "^6.0.1",
42
41
  "cesium": "^1.132.0",
42
+ "rollup-plugin-dts": "^6.1.0",
43
43
  "vite": "^7.1.2",
44
44
  "vite-plugin-cesium": "^1.2.23",
45
45
  "vite-plugin-static-copy": "^3.1.2",
46
- "vue-tsc": "^3.0.5",
47
- "rollup-plugin-dts": "^6.1.0"
46
+ "vue-tsc": "^3.0.5"
48
47
  },
49
48
  "keywords": [
50
49
  "cesium",