gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 16:13:07 25 4
gpt4 key购买 nike

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

在我的 Cesium 应用程序中,我输入我的地址,然后 View 放大到我的街道。耶!然后我拉近一点,这样我就可以在我的房子周围画一个多边形。现有代码在这方面做得很好。然而,当我缩小然后再次放大时,我的多边形并没有保持在我家的 Lat-Lon 位置上

Does Cesium contain a utility to scale pixels to lat-lon coordinates or do I need to use something like distanceToBoundingSphere(boundingSphere) and calculate it myself? I only want the x,y coordinates; I don't care about height at all.

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

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

收集多边形的位置:

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

    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

真的很大而且轮廓没有被移除。

最佳答案

一个问题涉及很多,但我会尝试解决其中的关键部分。

首先,Cartesian3类本身。在内部,构造后,此类包含 x, y, z 成员,其中包含 314923.1 等值。您可能应该将这些视为黑盒、不透明的值。事实上,它们表示笛卡尔坐标位置,以米为单位,距离地球中心,这是渲染引擎所需要的,但通常对人类制图师没有用。要理解的关键是 z 将始终填充一个真实值,这并不意味着在创建值时是否考虑了高度。

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

各种辅助函数采用通用值(例如以度为单位的经/纬度)并转换为这两种格式中的任何一种。这些辅助函数中的一些不包含高度参数,而另一些则包含它。这两个类的文档列举了这些助手。

地形关闭时,通过鼠标点击获得精确的经/纬度很简单,但由于使用透视 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);

这段代码尝试了一种双管齐下的方法:它尝试像以前一样选择椭球体,并且还尝试从“深度缓冲区”中选择,它是 3D 图形系统的一部分,允许 Cesium 检查如何渲染时,远多边形远离相机。将两个结果进行比较,以离相机较近的为准。这完全避免了对 sampleTerrain 调用的需要,因为鼠标位置已用于直接在渲染多边形的空间中选取笛卡尔点(这可能是地形,但甚至可能是顶部建筑物等)。

在你的下一个代码块中,你使用 asset.latlonalt 来填充 lonlat,但是你有 alt 硬编码为 01000 而不是来自相同的数据结构。这可能是高度信息丢失的地方,如果它是从那里开始的(它不是,如果你只是选择椭圆体本身,虽然它可能是由 sampleTerrain 稍后添加的. 注意 sampleTerrain 是异步的,因为地形 block 是从服务器加载的)。如果您决定尝试深度拾取技术,将直接生成 Cartesian3,因此您不必担心转换它或保留高度等问题。

最后一个评论,Cesium 的最新版本确实支持 GroundPrimitive这允许 polygons to drape on terrain .这不会使您免于一开始就“选择”正确的经/纬度(考虑透视地形)的需要,但会允许多边形位于凹凸不平的表面上而不是粘在上面。

关于javascript - Cesium 如何在放大/缩小时缩放多边形以匹配 Lat-Lon 位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35929240/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com