mirror of
				https://github.com/ethan-zf/cesium-plot-js.git
				synced 2025-11-04 01:04:18 +00:00 
			
		
		
		
	upd: 增加半径属性显示
This commit is contained in:
		
							parent
							
								
									20d5741675
								
							
						
					
					
						commit
						5251862c94
					
				@ -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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user