Cesium保姆教程之绘制任意多边形

Cesium保姆教程之绘制任意多边形

本人是一个cesium小白,对于cesium理解的不是非常透彻,因此只能根据自己的理解和网上的大佬教程进行编写,把工作中所涉及到的cesium工作,做成一个一个小功能效果,由于本人刚开始写文章,导致文章多处语句不通顺流畅,请见谅,由于工作和自己的原因,导致了自己很久没有写文章,也没有对cesium进行提炼总结,打算这段时间对cesium进行总结提炼。本文所涉及到的前端技术栈主要是vue3+cesium,后续慢慢更新关于cesium效果的其他案例。

本篇是实现cesium的绘制任意多边形功能,参考案例:Drawing on Terrain - Cesium Sandcastle

思路

鼠标左击事件:获取点,添加获取到的点(第一次左击的时候要添加两次点,这样会确保在鼠标移动的时候已经添加上多边形);

鼠标移动事件:移动,不断删除上一个点,并获取最后一个点的位置信息添加到多边形顶点中;

鼠标右击事件:结束绘制。

实现效果

实现代码

鼠标左击事件

js 复制代码
handler.setInputAction((event) => {
        let ray = viewer.camera.getPickRay(event.position);
        let earthPosition = viewer.scene.globe.pick(ray, viewer.scene)
        //鼠标开始点击多边形的第一个点
        if (activeShapePoints.length === 0) {
            //将第一个左击的点添加到多边形顶点集合中
            activeShapePoints.push(earthPosition)
            //多边形的坐标采用回调的形式
            //边线顶点
            let linePoints = new Cesium.CallbackProperty(() => {
                let vertexPoints = activeShapePoints.concat([activeShapePoints[0]]);
                return vertexPoints;
            }, false)
            //多边形顶点
            let dynamicPositions = new Cesium.CallbackProperty(() => {
                return new Cesium.PolygonHierarchy(activeShapePoints)
            }, false)
            //添加一个多边形
            polygon = viewer.entities.add({
                name: "Polygon",
                id: id,
                polyline: {
                    positions: linePoints,
                    width: outlineWidth,
                    material: outlineColor,
                    clampToGround: true
                },
                polygon: {
                    hierarchy: dynamicPositions,
                    material: color,
                    outlineColor: outlineColor,
                    height: 0
                }
            })
            
            polygon.GeoType = "Polygon"
        }
        //将鼠标点击的点添加到多边形顶点集合中
        activeShapePoints.push(earthPosition)
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

鼠标移动事件

js 复制代码
//鼠标移动事件
    handler.setInputAction((movement) => {
        //获取鼠标所在的位置
        const ray = viewer.camera.getPickRay(movement.endPosition)
        const newPosition = viewer.scene.globe.pick(ray, viewer.scene)
        //已经定义了polygon
        if (Cesium.defined(polygon)) {
            //删除多边形顶点中最新的一个点
            activeShapePoints.pop()
            //将最新获取到的点添加到多边形顶点集合中
            activeShapePoints.push(newPosition)
        }
        if (activeShapePoints.length === 3) {
            polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND;
        }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

鼠标右击事件

js 复制代码
handler.setInputAction((event) => {
        //删除最后一个点(重复添加的点)
        activeShapePoints.pop()
        polygon.pottingPoint = activeShapePoints
        //将所有的点添加到结果数组中
        resList.push(polygon)
        //销毁右击事件
        handler.destroy()
        if (typeof callback === "function") callback(polygon)
    }, Cesium.ScreenSpaceEventType.RIGHT_DOWN)

完整源码

创建任意多边形createPolygon.js

js 复制代码
const createPolygon = (viewer, resList, options, callback) => {
    if (!viewer) throw new Error("no viewer object!")
    options = options || {};
    let id = options.id || getRandomId();
    if (viewer.entities.getById(id)) {
        throw new Error("the id is an unique value")
    }
    let color = options.color || Cesium.Color.WHITE;
    let outlineColor = options.outlineColor || color.withAlpha(1)
    // let outlineColor = color.withAlpha(1);
    const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    // let tip = "左键点击开始绘制";
    let activeShapePoints = [];
    let polygon = undefined;
    let floatingPoint = undefined;
    let drawStatus = true;
    //鼠标左击事件
    handler.setInputAction((event) => {
        let ray = viewer.camera.getPickRay(event.position);
        let earthPosition = viewer.scene.globe.pick(ray, viewer.scene)
        // debugger
        //鼠标开始点击多边形的第一个点
        if (activeShapePoints.length === 0) {
            // debugger
            floatingPoint = createPoint(viewer, earthPosition)
            //将第一个左击的点添加到多边形顶点集合中
            activeShapePoints.push(earthPosition)
            //多边形的坐标采用回调的形式
            //多边形边界顶点
            let polylinePoints = new Cesium.CallbackProperty(() => {
                let vertexPoints = activeShapePoints.concat([activeShapePoints[0]])
                return vertexPoints
            }, false)
            //多边形顶点
            let dynamicPositions = new Cesium.CallbackProperty(() => {
                return new Cesium.PolygonHierarchy(activeShapePoints)
            }, false)
            //添加一个多边形
            polygon = viewer.entities.add({
                name: "Polygon",
                id: id,
                polyline: {
                    positions: polylinePoints,
                    width: 5,
                    material: outlineColor,
                    clampToGround: true
                },
                polygon: {
                    hierarchy: dynamicPositions,
                    material: color,
                    heightReference: Cesium.HeightReference.NONE
                    // outlineColor: outlineColor,
                    // height: 0
                }
            })
            polygon.GeoType = "Polygon"
        }
        //将鼠标点击的点添加到多边形顶点集合中
        activeShapePoints.push(earthPosition)
        createPoint(viewer, earthPosition)
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    //鼠标移动事件
    handler.setInputAction((movement) => {
        //获取鼠标所在的位置
        const ray = viewer.camera.getPickRay(movement.endPosition);
        const newPosition = viewer.scene.globe.pick(ray, viewer.scene);
        //已经定义了polygon
        if (Cesium.defined(polygon)) {
            floatingPoint.position.setValue(newPosition);
            console.log("object");
            //删除多边形顶点中最新的一个点
            activeShapePoints.pop()
            //将最新获取到的点添加到多边形顶点集合中
            activeShapePoints.push(newPosition)
        }
        if (activeShapePoints.length === 3) {
            polygon.polygon.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
        }
         console.log("ssssssss");
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    handler.setInputAction((event) => {
        //删除最后一个点(重复添加的点)
        activeShapePoints.pop()
        polygon.pottingPoint = activeShapePoints
        //将所有的点添加到结果数组中
        resList.push(polygon)
        //销毁右击事件
        handler.destroy()
        drawStatus = false
        if (typeof callback === "function") callback(polygon)
    }, Cesium.ScreenSpaceEventType.RIGHT_DOWN)
}

前端调用

index.vue

vue 复制代码
<template>
    <div>
        <div id="cesiumContainer">
            <div class="plotting-tool">
                <el-button @click="startDraw()">开始创建</el-button>
            </div>
        </div>

    </div>
</template>

<script setup>
import * as Cesium from "cesium"
import "cesium/Source/Widgets/widgets.css"

import initCesium from "@/cesiumUtils/initCesium"
import createPolygon from "@/components/createPolygon";
import { onMounted } from "vue";


let viewer = null;
//生命周期钩子
onMounted(async () => {
    viewer = await initCesium("cesiumContainer");
    viewer.camera.lookAt(
        Cesium.Cartesian3.fromDegrees(-122.2058, 46.1955, 1000.0),
        new Cesium.Cartesian3(5000.0, 5000.0, 5000.0)
    );
    viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
})
const startDraw = () => {
    createPolygon(viewer, [], 
        { 
            color: Cesium.Color.BLUE, 
            outlineColor: Cesium.Color.GREEN 
        }, 
        (e) => { console.log(e); }
    )
}

</script>

<style lang="less" scoped>
#cesiumContainer {
    width: 100vw;
    height: 100vh;
    margin: 0;
    padding: 0;
    overflow: hidden;
    position: relative;

}

.dynamic-trail-tools {
    position: absolute;
    border: 1px solid rgb(31, 30, 30);
    border-radius: 5px;
    background-color: rgba(66, 65, 66, 0.8);
    z-index: 9999;
    margin: 10px;
    padding: 10px;
}

.edit {
    position: absolute;
    top: 0;
    left: 0;
    padding: 10px;
}

.plotting-tool {
    position: absolute;
    margin: 10px;
    padding: 10px;
    border: 1px solid rgb(39, 38, 38);
    border-radius: 5px;
    background-color: rgba(66, 65, 66, 0.8);
    z-index: 10;
}
</style>

好了,以上就是本篇文章的全部内容,由于本人是第一次写这种技术博客,缺乏经验,语言也过于简单,请见谅。本篇后续也会不断修改完善,主要是对于点的获取不能仅仅局限于地形,也会在模型上进行绘制,这个会马上进行更新。文章中也有些许地方写的不对,请各位同学和同行进行批评指正,希望有你们的批评指正能让我的文章会越来越完善,自己对于cesium的理解也会越来越深,也希望大家对自己的研究的技术越来深入和精通。

相关推荐
gis_rc4 天前
python下shp转3dtiles
python·3d·cesium·3dtiles·数字孪生模型
grasperp5 天前
3DTiles数据切片工具,支持LAS、OBJ、FBX 3DTiles怎么切片?3DTiles切片
cesium·3dtiles·三维gis·3dtiles切片·数据切片
duansamve7 天前
Cesium中实现在地图上移动/旋转点、线、面
cesium
冥界摄政王8 天前
CesiumJS学习第四章 替换指定3D建筑模型
3d·vue·html·webgl·js·cesium
冥界摄政王10 天前
Cesium学习第二章 camera 相机
node.js·html·vue3·js·cesium
冥界摄政王11 天前
Cesium学习第一章 安装下载 基于vue3引入Cesium项目开发
vue·vue3·html5·webgl·cesium
你们瞎搞13 天前
Cesium加载20GB航测影像.tif
前端·cesium·gdal·地图切片
闲云一鹤14 天前
Cesium 使用 Turf 实现坐标点移动(偏移)
前端·gis·cesium
二狗哈14 天前
Cesium快速入门34:3dTile高级样式设置
前端·javascript·算法·3d·webgl·cesium·地图可视化
二狗哈15 天前
Cesium快速入门33:tile3d设置样式
3d·状态模式·webgl·cesium·地图可视化