铯如何在放大/缩小时缩放多边形以匹配Lat-Lon位置

时间:2016-03-10 23:15:32

标签: javascript node.js cesium

我正在寻找一位Cesium Guru,以帮助我找到我需要的东西。我是Cesium的新手,但我一直在使用我继承的教程和一些现有代码。

在我的Cesium应用程序中,我输入我的地址,视图放大到我的街道。好极了!然后我放大了,所以我可以在我的房子周围绘制一个多边形。现有代码非常好。然而当我缩小然后再放大时,我的多边形不能保持我家的Lat-Lon位置

  

Cesium是否包含将像素缩放到lat-lon坐标的实用程序,还是需要使用像   distanceToBoundingSphere(boundingSphere)并自己计算?一世   只想要x,y坐标;我根本不在乎身高。

我一直在寻找演示和教程,到目前为止还没有找到我认为我正在寻找的东西。也许我已经找到了一些接近的东西,但我还不知道我是否已经找到它。救命啊!

============================代码=============== ===================

收集多边形的位置:

singleClick仅捕获该点的坐标,并在用户将鼠标拖动到新点时绘制折线。因此,一堆折线和每个点的坐标集合。

    positionHandler.setInputAction(function (click) {
        cartesian = scene.camera.pickEllipsoid(click.position, ellipsoid);
        if (cartesian) {
            var setCartographic = ellipsoid.cartesianToCartographic(cartesian);
            asset.latlonalt.push(
                Cesium.Math.toDegrees(setCartographic.latitude).toFixed(15),
                Cesium.Math.toDegrees(setCartographic.longitude).toFixed(15),
                Cesium.Math.toDegrees(setCartographic.height).toFixed(15)
            );
            lla.push(Cesium.Math.toDegrees(setCartographic.longitude), Cesium.Math.toDegrees(setCartographic.latitude));
            if (lla.length >= 4) {
                self.loggingMessage((lla.length / 2) + ' Points Added');
            }
            Cesium.sampleTerrain(terrainProvider, 11, [cartographic])
                .then(function (updatedPositions) {
                    asset.latlonalt[2] = updatedPositions[0].height;
                    stage = 1;
                });
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

然后,doubleClick将获取在singleClick函数中捕获的坐标,并调用self.createAsset(' add',asset)来创建多边形。

    positionHandler.setInputAction(function (doubleClick){
        if (asset.shape == 'Polygon') {
            var len = asset.latlonalt.length;
            if(len > 9) {
                asset.rad = (len / 3);
                console.log("Creating Asset");
                self.loggingMessage("Creating Asset");
                socket.emit('newElement', asset.cType, asset);
                self.createAsset('add', asset);
                viewer.entities.remove(entity);
                viewer.entities.remove(newCircle);
                viewer.entities.remove(newPolygon);
                viewer.entities.remove(newOutline);
                positionHandler = positionHandler && positionHandler.destroy();
            }else{
                console.log('3+ Positions Required');
                loggingMessage('3+ Positions Required.');
            }
        }
    }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)

创建多边形:

            var newPolygon = viewer.entities.add({
                name : asset.id,
                polygon : {
                    hierarchy : Cesium.Cartesian3.fromDegreesArray(vertices),
                    material : rgba[0],
                    outline : true,
                    outlineColor : rgba[1]
                }
            });
            var newLabel = viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(asset.latlonalt[1], asset.latlonalt[0], 1000),
                name: asset.id,
                label: {
                    text: asset.name,
                    font : '16px Helvetica'
                }
            });
            var newPoint = viewer.entities.add({
                position: Cesium.Cartesian3.fromDegrees(asset.latlonalt[1], asset.latlonalt[0], 0),
                name: asset.id,
                point : {
                pixelSize : 5,
                    color : Cesium.Color.RED,
                    outlineColor : Cesium.Color.RED,
                    outlineWidth : 2
                }
            });
            self.currentGeometry[asset.id] = {shape: newPolygon, label: newLabel, point: newPoint};

看起来我们正在使用Terrain(我认为)。

Terrain Image

我应该对哪些号码感兴趣:

enter image description here

收集坐标时,只有第一个z不是零:

enter image description here

我取这个值并填充其他z值:

enter image description here

现在我已经添加了z值,在createAsset方法中出现错误。我需要跟踪该问题以查看结果。现在,它看起来像这样:

enter image description here

真的很大,大纲也没有被删除。

1 个答案:

答案 0 :(得分:2)

一个问题还有很多问题,但我会尝试解决这个问题的关键部分。

首先,Cartesian3类本身。在内部,构造之后,此类包含x, y, z成员,其中包含314923.1之类的值。您应该将这些视为黑盒,不透明的值。事实上,它们代表了从行星中心开始的笛卡尔位置,以米为单位,这是渲染引擎所需要的,但通常对人类制图师无用。要理解的关键是z将始终填充实际值,这并不意味着在创建值时会考虑高度。

有一个单独的班级Cartographic,其中包含熟悉的经度(弧度),纬度(弧度)和海拔高度(以米为单位)。通常,这些必须在切换到渲染引擎之前转换为Cartesian3。此转换需要了解Ellipsoid(默认为WGS84椭球),因此,零高度值表示坐在该椭球上的点(通常表示当打开地形时该点位于地下)。

各种辅助函数采用常用值(例如lon / lat in degrees)并转换为这两种格式中的任何一种。其中一些辅助函数不包括高度参数,其他包括它。这两个类的文档列举了这些帮助程序。

当关闭地形时,通过鼠标点击获取精确的lon / lat很简单,但由于使用了透视3D相机,因此在开启时更加复杂。如果没有地形,您可以在上面的第一个代码示例中调用scene.camera.pickEllipsoid,然后获取确切的位置。但是当地形开启时,即使点击平坦的平原也会计算出错误的坐标,在您正在查看的地形的下方和后方找到一个地下点。

随意搜索没有找到正确的代码,但黄金标准似乎是baked into the existing camera controller here。它看起来像这样:

    var depthIntersection;
    if (scene.pickPositionSupported) {
        depthIntersection = scene.pickPosition(mousePosition, scratchDepthIntersection);
    }

    var ray = camera.getPickRay(mousePosition, pickGlobeScratchRay);
    var rayIntersection = globe.pick(ray, scene, scratchRayIntersection);

    var pickDistance = defined(depthIntersection) ?
        Cartesian3.distance(depthIntersection, camera.positionWC) :
        Number.POSITIVE_INFINITY;
    var rayDistance = defined(rayIntersection) ?
        Cartesian3.distance(rayIntersection, camera.positionWC) :
        Number.POSITIVE_INFINITY;

    if (pickDistance < rayDistance) {
        return Cartesian3.clone(depthIntersection, result);
    }

    return Cartesian3.clone(rayIntersection, result);

这段代码试图采用双管齐下的方法:它试图像以前一样选择椭圆体,并尝试从&#34;深度缓冲区中选择#34;这是3D图形系统的一部分允许Cesium在渲染时检查多边形与相机的距离。两个结果进行了比较,并且更接近相机的人被宣布为获胜者。这完全避免了sampleTerrain调用的需要,因为鼠标位置已被用于直接在渲染多边形的空间中拾取笛卡尔点(这可能是地形,但甚至可能是建筑物的顶部等等。)

在下一个代码块中,您使用asset.latlonalt填充lonlat,但是alt已经硬编码为01000而不是来自相同的数据结构。这可能是海拔高度信息丢失的地方,如果它是在那里开始的(如果你只是选择椭圆体本身,它不是,尽管它可能稍后被sampleTerrain添加。请注意,由于从服务器加载地形图块,sampleTerrain是异步的。如果你决定尝试深度采摘技术,那将直接产生Cartesian3,所以你不必担心转换它或保持高度等。

最后一条评论,最近版本的Cesium确实支持允许GroundPrimitivepolygons to drape on terrain。这不会让你免于挑选&#34;挑选&#34;正确的lon / lat(考虑透视地形),但允许多边形放置在块状表面上而不会穿过。