cesium如何实现区域下钻

        首先,这里讲一下数据源,数据源是拷贝的DataV.GroAtlas里的数据,这里整合了一下之前发的区域高亮的代码来实现的,单击左键使得区域高亮,每次点击都移除上一次点击的模块,双击左键,实现区域下钻并请求对应的数据源,单击右键来实现恢复上一层级。具体代码如下:

<template>
  <div>
    <CesiumViewer ref="cesiumViewerRef" />
  </div>
</template>

<script setup>
import * as Cesium from "cesium";
import { ref, onMounted } from "vue";
import {
  province,
  xizang,
  ali,
  naqu,
  changdu,
  linzhi,
  shannan,
  lasan,
  rika,
} from "./json/data";
// import CesiumViewer from "../../cesiumComponents/cesiumViewer.vue";
import CesiumViewer from "@/components/cesiumViewer.vue";
let viewer, dataSource, highlightEntity;
const cesiumViewerRef = ref();

const regionValue = ref();
const regionData = ref([]);

onMounted(() => {
  viewer = window.cesiumViewer;
  dataSource = new Cesium.GeoJsonDataSource();
  viewer.dataSources.add(dataSource);
  provinceDataSource();
});
// 移除高亮显示
const removeHighlight = () => {
  if (Cesium.defined(highlightEntity)) {
    highlightEntity.polygon.material = Cesium.Color.POWDERBLUE.withAlpha(0.3);
    highlightEntity = null;
  }
};
// 加载西藏
const provinceDataSource = () => {
  // 移除事件监听和高亮显示
  destroyAllEvents();
  dataSource
    .load(province, {
      fill: Cesium.Color.TRANSPARENT,
      stroke: Cesium.Color.TRANSPARENT, //设置多边形轮廓的默认颜色
      strokeWidth: 20, //轮廓的宽度
      clamToGround: true, //让地图贴地
    })
    .then(() => {
      // 设置行政区域的样式
      const entities = dataSource.entities.values;
      entities?.forEach((item, index) => {
        const entity = entities[index];
        if (entity.name == "西藏自治区") {
          entity.polygon.material = Cesium.Color.POWDERBLUE.withAlpha(0.3);
          entity.polygon.outline = true;
          entity.polygon.outlineColor = Cesium.Color.RED;
          var polyPositions = entity.polygon.hierarchy.getValue(
            Cesium.JulianDate.now()
          ).positions;
          var polyCenter =
            Cesium.BoundingSphere.fromPoints(polyPositions).center;
          polyCenter =
            Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
          viewer.entities.add({
            position: polyCenter,
            label: {
              //标签
              scale: 0.6,
              font: "24px sans-serif",
              text: entity.properties.name,
              // showBackground: true,
              horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
              verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            },
          });
        }
      });
    });

  // 双击
  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      Cesium.defined(pickedObject) &&
      pickedObject.id instanceof Cesium.Entity &&
      pickedObject.id.name === "西藏自治区"
    ) {
      removeHighlight();
      console.log(pickedObject.id.properties.adcode);
      if (pickedObject.id.properties.adcode) {
        cityDataSource();
        // 移除父级区域
        viewer.entities.removeAll();
      }

      // 高亮显示行政区域
    } else {
      removeHighlight();
    }
  }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

  // 单击
  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      Cesium.defined(pickedObject) &&
      pickedObject.id instanceof Cesium.Entity &&
      pickedObject.id.name === "西藏自治区"
    ) {
      removeHighlight();
      // 高亮显示行政区域
      highlightEntity = pickedObject.id;
      regionValue.value = highlightEntity.properties.adcode.getValue()
      highlightEntity.polygon.material = Cesium.Color.POWDERBLUE;
    } else {
      removeHighlight();
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
};

