如果我知道中心和左上方的GPS位置,我如何获得矩形的纬度和经度?

时间:2016-03-01 03:14:28

标签: google-maps math google-maps-api-3 latitude-longitude gmsgroundoverlay

背景:

我正在尝试使用Google地图ground overlay,但我们缺少GPS位置。

我们在Google地图屏幕截图上绘制了一个叠加地图。从这张截图中我们记录了左上角和中心位置。

我们要求右下角位置准确地覆盖这些图像。见下文:

Top Left positions and center positions GPS known

初步思考是找到两点之间的差异并将其添加到中心点。

尝试逻辑:

在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];

问题:

然而,看起来这就是地球的曲线抛出简单数学出门的地方。我猜测下面发生的是为什么。

The image overlay is flat while the GPS system is curved.

所以给定我有一个矩形叠加,我知道左上角和中心点我可以计算出右下角的纬度和经度 I.e X在上图中。注意我不知道这个矩形的真实世界距离。

注意:我也知道我必须将这些更改为NW / SE以使用地面叠加。

5 个答案:

答案 0 :(得分: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);
    
  4. 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>

答案 1 :(得分: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

您可以随时将其削减到您需要的功能。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

我们首先使用计算部分,然后再编程部分。假设是 -

中心点= e

左上角= A

右上角= B

右下角= C

左下角= D

AD = f

的中点

AB = g

的中点

计算部分

location g parameters- lat-A.lat,long-e.long

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

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

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

B点距离A

点C = 2Af来自B

从A

点D = 2Af

编程部分

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点的纬度和长值来得到它。通过这两个长度(Af和Ag),我们可以根据需要获得矩形的四个latlng点。

谢谢

答案 4 :(得分: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()
    ];
};

使用下面的代码生成一个 lat/long 矩形数组。

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] });
            }