谷歌地球插件API-我如何才能得到当前的地图比例

Google Earth Plugin API - How can I get the current map scale?

本文关键字:地图 API- 插件 谷歌地球      更新时间:2023-09-26

我有一个托管Google Earth插件实例的应用程序,我有兴趣获得地图的当前比例并在我的应用程序中使用它。

我知道我可以使用GEOptions并设置缩放图例可见性,但我想在我的应用程序中使用实际缩放值,但我找不到它的API

有办法做到这一点吗?

如果不是,我如何使用当前视图来计算当前比例?

我使用以下函数从Google Earth插件API获得近似比例。这是根据相机离地面的高度计算的。地球仪的倾斜、平移等不会影响返回的值。如果您只需要大致了解相机和地面之间的实际地图比例,这是一个简单的功能,效果很好。即使相机倾斜向地平线,这仍然会像相机直视一样使用计算。

当相机倾斜时,没有可以计算的单一比例,因为比例在可见地图上的任何给定点都会发生变化。距离中的两个点在屏幕上的每像素距离与相机附近两点之间的距离不同。比例图例实际上也是一个近似值,因为距离仅在可见地图的特定部分上是准确的。

function getScale() {
    var camera = ge.getView().copyAsCamera(ge.ALTITUDE_RELATIVE_TO_GROUND),
        eyeAlt,
        scale;
    eyeAlt = camera.getAltitude();
    scale = Math.round(eyeAlt * 10.5);
    return scale;
}

比例尺图例本身非常模糊,因为谷歌地球是一个3D地球仪,透视显然不是一个保持距离(甚至距离之间的比例)的投影。当直接向下看并且相当接近地球表面时,这不是一个问题,但一旦视野倾斜,离相机更近的土地将与地平线上的土地有非常不同的比例。

在这一点上,询问屏幕上某一点的当前刻度更有意义。没有直接的API,但你总是可以找到屏幕上任何两点的lat/lng坐标,然后找到它们之间的距离。

GEView.hitTest可能是最简单的方法。您可以指定命中测试的位置(以像素为单位),也可以指定为插件大小的一小部分(从DOM容器的边缘偏移)。因此,例如,如果你想让km/pixel靠近视图的中间,你可以:取插件的宽度和高度,将它们除以2,然后在每个方向上偏移10个像素,进行hitest查询,找到返回坐标之间的距离,最后除以10。同样,你实际偏移这些像素的方式取决于你想要测量刻度的确切位置(请注意,如果你的命中测试没有击中地球,你会得到一个空的返回值)。

警告:这是一段非常快速的代码(使用该线程的距离计算)。在任何地方使用之前请彻底测试,但它应该看起来像这样:

function getSomethingResemblingScale() {
  var earthDiv = document.getElementById('map3d');
  var hw = earthDiv.offsetWidth / 2;
  var hh = earthDiv.offsetHeight / 2;
  var view = ge.getView();
  var hitTest1 = view.hitTest(hw - 5, ge.UNITS_PIXELS, hh, ge.UNITS_PIXELS, ge.HIT_TEST_TERRAIN);
  var hitTest2 = view.hitTest(hw + 5, ge.UNITS_PIXELS, hh, ge.UNITS_PIXELS, ge.HIT_TEST_TERRAIN);
  var dist = calcDistance(hitTest1.getLatitude(), hitTest1.getLongitude(), hitTest2.getLatitude(), hitTest2.getLongitude());
  console.log('scale: ' + (dist/10) + ' km/pixel');
}
function calcDistance(lat1, lon1, lat2, lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = (lat2-lat1) * (Math.PI / 180);
  var dLon = (lon2-lon1) * (Math.PI / 180);
  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1*(Math.PI / 180)) * Math.cos(lat2*(Math.PI / 180)) * 
          Math.sin(dLon/2) * Math.sin(dLon/2); 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c;
  return d;
}