旋转后从地面叠加获取NW LatLng

时间:2018-02-20 22:33:47

标签: android google-maps

我需要从一个绑定地面覆盖的矩形中获取NW LatLng。使用mOverlay.getBounds()将获得旋转前我需要的点(getBounds忽略旋转)。 enter image description here

这是地面覆盖,我需要的确切LatLng是红色的点。当它完全位于北/南(图像左侧)时,我可以使用getBounds()获得该点没问题。在旋转图像之后,我现在需要的是任何点,即朝南/朝南的矩形的NW角,其包含我的旋转地面覆盖(右侧图像的红点)。

1 个答案:

答案 0 :(得分:2)

我不得不假设你正在使用'承载'旋转叠加图像,图像的锚点是中心。此外,由于地图是一个球体建模,当你说矩形时,我们确实假设一个二维平面与图像中心的球体相切(非旋转)。

这种解释简化了旋转角度小于pi / 2弧度并且在顺时针方向的假设。

这些都不是新的,所以没有信用 - 但我尽力适应你的问题。

总之,这种方法将WGS-84坐标系中的原始矩形(非旋转)转换为x / y坐标系(以原点为中心),使用trig计算旋转的新x / y,选择角,导出x超矩形左上角的/ y,将结果转换回WGS-84球面坐标系。

// convert your rotation value (bearing clockwise) to radians

// Using the bounding rectangle (which is of the non-rotated image) compute distance 
// between nw and ne corner (width) and nw and sw corner (height) (in meters).  
// The purpose of this is to establish an x/y coordinate system with origin being 
// the center of the non-rotated image.

// Compute the corner coordinates of original bounding rectangle in an x/y coordinate 
// system using the center as the origin (0,0) e.g. divide NW-NE width by 2 change sign as needed.  Units are meters

// Compute rotated NW corner (x`,y`) (in x/y system) using original NW corner(x/y) 
// and bearing:

//     x` = x * cos(bearingInRadians) + y * sin(bearingInRadians) and y` = -(x * sin(bearingInRadians)) + y * cos(bearingInRadians)

// Compute the y-distance from original NW corner (x/y) to new NW corner (x`,y`) 
// (subtract the y's)

// Compute latitude of super-bounding by using SphericalUtil.computeOffset using 
// original NW lat-lng as 'from', and y-distance (meters) as distance and heading as 0 (north-up).

// Compute the rotated SW corner(x``,y``) (in x/y system) in the same manner 
// as the NW corner above.

// Compute the x-distance from original SW corner (x/y) to new SW corner

// Compute longitude of super-bounding rectangle by using
// SphericalUtil.computeOffset using original NW lat-lng as 'from', and 
// x-distance (meters) as distance and heading as 270.

克服简化意味着选择要使用的角落,并将其映射到纬度和经度。

我希望这样的事情已经实施,但希望这有助于解释所需要的内容。快乐的狩猎。

这是以上的实现:

    GroundOverlayOptions goo = new GroundOverlayOptions();
    BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.rectangle);
    goo.image(bd);
    goo.position(latLng, 1000F);
    GroundOverlay go = mMap.addGroundOverlay(goo);
    LatLngBounds llb = go.getBounds();
    LatLng ne = llb.northeast;
    LatLng sw = llb.southwest;

    PolylineOptions po = new PolylineOptions().add(new LatLng(llb.northeast.latitude,llb.southwest.longitude))
            .add(llb.northeast)
            .add(new LatLng(llb.southwest.latitude,llb.northeast.longitude))
            .add(llb.southwest)
            .add(new LatLng(llb.northeast.latitude,llb.southwest.longitude));
    Polyline polyline = mMap.addPolyline(po);

    MarkerOptions mo = new MarkerOptions();
    mo.position(new LatLng(ne.latitude,sw.longitude));
    mMap.addMarker(mo);
    goo.bearing(25.0F);
    GroundOverlay go2 = mMap.addGroundOverlay(goo);

    double rads = Math.toRadians(25.0);

    float[] result = new float[1];
    Location.distanceBetween(llb.northeast.latitude, llb.southwest.longitude, llb.northeast.latitude, llb.northeast.longitude, result);
    float width = result[0];
    Location.distanceBetween(llb.northeast.latitude, llb.northeast.longitude, llb.southwest.latitude, llb.northeast.longitude, result);
    float height = result[0];

    float upperLeftX = -(width / 2);
    float upperLeftY = (height / 2);

    float lowerLeftX = upperLeftX;
    float lowerLeftY = -upperLeftY;

    double newX = (upperLeftX * cos(rads) + upperLeftY * sin(rads));
    double newY = (-(upperLeftX * sin(rads)) + upperLeftY * cos(rads));

    double deltaY = abs(newY - upperLeftY);
    LatLng newLat = SphericalUtil.computeOffset(llb.northeast, deltaY, 0.0);

    double newX2 = (lowerLeftX * cos(rads) + lowerLeftY * sin(rads));
    double newY2 = (lowerLeftX * Math.sin(rads) + lowerLeftY * cos(rads));

    double deltaX = abs(newX2 - lowerLeftX);
    LatLng newLng = SphericalUtil.computeOffset(llb.southwest, deltaX, 270.0);

    MarkerOptions mo2 = new MarkerOptions();
    mo2.position(new LatLng(newLat.latitude, newLng.longitude));
    mMap.addMarker(mo2);

结果:

enter image description here

注释

  1. 使用线性缩放投影球体表面时会出现错误,但在使用小区域时会明显减少。
  2. 参考文献:

    1. 对于我引用的trig:rotate rectangle
    2. Android内容(1):Spherical Util