const cityDataSource = () => {
  // 移除事件监听和高亮显示
  destroyAllEvents();
  dataSource
    .load(xizang, {
      stroke: Cesium.Color.TRANSPARENT, //设置多边形轮廓的默认颜色
      strokeWidth: 20, //轮廓的宽度
      clamToGround: true, //让地图贴地
    })
    .then(() => {
      // 设置行政区域的样式
      const entities = dataSource.entities.values;
      entities?.forEach((item, index) => {
        const entity = entities[index];
        entity.polygon.material = Cesium.Color.POWDERBLUE.withAlpha(0.3);
        entity.polygon.outline = true;
        entity.polygon.outlineColor = Cesium.Color.RED;
        var polyPositions = entity.polygon.hierarchy.getValue(
          Cesium.JulianDate.now()
        ).positions;
        var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
        viewer.entities.add({
          position: polyCenter,
          label: {
            //标签
            scale: 0.6,
            font: "24px sans-serif",
            text: entity.properties.name,
            // showBackground: true,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          },
        });
      });
    });
  let pickedId = "";
  // 单击
  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      Cesium.defined(pickedObject) &&
      pickedObject.id instanceof Cesium.Entity
    ) {
      pickedId = pickedObject.id.id;
      removeHighlight();
      // 高亮显示行政区域
      highlightEntity = pickedObject.id;
      regionValue.value = highlightEntity.properties.adcode.getValue()
      highlightEntity.polygon.material = Cesium.Color.POWDERBLUE;
    } else {
      removeHighlight();
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  // 双击
  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      Cesium.defined(pickedObject) &&
      pickedObject.id instanceof Cesium.Entity
    ) {
      if (pickedObject.id.name == "阿里地区") {
        countyDataSource(ali);
      } else if (pickedObject.id.name == "那曲市") {
        countyDataSource(naqu);
      } else if (pickedObject.id.name == "昌都市") {
        countyDataSource(changdu);
      } else if (pickedObject.id.name == "林芝市") {
        countyDataSource(linzhi);
      } else if (pickedObject.id.name == "山南市") {
        countyDataSource(shannan);
      } else if (pickedObject.id.name == "拉萨市") {
        countyDataSource(lasan);
      } else if (pickedObject.id.name == "日喀则市") {
        countyDataSource(rika);
      }
      removeHighlight();
      // 移除父级区域
      viewer.entities.removeAll();
      // viewer.dataSources.removeAll();
    } else {
      removeHighlight();
    }
  }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      typeof pickedObject == "undefined" ||
      (Cesium.defined(pickedObject) &&
        pickedObject.id instanceof Cesium.Entity &&
        pickedObject.id.id !== pickedId)
    ) {
      removeHighlight();
      // 移除父级区域
      viewer.entities.removeAll();
      provinceDataSource();
    }
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};

const countyDataSource = (data) => {
  // 移除事件监听和高亮显示
  destroyAllEvents();
  dataSource
    .load(data, {
      stroke: Cesium.Color.TRANSPARENT, //设置多边形轮廓的默认颜色
      strokeWidth: 20, //轮廓的宽度
      clamToGround: true, //让地图贴地
    })
    .then(() => {
      // 设置行政区域的样式
      const entities = dataSource.entities.values;
      entities?.forEach((item, index) => {
        const entity = entities[index];
        entity.polygon.material = Cesium.Color.POWDERBLUE.withAlpha(0.3);
        entity.polygon.outline = true;
        entity.polygon.outlineColor = Cesium.Color.RED;
        var polyPositions = entity.polygon.hierarchy.getValue(
          Cesium.JulianDate.now()
        ).positions;
        var polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;
        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);
        viewer.entities.add({
          position: polyCenter,
          label: {
            //标签
            scale: 0.6,
            font: "24px sans-serif",
            text: entity.properties.name,
            // showBackground: true,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
          },
        });
      });
    });
  // 单击
  let pickedId = "";
  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      Cesium.defined(pickedObject) &&
      pickedObject.id instanceof Cesium.Entity
    ) {
      pickedId = pickedObject.id.id;
      removeHighlight();
      // 高亮显示行政区域
      highlightEntity = pickedObject.id;
      highlightEntity.polygon.material = Cesium.Color.POWDERBLUE;
    } else {
      removeHighlight();
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  viewer.screenSpaceEventHandler.setInputAction((event) => {
    const pickedObject = viewer.scene.pick(event.position);
    if (
      typeof pickedObject == "undefined" ||
      (Cesium.defined(pickedObject) &&
        pickedObject.id instanceof Cesium.Entity &&
        pickedObject.id.id !== pickedId)
    ) {
      removeHighlight();
      // 移除父级区域
      viewer.entities.removeAll();
      cityDataSource();
    }
  }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
};

// 移除事件
const destroyAllEvents = () => {
  // 单击左键
  viewer.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_CLICK
  );
  // 双击左键
  viewer.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
  // 单击右键
  viewer.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.RIGHT_CLICK
  );
};
const handleNodeClick = (e) => {
  console.log(e, "========1234");
};
</script>

