cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形)

这篇具有很好参考价值的文章主要介绍了cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上一篇学习了创建实体的一些基础知识,但有时还需要我们使用鼠标进行手动绘制,这一篇就来进行鼠标绘制实体的实现(点,线,矩形,圆,多边形)。
(这里需要掌握三个知识点,一是上一篇中的创建实体、二是鼠标事件、三是回调函数)
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

一、鼠标事件

既然是鼠标绘制,自然离不开鼠标事件,我们需要先简单了解一下cesium的鼠标事件。

1. ScreenSpaceEventHandler:

这是Cesium中用于处理鼠标和触摸事件的主要类。需要创建一个此类的实例来开始事件监听。

let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(event => {}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

上述代码示例为Cesium的canvas创建了一个新的事件处理器。

2. 常用的鼠标事件类型 (ScreenSpaceEventType):

LEFT_CLICK: 左键点击
RIGHT_CLICK: 右键点击
LEFT_DOUBLE_CLICK: 左键双击
RIGHT_DOUBLE_CLICK: 右键双击
MIDDLE_CLICK: 中键点击
MOUSE_MOVE: 鼠标移动
WHEEL: 鼠标滚轮滚动

3. 注册事件监听:

使用 setInputAction 方法可以为特定的事件类型设置回调函数。
在回调函数中的 event 对象,包含与事件相关的数据。例如,对于鼠标点击事件,可以访问 event.position 来获取鼠标点击的屏幕坐标。

handler.setInputAction(function(event) {
    console.log('鼠标左键点击位置::', event.position);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

4. 关闭或销毁事件监听:

handler.destroy();    //永久性销毁事件处理器,之后它不能再被使用。
handler.removeInputAction(eventType);  //仅移除特定事件类型的监听(如:handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);)

二、回调函数(CallbackProperty )

我们通过鼠标事件来获取位置信息,再通过回调函数进行属性值修改。

回调函数说明

Cesium.CallbackProperty 是 Cesium.js 库中的一个特性,允许用户为属性提供一个回调函数,该函数描述了属性值如何随时间变化。这在需要动态或根据特定逻辑更改属性值的情况下特别有用,例如为实体的位置、颜色或其他属性设置动画效果。其实我们这里画线,画圆、画多边形等都是先创建不同的实体,然后根据鼠标事件获取位置坐标,动态改变其属性值,从而显示鼠标绘制的效果。

以下是 Cesium.CallbackProperty 的主要特点:

1.动态属性:

与其他静态属性不同,使用 CallbackProperty 创建的属性是动态的,它可以随时间或其它条件变化。

2.回调函数:

当需要获取属性值时,会调用提供的回调函数。这意味着每次 Cesium 请求属性值时,它都会执行这个函数。因此,你可以基于各种条件(例如当前时间)来计算和返回不同的值。

3.构造函数参数:

callback:一个回调函数,当需要属性值时会被调用。这个函数通常接收两个参数:time 和 result。time 是一个 JulianDate 对象,表示当前时间;而 result 是一个可选的参数,用于存储结果,以避免不必要的对象创建。
isConstant:一个布尔值,表示该属性是否是常数。即使属性是由回调函数定义的,也有可能总是返回相同的值。在这种情况下,可以将 isConstant 设置为 true。

举例说明:

请见“五、鼠标绘制圆”中绘制圆的代码说明。

三、鼠标绘制点

cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(1)主要操作及思路:

允许用户点击地球的某个位置,然后在那个位置上添加一个红色的点,用户鼠标右击,结束绘制,并返回点位置。

(2)代码:

主方法:
/**
 * 绘制点
 */
DrawPoints() {
  return new Promise((resolve, reject) => {
      let viewer = this.viewer;
      let drawnPoints = [];

      // 创建一个事件处理器
      let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

      // 注册鼠标左键点击事件,用于绘制点
      handler.setInputAction(event => {
          // 获取鼠标点击的笛卡尔坐标(鼠标点击位置->笛卡尔坐标)
          var cartesian = this.getCatesian3FromPX(event.position);
          // 确保坐标有效
          if (cartesian) {
              // 添加点实体
              viewer.entities.add({
                  position: cartesian,
                  point: {
                      color: Cesium.Color.RED,
                      pixelSize: 10
                  }
              });

              // 获取地理坐标(经纬度)
              let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
              let longitude = Cesium.Math.toDegrees(cartographic.longitude);
              let latitude = Cesium.Math.toDegrees(cartographic.latitude);
              let height=Cesium.Math.toDegrees(cartographic.height);
              // 将绘制的点添加到数组中
              drawnPoints.push({ lng: longitude, lat: latitude,height:height });
          }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 注册鼠标右键点击事件,用于结束绘制
      handler.setInputAction(() => {
          // 销毁事件处理器
          handler.destroy();

          // 返回所有绘制的点
          resolve(drawnPoints);
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  });
},
调用进行位置拾取和坐标转换的方法(此处三个方法来自测量插件):
 /**
   * 拾取位置点
   * @param {Object} px 屏幕坐标
   * @return {Object} Cartesian3 三维坐标
   */
  getCatesian3FromPX: function(px) {
    if (this.viewer && px) {
      var picks = this.viewer.scene.drillPick(px);
      var cartesian = null;
      var isOn3dtiles = false,
        isOnTerrain = false;
      // drillPick
      for (let i in picks) {
        let pick = picks[i];

        if (
          (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||
          (pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||
          (pick && pick.primitive instanceof Cesium.Model)
        ) {
          //模型上拾取
          isOn3dtiles = true;
        }
        // 3dtilset
        if (isOn3dtiles) {
          this.viewer.scene.pick(px); // pick
          cartesian = this.viewer.scene.pickPosition(px);
          if (cartesian) {
            let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            if (cartographic.height < 0) cartographic.height = 0;
            let lon = Cesium.Math.toDegrees(cartographic.longitude),
              lat = Cesium.Math.toDegrees(cartographic.latitude),
              height = cartographic.height;
            cartesian = this.transformWGS84ToCartesian({
              lng: lon,
              lat: lat,
              alt: height
            });
          }
        }
      }
      // 地形
      let boolTerrain =
        this.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;
      // Terrain
      if (!isOn3dtiles && !boolTerrain) {
        var ray = this.viewer.scene.camera.getPickRay(px);
        if (!ray) return null;
        cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
        isOnTerrain = true;
      }
      // 地球
      if (!isOn3dtiles && !isOnTerrain && boolTerrain) {
        cartesian = this.viewer.scene.camera.pickEllipsoid(
          px,
          this.viewer.scene.globe.ellipsoid
        );
      }
      if (cartesian) {
        let position = this.transformCartesianToWGS84(cartesian);
        if (position.alt < 0) {
          cartesian = this.transformWGS84ToCartesian(position, 0.1);
        }
        return cartesian;
      }
      return false;
    }
  },
  /***
   * 坐标转换 84转笛卡尔
   * @param {Object} {lng,lat,alt} 地理坐标
   * @return {Object} Cartesian3 三维位置坐标
   */
  transformWGS84ToCartesian: function(position, alt) {
    if (this.viewer) {
      return position
        ? Cesium.Cartesian3.fromDegrees(
            position.lng || position.lon,
            position.lat,
            (position.alt = alt || position.alt),
            Cesium.Ellipsoid.WGS84
          )
        : Cesium.Cartesian3.ZERO;
    }
  },
  /***
   * 坐标转换 笛卡尔转84
   * @param {Object} Cartesian3 三维位置坐标
   * @return {Object} {lng,lat,alt} 地理坐标
   */
  transformCartesianToWGS84: function(cartesian) {
    if (this.viewer && cartesian) {
      var ellipsoid = Cesium.Ellipsoid.WGS84;
      var cartographic = ellipsoid.cartesianToCartographic(cartesian);
      return {
        lng: Cesium.Math.toDegrees(cartographic.longitude),
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        alt: cartographic.height
      };
    }
  },
getCatesian3FromPX方法说明:

该方法根据给定的屏幕坐标px,计算出对应的三维世界坐标。该三维世界坐标可以代表一个具体的点在地图上的位置。
使用drillPick方法来获取屏幕坐标点上所有的对象。如果该点上有一个或多个对象,方法会尝试从3D模型上拾取坐标。
如果拾取不在3D模型上,并且地形存在,则从地形上拾取坐标。
如果既不在3D模型上也不在地形上,则从地球椭球体上拾取坐标。
最后返回这个点的三维世界坐标,或者在无法确定时返回false。

transformWGS84ToCartesian方法说明:

该方法根据给定的地理坐标(WGS84格式)计算出相应的三维世界坐标(笛卡尔坐标)。
使用Cesium的Cartesian3.fromDegrees方法从给定的经纬度和高度计算出三维坐标。

transformCartesianToWGS84方法说明:

该方法根据给定的三维世界坐标(笛卡尔坐标)计算出相应的地理坐标(WGS84格式)。
使用Cesium的Ellipsoid.WGS84和cartesianToCartographic方法将三维世界坐标转换为地理坐标。

四、鼠标绘制线

cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(1)主要操作及思路:

使用左键点击事件来添加点,创建一个折线实体来表示用户点击确定的所有点之间的线段。同时每当用户移动鼠标时,显示从最后一个点击位置到当前鼠标位置的一个动态线段。

(2)代码:

/**
 * 绘制折线
 */
DrawPolyline() {
  return new Promise((resolve, reject) => {
      let viewer = this.viewer;
      let polylinePoints = [];

      // 临时折线实体
      let polylineEntity = viewer.entities.add({
          Id:"drawingPolyline",
          name:"画线",
          polyline: {
              //使用CallbackProperty允许我们在用户点击时动态更新线段的位置
              positions: new Cesium.CallbackProperty(() => {
                  return polylinePoints;
              }, false),
              width: 2,
              material: Cesium.Color.RED
          }
      });

      // 临时动态线实体
      let dynamicLineEntity = viewer.entities.add({
          polyline: {
              positions: new Cesium.CallbackProperty(() => {
                  if (lastPoint && currentMousePoint) {
                      return [lastPoint, currentMousePoint];
                  } else {
                      return [];
                  }
              }, false),
              width: 2,
              material: Cesium.Color.RED.withAlpha(0.5) // 使用半透明红色,与主线区分
          }
      });

      let lastPoint = null;
      let currentMousePoint = null;

      // 创建事件处理器
      let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

      // 注册鼠标左键点击事件,用于添加点和显示点
      handler.setInputAction(event => {
          let cartesian = this.getCatesian3FromPX(event.position);
          if (cartesian) {
              polylinePoints.push(cartesian);
              lastPoint = cartesian;

              viewer.entities.add({
                  position: cartesian,
                  point: {
                      color: Cesium.Color.BLUE,
                      pixelSize: 10
                  }
              });
          }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 鼠标移动事件,更新当前鼠标位置并重绘临时线
      handler.setInputAction(event => {
          currentMousePoint = this.getCatesian3FromPX(event.endPosition);
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // 注册鼠标左键双击点击事件,用于结束绘制
      handler.setInputAction(() => {
          handler.destroy();
          viewer.entities.remove(dynamicLineEntity); // 移除临时线

          resolve(polylinePoints);
      }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  });
},

五、鼠标绘制圆

cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(1)主要操作及思路:

用户首先通过单击选择圆的中心,然后通过移动鼠标选择半径。当用户双击时,绘制将完成。

(2)代码:

/**
 * 绘制圆形
 */
DrawCircle() {
  return new Promise((resolve, reject) => {
      let viewer = this.viewer;
      let centerPoint = null;
      let centerPointEntity = null;  // 用于存储中点实体的引用
      let radius = 10;
      viewer.scene.globe.depthTestAgainstTerrain = false;
      let drawingCircle = viewer.entities.add({
          id: "drawingCircle",
          name: "画圆",
          ellipse: {
              semiMinorAxis: new Cesium.CallbackProperty(() => {
                  return radius;
              }, false),
              semiMajorAxis: new Cesium.CallbackProperty(() => {
                  return radius;
              }, false),
              material: Cesium.Color.BLUE.withAlpha(0.2),
              outline: true,
              outlineColor: Cesium.Color.RED,
              outlineWidth:2,
              fill: true,  //为true时只显示轮廓线
          }
      });

      let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

      handler.setInputAction(event => {
          var cartesian = this.getCatesian3FromPX(event.position);
          if (cartesian && centerPoint === null) {
              centerPoint = cartesian;
              drawingCircle.position = centerPoint;

              // 添加中点实体并保存其引用
              centerPointEntity = viewer.entities.add({
                  position: cartesian,
                  point: {
                      color: Cesium.Color.RED,
                      pixelSize: 10
                  }
              });
          }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      handler.setInputAction(event => {
          if (centerPoint) {
              let cartesian = this.getCatesian3FromPX(event.endPosition);
              if (cartesian) {
                  let distance = Cesium.Cartesian3.distance(centerPoint, cartesian);
                  radius = distance;
              }
          }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      handler.setInputAction(() => {
          if (centerPoint !== null && radius > 0) {
              handler.destroy(); // 关闭鼠标事件监听,结束绘制

              let circleCenter = Cesium.Cartographic.fromCartesian(centerPoint);
              let lng = Cesium.Math.toDegrees(circleCenter.longitude);
              let lat = Cesium.Math.toDegrees(circleCenter.latitude);

              resolve({
                  center: { lng: lng, lat: lat },
                  radius: radius
              });
          }
      }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  });
},

代码说明:

我们可以看到鼠标绘制圆是如何实现的呢?首先,创建一个圆实体,即 let drawingCircle = viewer.entities.add({......}),其中在

         ellipse: {
              semiMinorAxis: new Cesium.CallbackProperty(() => {
                  return radius;
              }, false),
              semiMajorAxis: new Cesium.CallbackProperty(() => {
                  return radius;
              }, false),
              ...

这里使用了回调函数CallbackProperty,将semiMinorAxissemiMajorAxis绑定上了radius,也就是说圆的半径将根据radius值的变化而变化。看到这里相信你已经明白了,后面我们要做的就是根据鼠标移动来改变radius的值,从而改变圆的大小。即鼠标移动监听里的 radius = distance;

六、鼠标绘制矩形

cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(1)主要操作及思路:

首次单击选择左上角,移动鼠标调整矩形的大小,然后双击来结束绘制并保存矩形的点。通过捕获用户在地图上的鼠标操作来确定矩形的两个对角点,然后使用这两个点来定义矩形。

(2)代码:

/**
   * 绘制矩形
   */ 
  DrawRectangle() {
    var allPoints = [];
    // 设置返回值
    return new Promise((resolve, reject) => {
        let viewer = this.viewer;
        let topLeftPoint = null;
        let bottomRightPoint = null;

        let drawingRectangle = viewer.entities.add({
            id: "drawingRectangle",
            name: "画矩形",
            rectangle: {
                coordinates: new Cesium.CallbackProperty(() => {
                    if (topLeftPoint === null || bottomRightPoint === null) {
                        return;
                    }
                    let west = topLeftPoint.longitude;
                    let north = topLeftPoint.latitude;
                    let east = bottomRightPoint.longitude;
                    let south = bottomRightPoint.latitude;
                    return new Cesium.Rectangle(west, south, east, north);
                }, false),
                material: Cesium.Color.BLUE.withAlpha(0.2),
                closeTop: true,
                closeBottom: false
            }
        });

        let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

        handler.setInputAction(event => {
            var cartesian = this.getCatesian3FromPX(event.position);
            if (cartesian) {
                if (topLeftPoint === null) {
                    topLeftPoint = Cesium.Cartographic.fromCartesian(cartesian);
                }

                viewer.entities.add({
                    position: cartesian,
                    point: {
                        color: Cesium.Color.RED,
                        pixelSize: 10
                    }
                });
            }
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

        handler.setInputAction(event => {
            if (topLeftPoint) {
                bottomRightPoint = Cesium.Cartographic.fromCartesian(this.getCatesian3FromPX(event.endPosition));
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        handler.setInputAction(() => {
            if (topLeftPoint !== null && bottomRightPoint !== null) {
                handler.destroy(); // 关闭鼠标事件监听,结束绘制

                let west = Cesium.Math.toDegrees(topLeftPoint.longitude);
                let north = Cesium.Math.toDegrees(topLeftPoint.latitude);
                let east = Cesium.Math.toDegrees(bottomRightPoint.longitude);
                let south = Cesium.Math.toDegrees(bottomRightPoint.latitude);

                allPoints.push({ lng: west, lat: north });
                allPoints.push({ lng: east, lat: north });
                allPoints.push({ lng: east, lat: south });
                allPoints.push({ lng: west, lat: south });
                allPoints.push(allPoints[0]); // 闭合
                resolve(allPoints);
            }
        }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
    });
},

七、鼠标绘制多边形

贴地:
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis
不贴地:
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(1)主要操作及思路:

点击地图以定义多边形的顶点,可以随着鼠标移动看到多边形的形状实时更新,通过双击结束多边形绘制,并返回所有的顶点。

(2)代码:

主方法:
 /**
   * 绘制多边形
   * @param {Object}  option
   * @param {Boolean} option.ground 是否贴地
   */ 
   DrawPolygon(option) {
    var allPoints=[]
    // 设置返回值
    return new Promise((resolve, reject) => {
    // 1. 获取Cesium Viewer
    let viewer = this.viewer;
    // 2. 创建一个用于存储多边形顶点的数组
    let polygonPoints = [];
    // 3. 创建一个用于显示当前绘制中的多边形的实体
    let drawingPolygon = viewer.entities.add({
      id: "drawingPolygon",
      name: "画多边形",
      polygon: {
        hierarchy: new Cesium.CallbackProperty(() => {
          return new Cesium.PolygonHierarchy(polygonPoints);
        }, false),
        material: Cesium.Color.BLUE.withAlpha(0.2),
        perPositionHeight: (option&&option.ground)||false // true:不贴地/false:贴地
      },
    });

    // 4. 创建一个用于显示当前绘制中的线的实体
    let drawingLine = viewer.entities.add({
      id: "drawingLine",
      name: "画线",
      polyline: {
        positions: new Cesium.CallbackProperty(() => {
          return polygonPoints;
        }, false),
        width: 3,
        material: Cesium.Color.GREEN
      }
    });

    // 5. 监听鼠标点击事件,将点击的点添加到顶点数组中,并添加点实体
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction(event => {
      var cartesian = this.getCatesian3FromPX(event.position);
      if (cartesian) {
         // 将点坐标添加到数组中
        polygonPoints.push(cartesian.clone());
        // 在第一次点击时,添加一个克隆的点到数组中,用于动态更新
        if (polygonPoints.length === 1) {
          polygonPoints.push(cartesian.clone());
        }
        // 添加点实体
        viewer.entities.add({
          position: cartesian,
          point: {
            color: Cesium.Color.RED,
            pixelSize: 10
          }
        });

         //将三维笛卡尔坐标系点转为经纬度坐标点,并保存到点数组中
         let cartesian3 = cartesian.clone()
         // 使用Cesium.Cartographic.fromCartesian将Cartesian3对象转换为Cartographic对象
         let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
         allPoints.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height]);
        
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

    // 6. 监听鼠标移动事件,动态更新多边形和线的形状
    handler.setInputAction(event => {
      var cartesian = this.getCatesian3FromPX(event.endPosition);
      if (polygonPoints.length >= 2) {
        if (cartesian && cartesian.x) {
          polygonPoints.pop();
          polygonPoints.push(cartesian);
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

    // 7. 监听鼠标右键点击事件,结束绘制
    handler.setInputAction(() => {
      var cartesian=polygonPoints[polygonPoints.length-1]
        // 添加点实体
        viewer.entities.add({
          position: cartesian,
          point: {
            color: Cesium.Color.RED,
            pixelSize: 10
          }
        });
      polygonPoints.push(polygonPoints[0]);
      handler.destroy(); // 关闭鼠标事件监听,结束绘制
      resolve(allPoints);
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  })
  },
调用方法:
let option = {
        ground: true     //true:不贴地/false:贴地           
      };
DrawPolygon(option).then(allPoints => {
          // 在这里,allPoints是结束绘制后的点坐标数组
          var resultPoints=allPoints
        })

(3)DrawPolygon方法说明:

1,定义返回结果的方式:
var allPoints=[]
return new Promise((resolve, reject) => {
......
}

在这个方法开始时,定义了一个allPoints数组,用于存储绘制的多边形的所有顶点,并且返回一个Promise,允许在绘制结束后将这些点的坐标返回。

2,获取Cesium Viewer:
let viewer = this.viewer;

获取Cesium的Viewer实例

3,创建一个实体以显示绘制中的多边形:
let drawingPolygon = viewer.entities.add({ ... });

这段代码通过Cesium的entities.add方法创建一个新的实体,并将它添加到地图上。这个实体用于实时显示用户绘制的多边形。

4,创建一个实体以显示绘制中的线:
let drawingLine = viewer.entities.add({ ... });

创建一个实体来实时显示用户绘制的线。

5,设置鼠标点击事件的监听:
let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(event => { ... }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

这段代码创建一个新的ScreenSpaceEventHandler实例来监听鼠标和触摸事件。然后设置一个函数来监听左键点击事件。每当用户点击鼠标左键时,这个函数就会被调用,并将点击的位置添加到polygonPoints数组(即多边形的顶点)和allPoints数组。
需要说明的是这一段代码:

//将三维笛卡尔坐标系点转为经纬度坐标点,并保存到点数组中
         let cartesian3 = cartesian.clone()
         // 使用Cesium.Cartographic.fromCartesian将Cartesian3对象转换为Cartographic对象
         let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
         allPoints.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height]);

加上这一段只是因为,如果要对获取的点数组进行进一步使用,我更习惯使用经纬度坐标

6,设置鼠标移动事件的监听:
handler.setInputAction(event => { ... }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

当用户移动鼠标时,这个函数会被调用。它用于实时更新正在绘制的多边形和线的形状。

7,设置鼠标双击事件的监听:
handler.setInputAction(() => { ... }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

这个函数监听鼠标左键双击事件。当用户双击鼠标左键时,这个函数会被调用,表示用户完成了多边形的绘制。此时,它会添加最后一个点实体,关闭鼠标事件监听,结束绘制,并通过resolve(allPoints)将绘制的点坐标返回。

8,总说明:

这个方法允许用户通过点击和移动鼠标在Cesium地图上绘制一个多边形。在用户完成绘制(通过双击鼠标左键)后,这个方法通过Promise的resolve函数将绘制的点坐标数组allPoints返回,供其他部分的代码使用。
(比如进行填挖方的计算,将上面的点数组传到地形填挖方计算的方法,用来生成三角网)
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis

(4)拖拽点进行形状修改

绘制完成:
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis
拖拽点:
cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形),cesium学习,学习,cesium,gis
思路:
在完成绘制后(即在双击事件结束后),初始化一个新的鼠标事件处理器专门用于拖拽操作。在新的事件处理器中,设置监听左键按下、左键抬起和鼠标移动的事件,用于实现拖拽交互。为了在拖动点时停止地图的默认移动事件,需要在开始拖动事件时暂时禁用默认的摄像机控制,并在拖动结束后再次启用它。(保证点数组长度不变,修改拖拽点的位置)
代码:文章来源地址https://www.toymoban.com/news/detail-662757.html

let handler = this.globalHandler;
      handler.setInputAction(event => {
        var cartesian = this.getCatesian3FromPX(event.position);
        if (cartesian) {
          // 将点坐标添加到数组中
          polygonPoints.push(cartesian.clone());
          // 在第一次点击时,添加一个克隆的点到数组中,用于动态更新
          if (polygonPoints.length === 1) {
            polygonPoints.push(cartesian.clone());
          }
          // 添加点实体
          var pointEntity = viewer.entities.add({
            id: "point" + polygonPoints.length,
            position: cartesian,
            point: {
              color: Cesium.Color.RED,
              pixelSize: 10
            }
          });
          pointEntities.push(pointEntity);
          //添加到多边形数组中
          let cartesian3 = cartesian.clone();
          // 使用Cesium.Cartographic.fromCartesian将Cartesian3对象转换为Cartographic对象
          let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
          allPoints.push([
            Cesium.Math.toDegrees(cartographic.longitude),
            Cesium.Math.toDegrees(cartographic.latitude),
            cartographic.height
          ]);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      // 6. 监听鼠标移动事件,动态更新多边形和线的形状
      handler.setInputAction(event => {
        var cartesian = this.getCatesian3FromPX(event.endPosition);
        if (polygonPoints.length >= 2) {
          if (cartesian && cartesian.x) {
            polygonPoints.pop();
            polygonPoints.push(cartesian);
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // 7. 监听鼠标双击事件,结束绘制
      handler.setInputAction(() => {
        var cartesian = polygonPoints[polygonPoints.length - 1];
        handler.destroy(); // 关闭鼠标事件监听,结束绘制
        // 移除因单击事件产生的最后一个点
        if (polygonPoints.length > 1) {
          // 去除数组中最后一个点
          polygonPoints.pop();
          // 返回值
          allPoints.pop();
          allPoints.push(allPoints[0]); // 闭合
          var endPoint = viewer.entities.getById(
            "point" + (polygonPoints.length + 1)
          );
          if (endPoint) {
            viewer.entities.remove(endPoint);
          }
          var startPoint = viewer.entities.getById("point1");
          if (startPoint) {
            viewer.entities.remove(startPoint);
          }
        }
        resolve(allPoints);

        // 移除用于绘制的动态线实体
        viewer.entities.remove(drawingLine);

        // 以下为拖拽点改变多边形形状代码
        let selectedPointEntity = null;
        let selectedIndex = -1;
        var dragHandler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
        //鼠标按下
        dragHandler.setInputAction(event => {
          const pickedObject = viewer.scene.pick(event.position);
          if (
            Cesium.defined(pickedObject) &&
            pointEntities.includes(pickedObject.id)
          ) {
            selectedPointEntity = pickedObject.id;
            selectedIndex = pointEntities.indexOf(selectedPointEntity);

            // 禁用摄像机控制
            viewer.scene.screenSpaceCameraController.enableRotate = false;
            viewer.scene.screenSpaceCameraController.enableTranslate = false;
            viewer.scene.screenSpaceCameraController.enableZoom = false;
            viewer.scene.screenSpaceCameraController.enableTilt = false;
            viewer.scene.screenSpaceCameraController.enableLook = false;
          }
        }, Cesium.ScreenSpaceEventType.LEFT_DOWN);
        // 当鼠标移动时
        dragHandler.setInputAction(event => {
          if (selectedPointEntity) {
            const cartesian = this.getCatesian3FromPX(event.endPosition);
            if (cartesian && selectedIndex !== -1) {
              selectedPointEntity.position = cartesian;
              polygonPoints[selectedIndex] = cartesian;
              // 如果当前拖动的是第一个点或是最后一个点
              if (selectedIndex === 0||selectedIndex===polygonPoints.length - 2) {
                polygonPoints[polygonPoints.length - 1] = cartesian;
                pointEntities[polygonPoints.length - 1].position.setValue(
                  cartesian
                );
              }
            }
          }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        // 当鼠标左键抬起时
        dragHandler.setInputAction(() => {
          selectedPointEntity = null;
          selectedIndex = -1;

          // 启用摄像机控制
          viewer.scene.screenSpaceCameraController.enableRotate = true;
          viewer.scene.screenSpaceCameraController.enableTranslate = true;
          viewer.scene.screenSpaceCameraController.enableZoom = true;
          viewer.scene.screenSpaceCameraController.enableTilt = true;
          viewer.scene.screenSpaceCameraController.enableLook = true;
        }, Cesium.ScreenSpaceEventType.LEFT_UP);
      }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

到了这里,关于cesium学习记录08-鼠标绘制实体(点,线,矩形,圆,多边形)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Opencv(C++)笔记--绘制直线、矩形、椭圆、圆、填充多边形、绘制字体和随机产生坐标点

    目录 1--cv::line()绘制直线 2--cv::Rect()绘制矩形 3--cv::ellipse()绘制椭圆 4--cv::circle()绘制圆 5--cv::fillPoly()填充多边形 6--cv::putText()绘制字体 6--cv::RNG随机产生坐标点 使用 cv::Point p1 定义坐标点; 使用 cv::line() 绘制直线,传入的参数依次为:背景图、两个点的坐标、直线的颜色、直线

    2024年02月14日
    浏览(60)
  • OpenCV(十三):图像中绘制直线、圆形、椭圆形、矩形、多边形和文字

    目录 1.绘制直线line() 2.绘制圆形circle() 3.绘制椭圆形ellipse()  4.绘制矩形rectangle() 5.绘制多边形 fillPoly()  6.绘制文字putText() 7.例子 1.绘制直线line() img:绘制圆形的图像 ptl:直线起始点在图像中的坐标 pt2: 直线终点在图像中的坐标 color:圆形的颜色,用三通道表示 thickness:轮廓的宽

    2024年02月09日
    浏览(65)
  • 使用c#实现一个简单绘图软件(绘制矩形、多边形,画笔、橡皮擦功能)的完整教程

    c#是微软提供的用于开发windows软件的开发语言,可以使用其快速的实现windows桌面软件的开发。这里基于C#开发了一款简单的绘图软件,可以用于绘制矩形、多边形的绘制(基于这些可以实现自己的数据标注软件),还实现了画笔、橡皮擦功能。开发C#软件通常使用Visual Studio软

    2024年02月03日
    浏览(65)
  • cesium 绘制工具 鼠标提示tips工具组件

    本专题主要是针对学习cesium小伙伴,在项目中实践总结的一些工具,以及会详细介绍,知识和封装的原理,废话不多说,此文介绍的是,鼠标提示tips工具组件,在项目中使用会优化交互效果,对客户友好,例如标绘工具,地图操作。 之前在网上看到的都是,通过动态创建,

    2024年03月21日
    浏览(50)
  • 《QT从基础到进阶·十五》用鼠标绘制矩形(QGraphicsView、QPainter、QGraphicsRectItem)

    以下是鼠标绘制矩形最全的一种用法,完整源码将会放在最后面。 QT版本:5.15.2 VS版本:2019 1、在界面加载一张图片 界面的搭建选用QGraphicsView,自定义类GraphicsView继承QGraphicsView,在主程序中点击按钮打开 图片,相关代码如下: 2、创建矩形绘制对象,并绘制、移动矩形 在

    2024年02月04日
    浏览(51)
  • OpenCV-Python学习(13)—— OpenCV 多边形填充与绘制(cv.fillPoly、cv.polylines)

    1. 知识点 学习 cv.polylines 函数的使用; 学习 cv.fillPoly 函数的使用。 2. 绘制折线或多边形 cv.polylines 函数说明 2.1 函数使用 2.2 参数说明 参数 说明 img 表示要在其上绘制矩形的图像的img对象。 pts 表示一个或多个点集。 isClosed 表示标志,决定所绘制的多边形是否闭合。若为 T

    2024年02月16日
    浏览(58)
  • 利用fabric绘画矩形和多边形

    需求在一张图片上标注矩形和多边形,支持回显; fabric版本:4.6.0; Fabric.js 是一个功能强大且操作简单的 Javascript HTML5 canvas 工具库。 官方文档 参考链接 组件代码drawer.vue createUuid 是为了让每一个图形有自己的id;方便用于获取用户点击的那个图形等操作; defaultRectStyle、d

    2024年02月08日
    浏览(72)
  • 学习Canvas基础-绘制矩形

    学习Canvas基础-绘制矩形 canvas提供了三个API,分别是: 1.绘制矩形 rect(起点X, 起点Y, 绘制的矩形width, 绘制的矩形height) 但该方法不会出实际效果,需要配合 fill()和stroke()方法让其显现。 2.绘制一个填充的矩形 fillRect(起点X, 起点Y, 绘制的矩形width, 绘制的矩形height) 3.绘制一

    2023年04月09日
    浏览(59)
  • Python:opencv画点、圆、线、多边形、矩形

    简介 :机器学习视觉方向一般都需要在图像中添加标注框,标注框有着很大的用处,特别是对图像中某些需要关注的特征起到圈定的效果,方便对特征选择进行处理。 相关攻略: 机器学习:基本流程 Python:调用摄像头使用cv2库录制视频 Python:视频拆分成一帧一帧的图片

    2024年02月04日
    浏览(92)
  • 【opencv学习】鼠标回调函数、鼠标控制画矩形

    1.回调函数可以简单理解为一边做一件事的同时做另一件事,优化之前的实现完一个函数后才实现另一个的问题。 鼠标回调函数就是一边鼠标操作画图,一边显示画出的图像。 2.实现一个矩形rec只需要知道一个左上角的坐标和宽高即可实例化对象。

    2024年02月14日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包