turf.js

221 阅读5分钟

turf.js:panzhiyue.github.io/turfjs-docs…

1. 网站

turf.js 计算 cesium.xin/ 中文网站

iconfont 阿里巴巴 图标库

2. 弧度值与角度值的图片:

image.png

image.png

3. Cesium.Cartographic.fromCartesian作用

` 方法在 CesiumJS 库中用于将笛卡尔坐标(Cartesian coordinates)转换为地理坐标(Cartographic coordinates)。CesiumJS 是一个用于创建3D地球和2D地图的开源JavaScript库,广泛用于地理信息系统(GIS)、地球物理学、遥感以及游戏开发等领域。

在 CesiumJS 中,笛卡尔坐标系统是基于地心地固(ECEF, Earth-Centered, Earth-Fixed)坐标系的,这种坐标系以地球的中心为原点,使用 X、Y、Z 轴来表示空间中的点。而地理坐标系统则使用经度(longitude)、纬度(latitude)和高度(height)来表示地球上的点,这些值分别表示了点的位置相对于地球赤道和本初子午线的角度,以及点相对于地球椭球体的表面的高度。

Cesium.Cartographic.fromCartesian 方法正是用于执行这种转换的。它接受一个 Cesium.Cartesian3 对象作为参数,这个对象包含了笛卡尔坐标系中的 X、Y、Z 值,然后返回一个 Cesium.Cartographic 对象,该对象包含了对应的经度、纬度和高度值。

// 假设我们有一个 Cesium.Cartesian3 对象,表示地球上的某个点
var cartesian = new Cesium.Cartesian3(1234567.0, 2345678.0, 3456789.0); 
// 使用 Cesium.Cartographic.fromCartesian 方法将其转换为地理坐标 
var cartographic = Cesium.Cartographic.fromCartesian(cartesian); 
// 现在 cartographic 对象包含了经度、纬度和高度 
console.log('Longitude:', Cesium.Math.toDegrees(cartographic.longitude)); console.log('Latitude:', Cesium.Math.toDegrees(cartographic.latitude));
console.log('Height:', cartographic.height); 
// 注意:CesiumJS 中的经度和纬度是以弧度为单位的,因此如果你需要度为单位,
// 需要使用 Cesium.Math.toDegrees 方法进行转换。

绘制线

    addLinkLodLayer(formData) {
      formData.forEach((ele) => {
        const from = JSON.parse(ele.form)
        from.forEach((item) => {
         
          let id = `netLine${item.startId}-${item.endId}`
          // item.id = id // 用作树的key,也方便后面通过树控制场景链路显隐。
          // item.label = item.netName// 用作树的label
          let findExist = netLineEntity.findIndex(el => el.id === id)
          if (findExist === -1) {
            console.log(' viewer.entities.----', viewer.entities)
            let findStart = viewer.entities.values.find(child => child.id === `point${item.startId}`)
            let findEnd = viewer.entities.values.find(child => child.id === `point${item.endId}`)
            if (findStart && findEnd) {
              let positions = [findStart.position._value.clone(), findEnd.position._value.clone()]
              let start = DT.Cesium.Cartographic.fromCartesian(positions[0])
              let end = DT.Cesium.Cartographic.fromCartesian(positions[1])
              let updatePositions = getArc([DT.Cesium.Math.toDegrees(start.longitude), DT.Cesium.Math.toDegrees(start.latitude)], [DT.Cesium.Math.toDegrees(end.longitude), DT.Cesium.Math.toDegrees(end.latitude)], 40, 100000)
              // console.log('位置', updatePositions);

              const line = new DT.PolylineEntity({
                id,
                positions: updatePositions.map(function (point) {
                  return DT.Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2]);
                }),
                width: 4, // material: DT.Cesium.Color.fromCssColorString('#2e7b69'),
                // material: new DT.FlowLineMaterial({
                //   colorMixMode: false,
                //   image: this.gradient(),
                //   repeat: 1,
                //   speed: -15
                // }),
                material: new DT.MultipleColorFlowMaterial({
                  image: process.env.BASE_URL + 'static/img/link.png',
                  // image: 'data/images/test3.png',
                  backgroundAlpha: 0.6,
                  color: ['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)', 'rgb(255,0,255)', 'rgb(255,255,0)', 'rgb(0,255,255)'],
                  // color: ['rgb(255,0,0)', 'rgb(0,255,0)'],
                  repeat: 4,
                  speed: 20
                }),
                arcType: DT.Cesium.ArcType.GEODESIC, asynchronous: false
              })
              netLineEntity.push(line)
              console.log(netLineEntity);
              lodLayer.add(line)
              line.show = false
              // line.show = this.netCurrentCheck.includes(item.id)
            }
          }
        })
      })
      // console.log(netLineEntity);

    },

这个转换在处理地球表面的位置时非常有用,尤其是在需要将地球表面的点映射到地图或进行地理空间分析时。

4. 绘制多变形hierarchy

<html lang="en"> <head> <meta charset="UTF-8"> 
<title>Cesium Polygon Demo</title> 
<!-- 引入CesiumJS的CSS --> 
<link href="https://cesium.com/downloads/cesiumjs/releases/latest/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> 
<!-- 引入CesiumJS的JS,注意这里使用的是最新版本,你也可以指定具体版本 -->
<script src="https://cesium.com/downloads/cesiumjs/releases/latest/Build/Cesium/Cesium.js"></script> 
<style> 
html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } 
</style> 
</head>
<body> 
<div id="cesiumContainer"></div> 
<script src="app.js">
</script> 
</body> 
</html>

JavaScript部分 (app.js)

然后,在JavaScript文件中,你需要创建一个Cesium Viewer,并添加一个带有hierarchy属性的多边形实体(Entity)。

// 替换为你的Cesium Ion访问令牌,如果你不使用Cesium Ion服务,则可以省略此行 
// Cesium.Ion.defaultAccessToken = '你的Cesium Ion访问令牌'; 
// 初始化Cesium Viewer var viewer = new Cesium.Viewer('cesiumContainer', { terrainProvider: Cesium.createWorldTerrain()
// 可选,加载地形数据 });
// 定义一个多边形的顶点坐标(经纬度),注意这里的坐标需要是闭合的,即首尾坐标相同 
var polygonHierarchy = Cesium.PolygonHierarchy.fromCartesianArray([ Cesium.Cartesian3.fromDegrees(-115.0, 37.0), Cesium.Cartesian3.fromDegrees(-107.0, 37.0), Cesium.Cartesian3.fromDegrees(-107.0, 33.0), Cesium.Cartesian3.fromDegrees(-115.0, 33.0), 
// 注意:这里为了闭合多边形,我们再次添加了第一个点 Cesium.Cartesian3.fromDegrees(-115.0, 37.0) ]); // 创建一个多边形实体并添加到viewer中 viewer.entities.add({ polygon: { hierarchy: polygonHierarchy,
// 配置多边形的填充色和边框 material: Cesium.Color.fromCssColorString('#4CAF50'), // 填充色,这里使用CSS颜色字符串 
outline: true, // 显示边框 outlineColor: Cesium.Color.WHITE, // 边框颜色 
outlineWidth: 2 // 边框宽度 } }); // (可选)将视角飞到多边形所在位置
// viewer.zoomTo(viewer.entities); // 注意:zoomTo方法可能需要根据实际情况调整,这里只是一个示例
      for (let key in params) {
        const item = params[key]
        const response = await fetch(item.areaData)
        const { features } = await response.json();
        const data = features[0].geometry.coordinates
        let newArray = []
        const polylineInstance = []
        for (let i = 0; i < data.length; i++) {
          newArray.push(data[i][0], data[i][1])
          if (i % 2 === 0) {
            const endPosition = DT.Cesium.Cartesian3.fromDegrees(data[i][0], data[i][1], 0)
            polylineInstance.push(createPolyLine(item.position, endPosition))
          }
        }
        //添加多边形
        let polygon = viewer.entities.add({
          name: 'polygon',
          polygon: {
            //显示
            show: true,
            //层级结构,轮廓线坐标
            hierarchy: {
              positions: DT.Cesium.Cartesian3.fromDegreesArray(newArray),
            },
            height: 1000,
            heightReference: DT.Cesium.HeightReference.NONE,
            extrudedHeightReference: DT.Cesium.HeightReference.NONE,
            stRotation: Math.PI,
            granularity: Math.PI / 180,
            fill: true,
            //材质
            material: DT.Cesium.Color.GREEN.withAlpha(0.4),
            //是否开启轮廓线
            outline: true,
            //轮廓线颜色
            outlineColor: DT.Cesium.Color.AQUA,
            //轮廓线宽度
            outlineWidth: 1,
            //先前坐标高度 -只根据经纬度创建几个高度,不随地球曲率生成曲面
            perPositionHeight: false,
            //顶部封口
            closeTop: true,
            //底部封口
            closeBottom: true,
            //两点之间连线方式:NONE 直接连接  GEODESIC 测地线, RHUMB 恒向线
            arcType: DT.Cesium.ArcType.GEODESIC,
            //阴影类型
            shadows: DT.Cesium.ShadowMode.ENABLED,
          }
        })
        //添加线
        let primitives = viewer.primitives;
        let primitiveCollection = new DT.Cesium.PrimitiveCollection();
        primitives.add(primitiveCollection);
        //创建模型
        let model = await createModel(item.modelUrl, item.position, item.scale, primitiveCollection);
        let currentPolyline;



        const randomIndexes = [1, 4, 5, 9, 10, 15, 17, 22, 23, 27, 29, 35, 36, 37, 45, 47, 55, 57, 65, 66, 70, 72, 85, 95, 97, 100, 102, 111, 123, 135, 140, 141, 150, 152, 160]
        viewer.cesiumViewer.scene.preRender.addEventListener(async function () {
          const frontPosition = getCameraFrontPosition(item.distanceFromCamera, item.verticalOffset, item.horizontalOffset);
          //创建模型位置矩阵
          //更新模型矩阵
          model.modelMatrix = DT.Cesium.Transforms.eastNorthUpToFixedFrame(frontPosition);
          //每帧都会计算位置和连线
          // const newArray = []
          const polylineInstance = []
          for (let i = 0; i < randomIndexes.length; i++) {
      
            const value = randomIndexes[i]
            if (data[value]) {
              const endPosition = DT.Cesium.Cartesian3.fromDegrees(data[value][0], data[value][1], 0)
              polylineInstance.push(createPolyLine(frontPosition, endPosition))
            }

          }
          if (currentPolyline) {
            removePolyline(currentPolyline, primitiveCollection);
          }
          currentPolyline = addPolyline(polylineInstance, primitiveCollection);
        });
      }

注意

  1. Cesium Ion访问令牌:如果你不使用Cesium Ion服务(如地形数据、影像数据等),则可以省略Cesium.Ion.defaultAccessToken的设置。
  2. 多边形闭合:在定义polygonHierarchy时,坐标数组需要是闭合的,即首尾坐标需要相同,以确保多边形是封闭的。
  3. zoomTo方法:Cesium的zoomTo方法可能并不总是直接接受viewer.entities作为参数。如果需要自动将视角调整到特定实体或一组实体上,你可能需要使用其他方法,如viewer.flyTo结合实体的位置来计算飞行目标。

以上Demo展示了如何在Cesium中创建一个简单的多边形实体,并通过hierarchy属性定义了其顶点坐标。你可以根据需要调整多边形的颜色、边框等属性。