4

背景:

我正在尝试使用谷歌地图地面覆盖,但我们缺少 GPS 位置。

我们有一张要覆盖的地图,它是在谷歌地图屏幕截图上绘制的。从这个屏幕截图中,我们记录了左上角和中心中心位置。

我们需要右下角的位置来准确地叠加这些图像。见下文:

左上位置和中心位置 GPS 已知

最初的想法是找到两点之间的差异并将其添加到中心点。

尝试的逻辑:

在 JavaScript 中:

var topLeft      = [-32.8830055, 151.686214];
var centerCenter = [-32.9293803, 151.756686];

var difference1 = centerCenter[0] - ( (topLeft[0] - centerCenter[0] ) ) ;
var difference2 = centerCenter[1] - ( (topLeft[1] - centerCenter[1] ) ) ;

// being bottom right this should be "bigger" than above values
// outputs [-32.97575509999999, 151.827158];
var bottomRight  = [difference1 , difference2];

问题:

然而,这似乎是地球曲线将简单的数学抛出门外的地方。我猜下面发生的事情就是原因。

图像覆盖是平坦的,而 GPS 系统是弯曲的。

因此,鉴于我有一个矩形叠加层,并且我知道左上点和中心点,我可以计算出上图中右下点即 X 的纬度和经度。注意我不知道这个矩形的真实世界距离。

注意:我也知道我必须将这些更改为 NW / SE 才能使用地面覆盖。

4

5 回答 5

3

方法(使用几何库):

  1. 计算从西北到中心的航向

    google.maps.geometry.spherical.computeHeading(northwest, center);
    
  2. 计算从西北到中心的距离

    google.maps.geometry.spherical.computeDistanceBetween(northwest, center);
    
  3. 通过使用计算东南

    google.maps.geometry.spherical.computeOffset(center,
                                                 calculatedDistance,
                                                 calculatedHeading);
    

function initialize() {

  var nw = new google.maps.LatLng(62.400471, -150.287132),
    center = new google.maps.LatLng(62.341145, -150.14637),
    map = new google.maps.Map(document.getElementById('map_canvas'), {
      zoom: 9,
      center: center
    }),
    heading, distance, se;

  heading = google.maps.geometry.spherical.computeHeading(nw, center);
  distance = google.maps.geometry.spherical.computeDistanceBetween(nw, center);
  se = google.maps.geometry.spherical.computeOffset(center, distance, heading);

  new google.maps.Marker({
    map: map,
    position: center
  });
  new google.maps.Marker({
    map: map,
    position: nw
  });
  new google.maps.Marker({
    map: map,
    position: se
  });

  new google.maps.GroundOverlay(
    'https://developers.google.com/maps/documentation/' +
    'javascript/examples/full/images/talkeetna.png', {
      north: nw.lat(),
      south: se.lat(),
      west: nw.lng(),
      east: se.lng()
    }, {
      map: map
    });


}

google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map_canvas {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map_canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=geometry"></script>

于 2016-03-01T10:12:57.280 回答
2

您是否不愿意使用已经支持 Haversine 计算中心点的库?(通过测试启动)

查看 Geolib:https ://github.com/manuelbieh/Geolib

var center = geolib.getCenter([
    {latitude: 52.516272, longitude: 13.377722},
    {latitude: 51.515, longitude: 7.453619},
    {latitude: 51.503333, longitude: -0.119722}
]);

console.log(center);

// Output:
//
// {
//     "latitude": "52.009802",
//     "longitude": "6.629000",
//     "distance": 932.209
// }

您可以使用的 codepen 演示:http ://codepen.io/anon/pen/grbGrz/?editors=1010

您可以随时将其缩减为您需要的功能。

于 2016-03-01T05:31:47.430 回答
1

您可能需要使用Haversine公式进行此类计算。所涉及的数学显然比 SO 答案的典型水平更高,因此您的问题实际上可能属于 gis 或数学堆栈交换,其中一些更有经验的 SO 用户可能能够为您提供更详细的答案/示例。

于 2016-03-01T03:26:03.067 回答
1

以免从查询的开头开始。你有两个 latlng,现在你想得到矩形的 latlng。

我们将先进行计算部分,然后再进行编程部分。假设是-

中心点 = e

左上角 = A

右上角 = B

右下角 = C

左下 = D

AD的中点=f

AB的中点=g

计算部分

位置 g 参数 - lat-A.lat, long-e.long

位置 f 参数 - lat-e.lat, long-A.long

A 到 g 的距离 = A.distanceTo(g)

A 到 f 的距离 = A.distanceTo(f)

点 B = 2Ag 从 A

点 C = 2Af 从 B

点 D = 2Af 从 A

编程部分

LatLng A = null, B = null, C = null, D = null, e = null, f = null, g = null,temp=null;

e.latitude = your center latitude value;
e.longitude = your center longitude value;

A.latitude=your top left point latitude value;
A.longitude=your top left point longitude value;

f.latitude = e.latitude;
f.longitude = A.longitude;

g.latitude = A.latitude;
g.longitude = e.longitude;

double[] Ag = new double[1];
double[] Af = new double[1];

Location.distanceBetween(A.latitude, A.longitude, g.latitude, g.longitude, Ag);
Location.distanceBetween(A.latitude, A.longitude, f.latitude, f.longitude, Af);

temp=getDestinationPoint(A,90,(2*Ag));
B.latitude=temp.latitude;
B.longitude=temp.longitude;

temp=getDestinationPoint(B,180,(2*Af));
C.latitude=temp.latitude;
C.longitude=temp.longitude;

temp=getDestinationPoint(A,180,(2*Af));
D.latitude=temp.latitude;
D.longitude=temp.longitude;

private LatLng getDestinationPoint (LatLng source,double brng, double dist){
            dist = dist / 6371;
            brng = Math.toRadians(brng);

            double lat1 = Math.toRadians(source.latitude), lon1 = Math.toRadians(source.longitude);
            double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
                    Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
            double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
                            Math.cos(lat1),
                    Math.cos(dist) - Math.sin(lat1) *
                            Math.sin(lat2));
            if (Double.isNaN(lat2) || Double.isNaN(lon2)) {
                return null;
            }
            return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
        }

