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的理解也会越来越深,也希望大家对自己的研究的技术越来深入和精通。

相关推荐
undefined&&懒洋洋3 天前
Cesium使用flyToBoundingSphere实现倾斜相机视角观察物体
前端·javascript·cesium·webgis
GIS瞧葩菜6 天前
GeoSever发布图层(保姆姬)
wms·geoserver·cesium
新中地GIS开发老师7 天前
地理信息科学专业想搞GIS开发:学前端还是后端?
前端·javascript·arcgis·前端框架·cesium
qbbmnnnnnn13 天前
【WebGis开发 - Cesium】三维可视化项目教程---图层管理拓展图层顺序调整功能
vue.js·webgl·三维可视化·cesium·vue3.0·webgis·vuedraggable
smiler15 天前
cesium两种方式实现贴地
前端·cesium
按图索迹17 天前
100GB,台湾台东县绿岛倾斜摄影3DTiles数据来了
三维可视化·cesium·倾斜摄影·3dtiles·台湾倾斜摄影
htsitr24 天前
Cesium如果链接着色器的?
cesium·着色器
T0uken1 个月前
【WebGIS】Cesium:Viewer 初始化、地图加载与基础交互
gis·cesium·webgis
qbbmnnnnnn1 个月前
【WebGis开发 - Cesium】三维可视化项目教程---图层管理基础
前端·wmts·cesium·vue3.0·webgis·3dtiles·图层管理
按图索迹1 个月前
台湾高雄三维倾斜摄影模型3DTiles样例数据介绍
人工智能·3d·cesium·倾斜摄影·3dtiles·台湾·3dgis