<style lang="scss" scoped>
.zkr-el-tree {
  width: 240px;
  height: 500px;
  overflow: auto;
  position: absolute;
  top: 20px;
}
</style>

注:如有问题或者有更好的解决方式可以联系笔者,进行解答及优化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现局部区域等高线,需要先获取该区域的高程数据。然后,可以使用Cesium的TerrainProvider来加载高程数据,并利用Cesium的Terrain-quantized-mesh来渲染地形。接着,将等高线数据转换成多边形,并使用Cesium的PolygonGeometry来渲染等高线。最后,通过调整等高线的颜色和透明度,使其更加清晰可见。 以下是一个实现局部区域等高线的示例代码: ```javascript // 加载地形 var terrainProvider = new Cesium.CesiumTerrainProvider({ url : 'https://assets.agi.com/stk-terrain/world', requestVertexNormals : true }); viewer.terrainProvider = terrainProvider; // 获取局部区域高程数据 var rectangle = Cesium.Rectangle.fromDegrees(110, 20, 120, 30); var terrainData = terrainProvider.requestTileGeometry(0, 0, 0); // 转换等高线数据 var contourData = generateContourData(terrainData, rectangle, 100); // 渲染等高线 var contourGeometry = Cesium.PolygonGeometry.fromContour({ polygonHierarchy : new Cesium.PolygonHierarchy(contourData), height : 0, extrudedHeight : 0 }); var contourInstance = new Cesium.GeometryInstance({ geometry : contourGeometry, attributes : { color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5)) } }); var contourPrimitive = new Cesium.Primitive({ geometryInstances : contourInstance, appearance : new Cesium.PerInstanceColorAppearance() }); viewer.scene.primitives.add(contourPrimitive); // 生成等高线数据 function generateContourData(terrainData, rectangle, interval) { var longitudeExtent = Cesium.Math.toDegrees(terrainData.longitudeExtent); var latitudeExtent = Cesium.Math.toDegrees(terrainData.latitudeExtent); var terrainWidth = terrainData._uVertexCount - 1; var terrainHeight = terrainData._vVertexCount - 1; var gridWidth = longitudeExtent / terrainWidth; var gridHeight = latitudeExtent / terrainHeight; var minHeight = Number.MAX_VALUE; var maxHeight = Number.MIN_VALUE; var contourData = []; for (var i = 0; i < terrainWidth; i++) { for (var j = 0; j < terrainHeight; j++) { var x = rectangle.west + i * gridWidth; var y = rectangle.south + j * gridHeight; var height = terrainData.getHeight(i, j); minHeight = Math.min(minHeight, height); maxHeight = Math.max(maxHeight, height); } } for (var k = minHeight + interval; k <= maxHeight; k += interval) { var contourLine = []; for (var i = 0; i < terrainWidth; i++) { for (var j = 0; j < terrainHeight; j++) { var x = rectangle.west + i * gridWidth; var y = rectangle.south + j * gridHeight; var height = terrainData.getHeight(i, j); if (height >= k && height < k + interval) { var p1 = Cesium.Cartesian3.fromDegrees(x, y, height); var p2 = Cesium.Cartesian3.fromDegrees(x + gridWidth, y, terrainData.getHeight(i + 1, j)); var p3 = Cesium.Cartesian3.fromDegrees(x + gridWidth, y + gridHeight, terrainData.getHeight(i + 1, j + 1)); var p4 = Cesium.Cartesian3.fromDegrees(x, y + gridHeight, terrainData.getHeight(i, j + 1)); contourLine.push(p1, p2, p3, p4, p1); } } } if (contourLine.length > 0) { contourData.push(contourLine); } } return contourData; } ``` 需要注意的是,由于等高线的渲染是通过多边形来实现的,因此等高线的精度和效率都与多边形数量有关。因此,在实际应用中需要根据需求和性能做出权衡。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值