Cesium 坐标拾取Pick(1)

20 篇文章 1 订阅
20 篇文章 7 订阅

一、简介

        在Cesium中坐标的拾取非常重要,比如在标绘、测量等功能中需要获取地球表面、地形、三维模型、实体元素等物体表面的经纬度和高程,这样绘制的图形才能准确,拿到的坐标才可以使用。

        与拾取相关的API比较多,不同的API适用的场景不同。比较常用的有scene.pickPosition、scene.pickPositionSupported、scene.pickTranslucentDepth、scene.pick、scene.drillPick、scene.camera.pickEllipsoid、scene.camera.getPickRay、scene.globe.pick等。另外还有一些私有类或者方法有时候也会用到,包括scene.picking、scene.pickFromRay、scene.drillPickFromRay等。

        下面根据我自己在产品封装和项目中实际经验先大致说一下。【不涉及原理细节,拾取原理请等待第2篇文章】

1) scene.pick [拾取到实体对象]

        该API签名为pick(windowPosition, width, height) → Object

        返回一个具有“primitive”属性的对象,该对象包含特定窗口坐标处场景中的第一个(顶部)基元,如果该位置没有任何内容,则返回未定义的对象。可以根据基元的类型潜在地设置其他属性,并且可以用于进一步识别拾取的对象。

        拾取3dtiles后,拾取将返回Cesium3DTileFeature对象。

2)scene.drillPick [拾取到实体对象]

        该API签名为drillPick(windowPosition, limit, width, height) → Array.<*>

        穿透拾取到多个对象。

3)scene.globe.pick[拾取到坐标]

        该API签名为pick(ray, scene, result) → Cartesian3|undefined

        返回射线和地球Globe交点的坐标,Globe包括地形图层、影像图层等,因此拾取到与地形交点的坐标。

4)scene.pickPosition[拾取到坐标]

        该API签名为pickPosition(windowPosition, result) → Cartesian3

        返回从深度缓冲区和窗口位置重建的笛卡尔位置。

5)scene.camera.pickEllipsoid[拾取到坐标]

        该API签名为pickEllipsoid(windowPosition, ellipsoid, result) → Cartesian3|undefined

        拾取椭球体表面的坐标。

        通常拾取坐标的时候要做一些判断,先用scene.pick判断拾取到的对象类型,如果是三维模型(gltf、3dtiles等)或者Entity、primitive等,则调用scene.pickPosition;然后再判断是否加载了地形图层,如果有地形(不是默认地形),则调用scene.globe.pick,否则调用scene.camera.pickEllipsoid。

        也可以调用私有方法scene.drillPickFromRay,这个也是准确的,可以穿透拾取,可以排除掉不想拾取的对象,该API有一些特殊的优势,后续再介绍。

        另外在做绘制功能的时候有时候还需要直接采用拾取到的点对象的坐标作为拾取到的最终坐标。

        在调用scene.drillpick再调用scene.pickPosition会导致坐标不准,参考资料:Result of `pickPosition` changes after call to `drillPick` - CesiumJS - Cesium Community

        其他与拾取相关的博文请参考Cesium的拾取问题总结 - 知乎Cesium——PICK不同使用场景_cesium pick-CSDN博客

        其他参考资料Graphics Tech in Cesium - Renderer Architecture – Cesium

        How to get the object (ID) of every pixel? - CesiumJS - Cesium Community

        https://github.com/CesiumGS/cesium/blob/1.95/Source/Scene/Scene.js#L154

二、效果

三、代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>标绘</title>
    <script src="./js/config.js"></script>
    <script src="./scripts/vue.min.js"></script>
    <script type="text/javascript" src="./scripts/element.index.js"></script>
    <link rel="stylesheet" href="./scripts/element.index.css">
    <link rel="stylesheet" href="./css/common.css">
    <script type="text/javascript" src="../anov-gis-sdk/index.js"></script>
    <link rel="stylesheet" href="../anov-gis-sdk/index.css">
    <style>
        .draw-panel {
            height: 70px;
            line-height: 70px;
            padding-left: 20px;
            padding-right: 20px;
        }
    </style>