解释

f和g分别是线AD和AB的中点。我们可以通过改变 A 和 e 点的 lat 和 long 值来得到它。通过这两个长度(Af 和 A​​g),我们可以根据需要获得矩形的四个纬度点。

谢谢你

于 2016-03-01T09:15:25.077 回答
0

使用下面的 javascript 函数获取基于中心和距离的矩形的经纬度列表。latLngArr 是矩形点的列表。

Number.prototype.degreeToRadius = function () {
    return this * (Math.PI / 180);
};

Number.prototype.radiusToDegree = function () {
    return (180 * this) / Math.PI;
};

function getBoundingBox(fsLatitude, fsLongitude, fiDistanceInKM) {

    if (fiDistanceInKM == null || fiDistanceInKM == undefined || fiDistanceInKM == 0)
        fiDistanceInKM = 1;
    
    var MIN_LAT, MAX_LAT, MIN_LON, MAX_LON, ldEarthRadius, ldDistanceInRadius, lsLatitudeInDegree, lsLongitudeInDegree,
        lsLatitudeInRadius, lsLongitudeInRadius, lsMinLatitude, lsMaxLatitude, lsMinLongitude, lsMaxLongitude, deltaLon;
    
    // coordinate limits
    MIN_LAT = (-90).degreeToRadius();
    MAX_LAT = (90).degreeToRadius();
    MIN_LON = (-180).degreeToRadius();
    MAX_LON = (180).degreeToRadius();

    // Earth's radius (km)
    ldEarthRadius = 6378.1;

    // angular distance in radians on a great circle
    ldDistanceInRadius = fiDistanceInKM / ldEarthRadius;

    // center point coordinates (deg)
    lsLatitudeInDegree = fsLatitude;
    lsLongitudeInDegree = fsLongitude;

    // center point coordinates (rad)
    lsLatitudeInRadius = lsLatitudeInDegree.degreeToRadius();
    lsLongitudeInRadius = lsLongitudeInDegree.degreeToRadius();

    // minimum and maximum latitudes for given distance
    lsMinLatitude = lsLatitudeInRadius - ldDistanceInRadius;
    lsMaxLatitude = lsLatitudeInRadius + ldDistanceInRadius;

    // minimum and maximum longitudes for given distance
    lsMinLongitude = void 0;
    lsMaxLongitude = void 0;

    // define deltaLon to help determine min and max longitudes
    deltaLon = Math.asin(Math.sin(ldDistanceInRadius) / Math.cos(lsLatitudeInRadius));

    if (lsMinLatitude > MIN_LAT && lsMaxLatitude < MAX_LAT) {
        lsMinLongitude = lsLongitudeInRadius - deltaLon;
        lsMaxLongitude = lsLongitudeInRadius + deltaLon;
        if (lsMinLongitude < MIN_LON) {
            lsMinLongitude = lsMinLongitude + 2 * Math.PI;
        }
        if (lsMaxLongitude > MAX_LON) {
            lsMaxLongitude = lsMaxLongitude - 2 * Math.PI;
        }
    }

    // a pole is within the given distance
    else {
        lsMinLatitude = Math.max(lsMinLatitude, MIN_LAT);
        lsMaxLatitude = Math.min(lsMaxLatitude, MAX_LAT);
        lsMinLongitude = MIN_LON;
        lsMaxLongitude = MAX_LON;
    }

    return [
        lsMinLatitude.radiusToDegree(),
        lsMinLongitude.radiusToDegree(),
        lsMaxLatitude.radiusToDegree(),
        lsMaxLongitude.radiusToDegree()
    ];
};

使用下面的代码生成一个纬度/经度的矩形数组。

var lsRectangleLatLong = getBoundingBox(parseFloat(latitude), parseFloat(longitude), lsDistance);
            if (lsRectangleLatLong != null && lsRectangleLatLong != undefined) {
                latLngArr.push({ lat: lsRectangleLatLong[0], lng: lsRectangleLatLong[1] });
                latLngArr.push({ lat: lsRectangleLatLong[0], lng: lsRectangleLatLong[3] });
                latLngArr.push({ lat: lsRectangleLatLong[2], lng: lsRectangleLatLong[3] });
                latLngArr.push({ lat: lsRectangleLatLong[2], lng: lsRectangleLatLong[1] });
            }
于 2021-03-26T12:24:31.763 回答