From 5251862c94f4b5c65b68dc000e53839bb33e0f8f Mon Sep 17 00:00:00 2001 From: muxuming1 Date: Tue, 16 Sep 2025 10:00:30 +0800 Subject: [PATCH] =?UTF-8?q?upd:=20=E5=A2=9E=E5=8A=A0=E5=8D=8A=E5=BE=84?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/polygon/circle.ts | 208 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/src/polygon/circle.ts b/src/polygon/circle.ts index aa0b1fb..7bb4aa1 100644 --- a/src/polygon/circle.ts +++ b/src/polygon/circle.ts @@ -8,6 +8,8 @@ import { PolygonStyle } from '../interface'; export default class Circle extends Base { points: Cartesian3[] = []; freehand: boolean; + radius: number = 0; // 添加半径属性 + radiusLabelEntity: any; // 添加半径标签实体 constructor(cesium: any, viewer: any, style?: PolygonStyle) { super(cesium, viewer, style); @@ -32,6 +34,96 @@ export default class Circle extends Base { } } + /** + * 计算标签位置(圆心到右侧圆边的中间位置) + */ + calculateLabelPosition(): Cartesian3 { + if (this.points.length < 1) { + return this.points[0]; + } + + const centerCartesian = this.points[0]; + + // 计算局部坐标系(东-北-上) + const localFrame = this.cesium.Transforms.eastNorthUpToFixedFrame(centerCartesian); + + // 提取东向单位向量(右侧方向) + const eastVector = this.cesium.Cartesian3.fromElements( + localFrame[0], + localFrame[1], + localFrame[2], + new this.cesium.Cartesian3(), + ); + + // 归一化方向向量 + this.cesium.Cartesian3.normalize(eastVector, eastVector); + + // 计算半径的一半距离的偏移量(向右) + const halfRadiusOffset = this.cesium.Cartesian3.multiplyByScalar( + eastVector, + this.radius / 2, // 半径的一半 + new this.cesium.Cartesian3(), + ); + + // 计算标签位置(圆心 + 向右偏移半径的一半) + const labelPosition = this.cesium.Cartesian3.add( + centerCartesian, + halfRadiusOffset, + new this.cesium.Cartesian3(), + ); + + // 投影到椭球表面 + const surfacePosition = this.cesium.Ellipsoid.WGS84.scaleToGeodeticSurface( + labelPosition, + new this.cesium.Cartesian3(), + ); + + return surfacePosition || labelPosition; + } + + /** + * 创建或更新半径标签 + */ + createRadiusLabel() { + if (this.points.length >= 1 && this.radius > 0) { + const labelPosition = this.calculateLabelPosition(); + const radiusText = this.formatRadiusText(this.radius); + + if (!this.radiusLabelEntity) { + this.radiusLabelEntity = this.dataSource.entities.add({ + position: labelPosition, + label: { + text: radiusText, + font: '16pt sans-serif', + fillColor: this.cesium.Color.WHITE, + outlineColor: this.cesium.Color.BLACK, + outlineWidth: 2, + style: this.cesium.LabelStyle.FILL_AND_OUTLINE, + pixelOffset: new this.cesium.Cartesian2(0, 0), + horizontalOrigin: this.cesium.HorizontalOrigin.CENTER, + verticalOrigin: this.cesium.VerticalOrigin.CENTER, + disableDepthTestDistance: Number.POSITIVE_INFINITY, + heightReference: this.cesium.HeightReference.CLAMP_TO_GROUND + } + }); + } else { + // 更新现有标签的文本和位置 + this.radiusLabelEntity.position = labelPosition; + this.radiusLabelEntity.label.text = radiusText; + } + } + } + + /** + * 更新半径标签位置(专门用于拖动时的位置更新) + */ + updateRadiusLabelPosition() { + if (this.radiusLabelEntity && this.points.length >= 1 && this.radius > 0) { + const labelPosition = this.calculateLabelPosition(); + this.radiusLabelEntity.position = labelPosition; + } + } + /** * Draw a shape based on mouse movement points during the initial drawing. */ @@ -40,6 +132,7 @@ export default class Circle extends Base { const geometryPoints = this.createGraphic(tempPoints); this.setGeometryPoints(geometryPoints); this.drawPolygon(); + this.updateRadiusLabel(); // 更新半径标签 } /** @@ -50,6 +143,8 @@ export default class Circle extends Base { const geometryPoints = this.createGraphic(this.points); this.setGeometryPoints(geometryPoints); this.drawPolygon(); + this.updateRadiusLabel(); // 更新半径标签 + this.updateRadiusLabelPosition(); // 确保标签位置跟随圆心 } createGraphic(positions: Cartesian3[]) { @@ -60,12 +155,14 @@ export default class Circle extends Base { const pnt2 = lnglatPoints[1]; const radius = Utils.MathDistance(center, pnt2); + this.radius = radius; // 保存半径数据 const res = this.generatePoints(positions); const temp = [].concat(...res); const cartesianPoints = this.cesium.Cartesian3.fromDegreesArray(temp); return cartesianPoints; } + generatePoints(positions) { const points = []; const degreesPerRadian = 180.0 / Math.PI; @@ -81,6 +178,8 @@ export default class Circle extends Base { // 计算两点之间的距离作为半径(米) const radius = this.cesium.Cartesian3.distance(centerCartesian, secondPointCartesian); + this.radius = radius; // 保存半径数据(米为单位) + // 计算局部坐标系(东-北-上) const localFrame = this.cesium.Transforms.eastNorthUpToFixedFrame(centerCartesian); // 提取东向和北向单位向量 @@ -141,7 +240,116 @@ export default class Circle extends Base { } return points; } + getPoints() { return this.points; } + + /** + * 获取圆的半径 + * @returns {number} 半径值(米) + */ + getRadius(): number { + return this.radius; + } + + /** + * 设置圆的半径 + * @param {number} radius 半径值(米) + */ + setRadius(radius: number): void { + this.radius = radius; + } + + /** + * 获取圆的直径 + * @returns {number} 直径值(米) + */ + getDiameter(): number { + return this.radius * 2; + } + + /** + * 获取圆的面积 + * @returns {number} 面积值(平方米) + */ + getArea(): number { + return Math.PI * this.radius * this.radius; + } + + /** + * 获取圆的周长 + * @returns {number} 周长值(米) + */ + getCircumference(): number { + return 2 * Math.PI * this.radius; + } + + /** + * 更新半径标签 + */ + updateRadiusLabel() { + if (this.points.length >= 1 && this.radius > 0) { + this.createRadiusLabel(); + } + } + + /** + * 格式化半径文本显示 + */ + formatRadiusText(radius: number): string { + if (radius >= 1000) { + return `半径: ${(radius / 1000).toFixed(2)} km`; + } else { + return `半径: ${radius.toFixed(2)} m`; + } + } + + /** + * 重写drawPolygon方法,添加半径标签显示 + */ + drawPolygon() { + super.drawPolygon(); + this.updateRadiusLabel(); + } + + /** + * 重写draggable方法,确保拖动时标签跟随移动 + */ + draggable() { + super.draggable(); + + // 监听拖动事件,确保标签位置实时更新 + if (this.dragEventHandler) { + const originalMouseMoveHandler = this.dragEventHandler.getInputAction(this.cesium.ScreenSpaceEventType.MOUSE_MOVE); + + this.dragEventHandler.setInputAction((event) => { + if (originalMouseMoveHandler) { + originalMouseMoveHandler(event); + } + // 在拖动过程中实时更新标签位置 + this.updateRadiusLabelPosition(); + }, this.cesium.ScreenSpaceEventType.MOUSE_MOVE); + } + } + + /** + * 重写remove方法,确保移除半径标签 + */ + remove() { + if (this.radiusLabelEntity) { + this.dataSource.entities.remove(this.radiusLabelEntity); + this.radiusLabelEntity = null; + } + super.remove(); + } + + /** + * 显示/隐藏半径标签 + */ + showRadiusLabel(show: boolean = true) { + if (this.radiusLabelEntity) { + this.radiusLabelEntity.label.show = show; + } + } }