Bootstrap

Cesium学习笔记2

函数功能概述:点击cesium中的地球表面,返回该点坐标值

 viewer.screenSpaceEventHandler.setInputAction(function (click) {
        const pickedObject = viewer.scene.pick(click.position);
        if (Cesium.defined(pickedObject) && pickedObject.primitive instanceof Cesium.PolygonGraphics) {
          // 如果点击到的是多边形等,这里可能需要更复杂的处理  
          // 这里只处理点击到地球表面的情况  
          return;
        }
        // 获取点击位置的笛卡尔坐标  
        const ray = viewer.camera.getPickRay(click.position);
        const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (cartesian) {
          // 将笛卡尔坐标转换为经纬度  
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
          const longitude = Cesium.Math.toDegrees(cartographic.longitude);
          const latitude = Cesium.Math.toDegrees(cartographic.latitude);

          // 显示经纬度,这里可以根据你的项目具体实现  
          console.log(`Longitude: ${longitude.toFixed(2)}, Latitude: ${latitude.toFixed(2)}`);

          // 例如,你可以通过Vue的data属性或methods来更新页面上的元素显示经纬度  
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

第一行:

viewer.screenSpaceEventHandler.setInputAction(function (click) {
  // 处理点击事件的代码
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

         其中function(click)是一个回调函数,接收一个“click”参数,并且因为是回调函数,会作为一个参数传递给setInputAction函数。

        首先,screenSpaceEventHandler是Cesium特有的一个组件,用于专门处理屏幕空间内的事件。主要特点是可以监听多种事件,具备回调机制,灵活性高,性能较好。

        其次,setInputAction是screenSpaceEventHandler类中的一个方法,主要用于为屏幕内的事件注册一个相关的处理函数。通常为setInputAction(action, type, [options])样式,其中action为指定类型事件发生时要调用的函数,这个函数会接收一个事件对象作为参数,且该对象包含了事件的相关信息,如事件发生的屏幕位置这种数据。Cesium.ScreenSpaceEventType.LEFT_CLICK)则是用来确定要处理的,或者说要监听的事件的类型,比如这里就是LEFT_CLICK类型,即鼠标左键点击。

        当鼠标在屏幕空间内点击时,首先被识别到是left_click事件,随后监听这类事件的监听器开始运行,当监听到这个事件时,screenSpaceEventHandler开始运行,自动收集与该事件的相关的信息,并且进行封装与传递,这里传递给“click”,随后“click”传递给function,再由回调函数function一起传递给setInputAction,等待调用。

第二行:

  const pickedObject = viewer.scene.pick(click.position);

       这段代码的意义是从屏幕空间中点击的位置拾取对象,若点击的位置有对象,则直接拾取,并在后续代码进行处理,若没有,则返回undefined。

         click.position是一个Cesium.Cartesian2对象,表示的是屏幕上的点击位置,而这个位置通常情况下是由屏幕空间事件处理器也即screenSpaceEventHandler来进行提供,当用户在屏幕上点击时,该事件处理器提供这些信息,click.position中的x,y分别表示位置在屏幕上的水平和竖直坐标。

        而viewer.scene.pick则是Cesium提供的方法,用于从屏幕坐标位置拾取到场景中的对象。这个方法接收两个参数,屏幕位置坐标,以及场景中的对象。且最后的返回值是一个Cesium.PickResult对象,包含了关于拾取到的对象的信息,该对象包含多个属性:

primitive:拾取到的原始对象,比如Cesium.Entity或者Cesium.primitive。

id:拾取到的对象的标识符,例如Cesium.Entity的实例。

instance:拾取到的实例,例如Cesium.primitive的实例。

windowPosition:屏幕坐标位置。

position:场景中的世界坐标的位置。

distance:拾取点到摄像机的距离。

如果未拾取到对象,则返回undefined。

        pickedObject是一个变量,用来存储从viewer.scene.pick(click.position)获得的结果。如果拾取到了一个对象,则pickedObject将包含该对象的信息。例如 pickedObject.primitive 可能包含拾取到的原始对象,例如 Cesium.Entity 或 Cesium.Primitive。如果未拾取到对象,pickedObject则是undefined。

第三行:

if (Cesium.defined(pickedObject) && pickedObject.primitive instanceof Cesium.PolygonGraphics) {
          // 如果点击到的是多边形等,这里可能需要更复杂的处理  
          // 这里只处理点击到地球表面的情况  
          return;
        }

        这段代码的意义是检测点击到东西是否是屏幕空间里地球上的,如果是,就继续后面的代码,如果不是,则代码直接返回,不再运行了。

        Cesium.defined(pickedObject)用来判断是否在场景中拾取到了对象,如果拾取到了,存在两种情况,1:拾取到地球上位置。2:拾取到ui等按钮(即多边形)。在Cesium.defined(pickedObject)中,如果拾取到了对象,则返回true,若未拾取到,则返回false。

        pickedObject.primitive instanceof Cesium.PolygonGraphics用来判断拾取到的对象是否是多边形对象(即是否是ui)。若是,则返回true,若不是,则返回false。此处pickedObject.primitive是前文viewer.scene.pick的返回值的属性。

        此时,存在4种情况,实际上是三种,因为第三种第四种无意义

第一种:拾取到了,是多边形【返回true】

第二种:拾取到了,不是多边形,是地球上的点【返回false】

第三种:未拾取到,是多边形(无意义)【返回false】

第四种:未拾取到,不是多边形,是地球上的点(无意义)【返回false】

当返回true时,执行return,直接退出回调函数,当返回false时,继续执行代码,但是第三第四种情况无意义,仅执行第二种情况。

第四行:

  const ray = viewer.camera.getPickRay(click.position);

        这段代码的意义是从当前摄像机位置发出一条射线指向鼠标点击的位置。 

        viewer.camera.getPickRay是一个Cesium中特有的方法,用于从当前摄像机的位置发出一条射线,且这条射线的方向是从摄像机指向屏幕上的指定位置。而这个方法接收一个Cesium.Cartesian2对象作为参数,表示屏幕上的位置坐标。这里接受的参数是click.position,即本篇文章第二行中的click.position,这个对象的信息来自screenSpaceEventHandler,当鼠标在屏幕上点击时,sceenSpaceHandler开始执行,收集一系列数据传递给第一行中的click,随后调用click中的不同属性进行相关处理。这里使用的就是click中的position属性。

        在接收这个click.position对象并进行处理后,会返回Cesium.Ray对象,这个对象又会存储到ray变量里。而返回的Cesium.Ray对象又包含了以下属性:

orign:射线的起点,通常为摄像机位置。

driection:射线的方向向量。

第五行:

        const cartesian = viewer.scene.globe.pick(ray, viewer.scene);

        这段代码意义在于从射线与地球的交点处,获得一个笛卡尔坐标。方便后续代码中对笛卡尔坐标进行处理,转换为经纬度。

        viewer.scene.globe.pick是Cesium提供的一个方法,用于从给定的射线中拾取地球表面的点。这个方法接收两个参数,一个是射线,一个是场景。该方法返回值是一个Cesium.Cartesian3对象,表示射线与地球表面的交点的笛卡尔坐标。

        ray是指射线,是一个Cesium.ray对象,表示从摄像机指向屏幕点击位置的射线,该射线正是由第四行代码的运行产生的,第四行代码运行后返回一个Cesium.Ray对象。

        viewer.scene是Cesium提供的场景对象,包含了当前渲染的场景信息。

        cartesian是一个Cesium.Cartesian3对象,用于存储viewer.scene.globe.pick返回的结果,表示射线与地球的交点信息。该对象包含三个坐标值(x,y,z),代表地球表面的交点的位置。

第六行:

 if (cartesian) {
          // 将笛卡尔坐标转换为经纬度  
          const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
          const longitude = Cesium.Math.toDegrees(cartographic.longitude);
          const latitude = Cesium.Math.toDegrees(cartographic.latitude);

          // 显示经纬度,这里可以根据你的项目具体实现  
          console.log(`Longitude: ${longitude.toFixed(2)}, Latitude: ${latitude.toFixed(2)}`);

          // alert(11111111)
          confirm(`Longitude: ${longitude.toFixed(2)}, Latitude: ${latitude.toFixed(2)}`)

          // 例如,你可以通过Vue的data属性或methods来更新页面上的元素显示经纬度  
        }

const cartographic = Cesium.Cartographic.formCartesian(cartesian) ;

         在const cartographic = Cesium.Cartographic.formCartesian(cartesian) ;中Cesium.Cartographic.formCartesian是由Cesium提供的静态方法,用于将笛卡尔坐标转换为地理坐标。这个方法接收一个Cesium.Cartesian3参数表示笛卡尔坐标,并在运行完后返回一个Cesium.Graphic对象作为地理坐标。返回的Cesium.Graphic对象包含以下属性:

Longitude:表示地理坐标的经度,坐标是弧度。

Latiude:表示地理坐标的纬度,坐标是弧度。

height:表示地理坐标的高度,单位是米。

其中的cartesian是一个Cesium.Cartesian3对象,包含了(x,y,z)三个坐标,是笛卡尔坐标,由第五行代码“const cartesian = viewer.scene.globe.pick(ray, viewer.scene);”的运行产生这个对象。

其中的cartographic是一个Cesium.Graphic对象,用来存储 Cesium.Cartographic.formCartesian方法运行后返回的结果。

const longitude = Cesium.Math.toDegrees(cartographic.longitude);

const latitude = Cesium.Math.toDegrees(cartographic.latitude);

          在 const longitude = Cesium.Math.toDegrees(cartographic.longitude);中,Cesium.Math.toDegrees是Cesium提供的一个静态方法,用于将弧度单位的数据转换为角度单位的数据,也即将弧度单位的经纬度转为角度单位的经纬度。cartographic.longitude是在上一行代码执行后返回的cartographic-----一个Cesium.Graphic对象中的一个属性,即经度属性。并返回一个以角度为属性的longitude数值变量。

        在const latitude = Cesium.Math.toDegrees(cartographic.latitude);也同理。

console.log(`Longitude: ${longitude.toFixed(2)}, Latitude: ${latitude.toFixed(2)}`);

        将最终得到的数据,打印出来。 使用 toFixed(2) 可以确保输出的经度和纬度值始终保留两位小数,使输出更加整洁和一致