mirror of
				https://github.com/ethan-zf/cesium-plot-js.git
				synced 2025-11-04 01:04:18 +00:00 
			
		
		
		
	Merge 5251862c94 into a8b7f2b46d
				
					
				
			This commit is contained in:
		
						commit
						d8268fdd98
					
				
							
								
								
									
										39
									
								
								src/base.ts
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/base.ts
									
									
									
									
									
								
							@ -36,6 +36,7 @@ export default class Base {
 | 
				
			|||||||
  styleCache: GeometryStyle | undefined;
 | 
					  styleCache: GeometryStyle | undefined;
 | 
				
			||||||
  minPointsForShape: number = 0;
 | 
					  minPointsForShape: number = 0;
 | 
				
			||||||
  tempLineEntity: CesiumTypeOnly.Entity;
 | 
					  tempLineEntity: CesiumTypeOnly.Entity;
 | 
				
			||||||
 | 
					  dataSource: CesiumTypeOnly.CustomDataSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(cesium: CesiumTypeOnly, viewer: CesiumTypeOnly.Viewer, style?: GeometryStyle) {
 | 
					  constructor(cesium: CesiumTypeOnly, viewer: CesiumTypeOnly.Viewer, style?: GeometryStyle) {
 | 
				
			||||||
    this.cesium = cesium;
 | 
					    this.cesium = cesium;
 | 
				
			||||||
@ -49,7 +50,8 @@ export default class Base {
 | 
				
			|||||||
    // Disable default behavior for double-clicking on entities.
 | 
					    // Disable default behavior for double-clicking on entities.
 | 
				
			||||||
    viewer.trackedEntity = undefined;
 | 
					    viewer.trackedEntity = undefined;
 | 
				
			||||||
    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
 | 
					    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
 | 
				
			||||||
 | 
					    this.dataSource = new this.cesium.CustomDataSource("entity");
 | 
				
			||||||
 | 
					    viewer.dataSources.add(this.dataSource);
 | 
				
			||||||
    this.onClick();
 | 
					    this.onClick();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -134,6 +136,7 @@ export default class Base {
 | 
				
			|||||||
          this.eventDispatcher.dispatchEvent('editEnd', this.getPoints());
 | 
					          this.eventDispatcher.dispatchEvent('editEnd', this.getPoints());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else if (this.state === 'static') {
 | 
					      } else if (this.state === 'static') {
 | 
				
			||||||
 | 
					        console.log('here')
 | 
				
			||||||
        //When drawing multiple shapes, the click events for all shapes are triggered. Only when hitting a completed shape should it enter editing mode.
 | 
					        //When drawing multiple shapes, the click events for all shapes are triggered. Only when hitting a completed shape should it enter editing mode.
 | 
				
			||||||
        if (hitEntities && activeEntity.id === pickedObject.id.id) {
 | 
					        if (hitEntities && activeEntity.id === pickedObject.id.id) {
 | 
				
			||||||
          const pickedGraphics = this.type === 'line' ? pickedObject.id.polyline : pickedObject.id.polygon;
 | 
					          const pickedGraphics = this.type === 'line' ? pickedObject.id.polyline : pickedObject.id.polygon;
 | 
				
			||||||
@ -182,7 +185,7 @@ export default class Base {
 | 
				
			|||||||
  finishDrawing() {
 | 
					  finishDrawing() {
 | 
				
			||||||
    // Some polygons draw a separate line between the first two points before drawing the complete shape;
 | 
					    // Some polygons draw a separate line between the first two points before drawing the complete shape;
 | 
				
			||||||
    // this line should be removed after drawing is complete.
 | 
					    // this line should be removed after drawing is complete.
 | 
				
			||||||
    this.type === 'polygon' && this.lineEntity && this.viewer.entities.remove(this.lineEntity);
 | 
					    this.type === 'polygon' && this.lineEntity && this.dataSource.entities.remove(this.lineEntity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.removeMoveListener();
 | 
					    this.removeMoveListener();
 | 
				
			||||||
    // Editable upon initial drawing completion.
 | 
					    // Editable upon initial drawing completion.
 | 
				
			||||||
@ -238,7 +241,7 @@ export default class Base {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
    if (!this.polygonEntity) {
 | 
					    if (!this.polygonEntity) {
 | 
				
			||||||
      const style = this.style as PolygonStyle;
 | 
					      const style = this.style as PolygonStyle;
 | 
				
			||||||
      this.polygonEntity = this.viewer.entities.add({
 | 
					      this.polygonEntity = this.dataSource.entities.add({
 | 
				
			||||||
        polygon: new this.cesium.PolygonGraphics({
 | 
					        polygon: new this.cesium.PolygonGraphics({
 | 
				
			||||||
          hierarchy: new this.cesium.CallbackProperty(callback, false),
 | 
					          hierarchy: new this.cesium.CallbackProperty(callback, false),
 | 
				
			||||||
          show: true,
 | 
					          show: true,
 | 
				
			||||||
@ -247,7 +250,7 @@ export default class Base {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Due to limitations in PolygonGraphics outlining, a separate line style is drawn.
 | 
					      // Due to limitations in PolygonGraphics outlining, a separate line style is drawn.
 | 
				
			||||||
      this.outlineEntity = this.viewer.entities.add({
 | 
					      this.outlineEntity = this.dataSource.entities.add({
 | 
				
			||||||
        polyline: {
 | 
					        polyline: {
 | 
				
			||||||
          positions: new this.cesium.CallbackProperty(() => {
 | 
					          positions: new this.cesium.CallbackProperty(() => {
 | 
				
			||||||
            return [...this.geometryPoints, this.geometryPoints[0]];
 | 
					            return [...this.geometryPoints, this.geometryPoints[0]];
 | 
				
			||||||
@ -281,12 +284,12 @@ export default class Base {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  removeTempLine() {
 | 
					  removeTempLine() {
 | 
				
			||||||
    if (this.tempLineEntity) {
 | 
					    if (this.tempLineEntity) {
 | 
				
			||||||
      this.viewer.entities.remove(this.tempLineEntity);
 | 
					      this.dataSource.entities.remove(this.tempLineEntity);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  addLineEntity(style: LineStyle) {
 | 
					  addLineEntity(style: LineStyle) {
 | 
				
			||||||
    const entity = this.viewer.entities.add({
 | 
					    const entity = this.dataSource.entities.add({
 | 
				
			||||||
      polyline: {
 | 
					      polyline: {
 | 
				
			||||||
        positions: new this.cesium.CallbackProperty(() => this.geometryPoints, false),
 | 
					        positions: new this.cesium.CallbackProperty(() => this.geometryPoints, false),
 | 
				
			||||||
        width: style.lineWidth,
 | 
					        width: style.lineWidth,
 | 
				
			||||||
@ -323,7 +326,7 @@ export default class Base {
 | 
				
			|||||||
      //   },
 | 
					      //   },
 | 
				
			||||||
      // });
 | 
					      // });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return this.viewer.entities.add({
 | 
					      return this.dataSource.entities.add({
 | 
				
			||||||
        position,
 | 
					        position,
 | 
				
			||||||
        point: {
 | 
					        point: {
 | 
				
			||||||
          pixelSize: 10,
 | 
					          pixelSize: 10,
 | 
				
			||||||
@ -385,7 +388,7 @@ export default class Base {
 | 
				
			|||||||
  removeControlPoints() {
 | 
					  removeControlPoints() {
 | 
				
			||||||
    if (this.controlPoints.length > 0) {
 | 
					    if (this.controlPoints.length > 0) {
 | 
				
			||||||
      this.controlPoints.forEach((entity: CesiumTypeOnly.Entity) => {
 | 
					      this.controlPoints.forEach((entity: CesiumTypeOnly.Entity) => {
 | 
				
			||||||
        this.viewer.entities.remove(entity);
 | 
					        this.dataSource.entities.remove(entity);
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_DOWN);
 | 
					      this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.LEFT_DOWN);
 | 
				
			||||||
      this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.MOUSE_MOVE);
 | 
					      this.controlPointsEventHandler.removeInputAction(this.cesium.ScreenSpaceEventType.MOUSE_MOVE);
 | 
				
			||||||
@ -574,7 +577,7 @@ export default class Base {
 | 
				
			|||||||
    setTimeout(() => {
 | 
					    setTimeout(() => {
 | 
				
			||||||
      const graphics = entity.polygon || entity.polyline || entity.billboard;
 | 
					      const graphics = entity.polygon || entity.polyline || entity.billboard;
 | 
				
			||||||
      let startAlpha: number;
 | 
					      let startAlpha: number;
 | 
				
			||||||
      let material = graphics.material;
 | 
					      const material = graphics.material;
 | 
				
			||||||
      if (material) {
 | 
					      if (material) {
 | 
				
			||||||
        if (material.image && material.color.alpha !== undefined) {
 | 
					        if (material.image && material.color.alpha !== undefined) {
 | 
				
			||||||
          // Texture material, setting the alpha channel in the color of the custom ImageFlowMaterialProperty.
 | 
					          // Texture material, setting the alpha channel in the color of the custom ImageFlowMaterialProperty.
 | 
				
			||||||
@ -712,7 +715,7 @@ export default class Base {
 | 
				
			|||||||
          // The face-arrow determined by three points, with the animation starting from the midpoint of the line connecting the first two points.
 | 
					          // The face-arrow determined by three points, with the animation starting from the midpoint of the line connecting the first two points.
 | 
				
			||||||
          startPoint = this.cesium.Cartesian3.midpoint(points[0], points[1], new this.cesium.Cartesian3());
 | 
					          startPoint = this.cesium.Cartesian3.midpoint(points[0], points[1], new this.cesium.Cartesian3());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        let endPoint = points[movingPointIndex];
 | 
					        const endPoint = points[movingPointIndex];
 | 
				
			||||||
        // To dynamically add points between the startPoint and endPoint, consistent with the initial drawing logic,
 | 
					        // To dynamically add points between the startPoint and endPoint, consistent with the initial drawing logic,
 | 
				
			||||||
        // update the point at index movingPointIndex in the points array with the newPosition,
 | 
					        // update the point at index movingPointIndex in the points array with the newPosition,
 | 
				
			||||||
        // generate the arrow, and execute the animation.
 | 
					        // generate the arrow, and execute the animation.
 | 
				
			||||||
@ -754,12 +757,12 @@ export default class Base {
 | 
				
			|||||||
        const startPointLeft = this.cesium.Cartesian3.midpoint(points[0], midPoint, new this.cesium.Cartesian3());
 | 
					        const startPointLeft = this.cesium.Cartesian3.midpoint(points[0], midPoint, new this.cesium.Cartesian3());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const startPointRight = this.cesium.Cartesian3.midpoint(midPoint, points[1], new this.cesium.Cartesian3());
 | 
					        const startPointRight = this.cesium.Cartesian3.midpoint(midPoint, points[1], new this.cesium.Cartesian3());
 | 
				
			||||||
        let endPointLeft = points[3];
 | 
					        const endPointLeft = points[3];
 | 
				
			||||||
        let endPointRight = points[2];
 | 
					        const endPointRight = points[2];
 | 
				
			||||||
        const t = elapsedTime / duration;
 | 
					        const t = elapsedTime / duration;
 | 
				
			||||||
        const controlPoint = this.getBezierControlPointforGrowthAnimation();
 | 
					        const controlPoint = this.getBezierControlPointforGrowthAnimation();
 | 
				
			||||||
        let curveControlPointsLeft = [startPointLeft, controlPoint.left, endPointLeft];
 | 
					        const curveControlPointsLeft = [startPointLeft, controlPoint.left, endPointLeft];
 | 
				
			||||||
        let curveControlPointsRight = [startPointRight, controlPoint.right, endPointRight];
 | 
					        const curveControlPointsRight = [startPointRight, controlPoint.right, endPointRight];
 | 
				
			||||||
        const newPositionLeft = this.getNewPosition(curveControlPointsLeft, t);
 | 
					        const newPositionLeft = this.getNewPosition(curveControlPointsLeft, t);
 | 
				
			||||||
        const newPositionRight = this.getNewPosition(curveControlPointsRight, t);
 | 
					        const newPositionRight = this.getNewPosition(curveControlPointsRight, t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -800,7 +803,7 @@ export default class Base {
 | 
				
			|||||||
      return this.cesium.Cartesian3.fromDegrees(p[0], p[1]);
 | 
					      return this.cesium.Cartesian3.fromDegrees(p[0], p[1]);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let newPosition = this.interpolateAlongCurve(curvePoints, t);
 | 
					    const newPosition = this.interpolateAlongCurve(curvePoints, t);
 | 
				
			||||||
    return newPosition;
 | 
					    return newPosition;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -819,13 +822,13 @@ export default class Base {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  remove() {
 | 
					  remove() {
 | 
				
			||||||
    if (this.type === 'polygon') {
 | 
					    if (this.type === 'polygon') {
 | 
				
			||||||
      this.viewer.entities.remove(this.polygonEntity);
 | 
					      this.dataSource.entities.remove(this.polygonEntity);
 | 
				
			||||||
      this.viewer.entities.remove(this.outlineEntity);
 | 
					      this.dataSource.entities.remove(this.outlineEntity);
 | 
				
			||||||
      this.polygonEntity = null;
 | 
					      this.polygonEntity = null;
 | 
				
			||||||
      this.outlineEntity = null;
 | 
					      this.outlineEntity = null;
 | 
				
			||||||
      this.lineEntity = null;
 | 
					      this.lineEntity = null;
 | 
				
			||||||
    } else if (this.type === 'line') {
 | 
					    } else if (this.type === 'line') {
 | 
				
			||||||
      this.viewer.entities.remove(this.lineEntity);
 | 
					      this.dataSource.entities.remove(this.lineEntity);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.removeClickListener();
 | 
					    this.removeClickListener();
 | 
				
			||||||
    this.removeMoveListener();
 | 
					    this.removeMoveListener();
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ import { PolygonStyle } from '../interface';
 | 
				
			|||||||
export default class Circle extends Base {
 | 
					export default class Circle extends Base {
 | 
				
			||||||
  points: Cartesian3[] = [];
 | 
					  points: Cartesian3[] = [];
 | 
				
			||||||
  freehand: boolean;
 | 
					  freehand: boolean;
 | 
				
			||||||
 | 
					  radius: number = 0; // 添加半径属性
 | 
				
			||||||
 | 
					  radiusLabelEntity: any; // 添加半径标签实体
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(cesium: any, viewer: any, style?: PolygonStyle) {
 | 
					  constructor(cesium: any, viewer: any, style?: PolygonStyle) {
 | 
				
			||||||
    super(cesium, viewer, style);
 | 
					    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.
 | 
					   * 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);
 | 
					    const geometryPoints = this.createGraphic(tempPoints);
 | 
				
			||||||
    this.setGeometryPoints(geometryPoints);
 | 
					    this.setGeometryPoints(geometryPoints);
 | 
				
			||||||
    this.drawPolygon();
 | 
					    this.drawPolygon();
 | 
				
			||||||
 | 
					    this.updateRadiusLabel(); // 更新半径标签
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
@ -50,6 +143,8 @@ export default class Circle extends Base {
 | 
				
			|||||||
    const geometryPoints = this.createGraphic(this.points);
 | 
					    const geometryPoints = this.createGraphic(this.points);
 | 
				
			||||||
    this.setGeometryPoints(geometryPoints);
 | 
					    this.setGeometryPoints(geometryPoints);
 | 
				
			||||||
    this.drawPolygon();
 | 
					    this.drawPolygon();
 | 
				
			||||||
 | 
					    this.updateRadiusLabel(); // 更新半径标签
 | 
				
			||||||
 | 
					    this.updateRadiusLabelPosition(); // 确保标签位置跟随圆心
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createGraphic(positions: Cartesian3[]) {
 | 
					  createGraphic(positions: Cartesian3[]) {
 | 
				
			||||||
@ -60,21 +155,88 @@ export default class Circle extends Base {
 | 
				
			|||||||
    const pnt2 = lnglatPoints[1];
 | 
					    const pnt2 = lnglatPoints[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const radius = Utils.MathDistance(center, pnt2);
 | 
					    const radius = Utils.MathDistance(center, pnt2);
 | 
				
			||||||
 | 
					    this.radius = radius; // 保存半径数据
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const res = this.generatePoints(center, radius);
 | 
					    const res = this.generatePoints(positions);
 | 
				
			||||||
    const temp = [].concat(...res);
 | 
					    const temp = [].concat(...res);
 | 
				
			||||||
    const cartesianPoints = this.cesium.Cartesian3.fromDegreesArray(temp);
 | 
					    const cartesianPoints = this.cesium.Cartesian3.fromDegreesArray(temp);
 | 
				
			||||||
    return cartesianPoints;
 | 
					    return cartesianPoints;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  generatePoints(center, radius) {
 | 
					  generatePoints(positions) {
 | 
				
			||||||
    let x, y, angle;
 | 
					 | 
				
			||||||
    const points = [];
 | 
					    const points = [];
 | 
				
			||||||
 | 
					    const degreesPerRadian = 180.0 / Math.PI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 验证输入格式
 | 
				
			||||||
 | 
					    if (!positions || positions.length !== 2) {
 | 
				
			||||||
 | 
					      console.error('输入参数格式错误,需要包含两个世界坐标点');
 | 
				
			||||||
 | 
					      return points;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 提取中心点和第二点(均为Cartesian3世界坐标)
 | 
				
			||||||
 | 
					    const centerCartesian = positions[0];
 | 
				
			||||||
 | 
					    const secondPointCartesian = positions[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 计算两点之间的距离作为半径(米)
 | 
				
			||||||
 | 
					    const radius = this.cesium.Cartesian3.distance(centerCartesian, secondPointCartesian);
 | 
				
			||||||
 | 
					    this.radius = radius; // 保存半径数据(米为单位)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // 计算局部坐标系(东-北-上)
 | 
				
			||||||
 | 
					    const localFrame = this.cesium.Transforms.eastNorthUpToFixedFrame(centerCartesian);
 | 
				
			||||||
 | 
					    // 提取东向和北向单位向量
 | 
				
			||||||
 | 
					    const eastVector = this.cesium.Cartesian3.fromElements(
 | 
				
			||||||
 | 
					      localFrame[0],
 | 
				
			||||||
 | 
					      localFrame[1],
 | 
				
			||||||
 | 
					      localFrame[2],
 | 
				
			||||||
 | 
					      new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    const northVector = this.cesium.Cartesian3.fromElements(
 | 
				
			||||||
 | 
					      localFrame[4],
 | 
				
			||||||
 | 
					      localFrame[5],
 | 
				
			||||||
 | 
					      localFrame[6],
 | 
				
			||||||
 | 
					      new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 归一化方向向量
 | 
				
			||||||
 | 
					    this.cesium.Cartesian3.normalize(eastVector, eastVector);
 | 
				
			||||||
 | 
					    this.cesium.Cartesian3.normalize(northVector, northVector);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 生成圆周点
 | 
				
			||||||
    for (let i = 0; i <= 100; i++) {
 | 
					    for (let i = 0; i <= 100; i++) {
 | 
				
			||||||
      angle = (Math.PI * 2 * i) / 100;
 | 
					      const angle = (Math.PI * 2 * i) / 100;
 | 
				
			||||||
      x = center[0] + radius * Math.cos(angle);
 | 
					      const cosAngle = Math.cos(angle);
 | 
				
			||||||
      y = center[1] + radius * Math.sin(angle);
 | 
					      const sinAngle = Math.sin(angle);
 | 
				
			||||||
      points.push([x, y]);
 | 
					
 | 
				
			||||||
 | 
					      // 计算偏移量(基于米)
 | 
				
			||||||
 | 
					      const eastOffset = this.cesium.Cartesian3.multiplyByScalar(
 | 
				
			||||||
 | 
					        eastVector,
 | 
				
			||||||
 | 
					        radius * cosAngle,
 | 
				
			||||||
 | 
					        new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      const northOffset = this.cesium.Cartesian3.multiplyByScalar(
 | 
				
			||||||
 | 
					        northVector,
 | 
				
			||||||
 | 
					        radius * sinAngle,
 | 
				
			||||||
 | 
					        new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // 计算目标点
 | 
				
			||||||
 | 
					      const targetPoint = this.cesium.Cartesian3.add(
 | 
				
			||||||
 | 
					        centerCartesian,
 | 
				
			||||||
 | 
					        this.cesium.Cartesian3.add(eastOffset, northOffset, new this.cesium.Cartesian3()),
 | 
				
			||||||
 | 
					        new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // 投影到椭球表面
 | 
				
			||||||
 | 
					      const surfacePoint = this.cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(
 | 
				
			||||||
 | 
					        targetPoint,
 | 
				
			||||||
 | 
					        new this.cesium.Cartesian3(),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // 转换回经纬度
 | 
				
			||||||
 | 
					      const cartographic = this.cesium.Cartographic.fromCartesian(surfacePoint);
 | 
				
			||||||
 | 
					      const longitude = cartographic.longitude * degreesPerRadian;
 | 
				
			||||||
 | 
					      const latitude = cartographic.latitude * degreesPerRadian;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      points.push([longitude, latitude]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return points;
 | 
					    return points;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -82,4 +244,112 @@ export default class Circle extends Base {
 | 
				
			|||||||
  getPoints() {
 | 
					  getPoints() {
 | 
				
			||||||
    return this.points;
 | 
					    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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user