</head>

<body>
    <div id="global">

    </div>
    <script>
        let g_polylineMeasurement;
        let g_pointMeasurement;
        let g_polygonMeasurement;
        let g_rectMeasurement;
        let g_CirgleMeasurement;
        let g_triangleMeasurement;
        new Vue({
            el: '#global',
            template: `
          <div id="cesiumContainer">
            <div class="draw-click draw-panel">
                <el-row>
                    <el-button type="primary" @click="pointMeasurement">点</el-button>
                    <el-button type="primary" @click="distanceMeasurement">折线</el-button>
                    <el-button type="primary" @click="areaMeasurement">多边形</el-button>
                    <el-button type="primary" @click="areaMeasurement_rect">矩形</el-button>
                    <el-button type="primary    " @click="areaMeasurement_circle">圆</el-button>
                    <el-button type="primary    " @click="addTerrain">地形</el-button> 
                    <el-checkbox style="display:inline-block" @change="depthTest">深度测试</el-checkbox>                                     
                    <el-button type="danger" @click="clearMeasurementResults">清除</el-button>
                </el-row>                
            </div>
          </div>`,
            data() {
                return {
                    tool: "",
                    inited: false
                };
            },
            mounted() {
                this.init3D();
                this.initMeasure();
            },
            methods: {
                init3D() {
                    window.viewer = new ANOVGIS.Viewer("cesiumContainer", {
                        contextOptions: {
                            id: "cesiumCanvas", 
                            webgl: {
                                preserveDrawingBuffer: true, 
                            },
                            showRenderLoopErrors: false,
                        },
                        geocoderType: ANOVGIS.GeocoderType.TIANDITU,
                        vrButton: false,
                        baseLayerPicker: true,
                        fullscreenButton: true,
                        homeButton: true,
                        sceneModePicker: true,
                        navigationHelpButton: true,
                        copyRight: false,
                        showMapInfo: true,
                        drillPick: false
                    });
                    //viewer.scene.debugShowFramesPerSecond = true;

                    const baselayer = ANOVGIS.ImageryLayerFactory.createImageryLayer(
                        ANOVGIS.ImageryType.TDT,
                        {
                            style: "img",
                            key: globalConfig.tdtKey
                        }
                    );
                    viewer.imageryLayers.addImageryProvider(baselayer);
                    this.initMouseEvent();
                    this.add3dtiles();
                    this.addBoxGraphic();
                    this.addModelGraphic();
                },
                initMouseEvent() {
                    viewer.addEventListener(ANOVGIS.MouseEventType.CLICK, (e) => {
                        console.log(e);
                    })
                },
                add3dtiles() {
                    let layer = new ANOVGIS.TilesetLayer();
                    viewer.addLayer(layer);
                    let tileset = new ANOVGIS.Tileset({
                        url: 'http://localhost/gis-share/shanghaiafter/tileset.json'
                    })
                    // tileset.clampToGround();
                    layer.addGraphic(tileset);
                },
                addBoxGraphic() {
                    const redBox = viewer.entities.add({
                        name: "Red box with black outline",
                        position: Cesium.Cartesian3.fromDegrees(121.44, 31.1434, 500.0),
                        box: {
                            dimensions: new Cesium.Cartesian3(400.0, 300.0, 500.0),
                            material: Cesium.Color.RED.withAlpha(0.8),
                            outline: true,
                            outlineColor: Cesium.Color.BLACK,
                        },
                    });
                },
                addModelGraphic() {
                    viewer.entities.add({
                        name: 'modeltest',
                        position: Cesium.Cartesian3.fromDegrees(121.64, 31.6434, 0.0),
                        model: {
                            scale: 1000,
                            uri: 'http://localhost/gis-share/other/CesiumMilkTruck.glb',
                        },
                    });
                },
                addTerrain() {
                    if (window.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider) {
                        const CesiumTerrian = Cesium.createWorldTerrain();
                        viewer.terrainProvider = CesiumTerrian;
                    } else {
                        viewer.terrainProvider = new Cesium.EllipsoidTerrainProvider();
                    }
                },
                depthTest(t) {
                    viewer.scene.globe.depthTestAgainstTerrain = t;
                },                
                initMeasure() {
                    if (!this.inited) {
                        this.inited = true;
                    }
                    this.clear();
                    g_pointMeasurement = new ANOVGIS.DrawPoint(viewer, {
                        justDraw: false,
                        pointSize: 12,
                        pointColor: Cesium.Color.YELLOW,
                        tempPoint_show: true,
                        showToolTip: false,
                        tempPoint_color: Cesium.Color.YELLOW,
                        onCompleted(positions) {
                            console.log(positions);
                        }
                    });
                    g_polylineMeasurement = new ANOVGIS.DrawPolyLine(viewer, {
                        lineColor: Cesium.Color.YELLOW,
                        justDraw: false,
                        onCompleted(positions) {
                            console.log(positions);
                        }
                    });
                    g_polygonMeasurement = new ANOVGIS.DrawPolygon(viewer, {
                        justDraw: false,

                        fillColor: Cesium.Color.YELLOW.withAlpha(0.5),
                        onCompleted(positions) {
                            console.log(positions);
                        }
                    });
                    g_rectMeasurement = new ANOVGIS.DrawRectangle(viewer, {
                        justDraw: false,
                        onCompleted(positions) {
                            console.log(positions);
                        }
                    });
                    g_CirgleMeasurement = new ANOVGIS.DrawCircle(viewer, {
                        justDraw: false,
                        fill: false,
                        outline: true,
                        outlineWidth: 4,
                        outlineColor: ANOVGIS.Color.YELLOW,
                        clampToGround: true,
                        onCompleted(positions) {
                            console.log(positions);
                        }
                    });
                },
                clear() {
                    if (g_polylineMeasurement) {
                        g_polylineMeasurement.clear();
                    }
                    if (g_polygonMeasurement) {
                        g_polygonMeasurement.clear();
                    }
                    if (g_pointMeasurement) {
                        g_pointMeasurement.clear();
                    }
                    if (g_rectMeasurement) {
                        g_rectMeasurement.clear();
                    }
                    if (g_CirgleMeasurement) {
                        g_CirgleMeasurement.clear();
                    }
                },
                end() {
                    if (g_polylineMeasurement) {
                        g_polylineMeasurement.end();
                    }
                    if (g_polygonMeasurement) {
                        g_polygonMeasurement.end();
                    }
                    if (g_pointMeasurement) {
                        g_pointMeasurement.end();
                    }
                    if (g_rectMeasurement) {
                        g_rectMeasurement.end();
                    }
                    if (g_CirgleMeasurement) {
                        g_CirgleMeasurement.end();
                    }
                },
                pointMeasurement: function () {
                    this.end();
                    g_pointMeasurement.startDraw();
                    this.tool = "point";
                },
                distanceMeasurement: function () {
                    this.end();
                    g_polylineMeasurement.startDraw();
                    this.tool = "distance";
                },
                triangleMeasurement: function () {
                    this.end();
                    g_triangleMeasurement.startDraw();
                    this.tool = "triangle";
                },
                areaMeasurement: function () {
                    this.end();
                    g_polygonMeasurement.startDraw();
                    this.tool = "area";
                },
                areaMeasurement_rect: function () {
                    this.end();
                    g_rectMeasurement.startDraw();
                    this.tool = "area_rect";
                },
                areaMeasurement_circle: function () {
                    this.end();
                    g_CirgleMeasurement.startDraw();
                    this.tool = "area_circle";
                },
                clearMeasurementResults: function () {
                    this.clear();
                    this.tool = "";
                }
            }
        });
    </script>
</body>

</html>

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苹果园dog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值