GeoMapping轴承和坐标计算的谷歌地图标记 [英] GeoMapping Bearing and Coordinate Calculation for GoogleMaps markers

查看:140
本文介绍了GeoMapping轴承和坐标计算的谷歌地图标记的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个Android应用程序和整合GoogleMapsV2 API。我有地图在绕锚点的各个位置上的一系列标记。

I'm writing an Android app and integrating GoogleMapsV2 API. I have a series of markers on the map at various locations around an anchor.

我想这些标记对锚的地位逐步收敛。

I want those markers to converge on the anchor's position incrementally.

我有一个循环的运行,将调用每个标记B和从B的位置计算轴承锚A.那么我计算目标坐标沿着轴承和更新一个固定的距离。

I've got a loop running that will call each marker B and from B's position calculate the bearing to the anchor A. I then calculate the destination coordinate for a fixed distance along that bearing and update.

下面是两个功能我使用(从堆栈岗位的合并和GeoMapping站点,充分披露采取了):

Here are the two functions (taken from an amalgamation of stack posts and a GeoMapping site, for full disclosure) I'm using:

public double calcBearing(double lat1, double lon1, double lat2, double lon2){
    double longitude1 = lon1;
    double longitude2 = lon2;
    double latitude1 = Math.toRadians(lat1);
    double latitude2 = Math.toRadians(lat2);
    double longDiff= Math.toRadians(longitude2-longitude1);
    double y= Math.sin(longDiff)*Math.cos(latitude2);
    double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);

    double calcBearing =  (Math.toDegrees(Math.atan2(y, x))+360)%360;
    return calcBearing;
}

public Coordinate calcCoordFromPointBearing(double lat1, double lon1, double bearing, double distance){
    double rEarth = 6371.01; // Earth's average radius in km
    double epsilon = 0.000001; // threshold for floating-point equality

    double rLat1 = deg2rad(lat1);
    double rLon1 = deg2rad(lon1);
    double rbearing = deg2rad(bearing);
    double rdistance = distance / rEarth;

    double rlat = Math.asin( Math.sin(rLat1) * Math.cos(rdistance) + Math.cos(rLat1) * Math.sin(rdistance) * Math.cos(rbearing) );
    double rlon;
    if (Math.cos(rlat) == 0 || Math.abs(Math.cos(rlat)) < epsilon) // Endpoint a pole
            rlon=rLon1;
    else
        rlon = ( (rLon1 - Math.asin( Math.sin(rbearing)* Math.sin(rdistance) / Math.cos(rlat) ) + Math.PI ) % (2*Math.PI) ) - Math.PI;

    double lat = rad2deg(rlat);
    double lon = rad2deg(rlon);
    return new Coordinate(lat,lon);
}

private double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

private double rad2deg(double rad) {
    return (rad * 180.0 / Math.PI);
}

总之,我搞砸了上述计算,我相信。我看到的行为是标记移动不稳定和高频结束了走向两个轴承:90和270。其结果是,他们往往从我的锚,而不是向它搬开

In short, I've screwed up the above calculations I believe. The behavior I'm seeing is the markers moving erratically and with a high frequency ending up heading towards two bearings: 90 and 270. As a result, they tend to move away from my anchor instead of towards it.

有人可以帮助我看出错误?我传递度都承载功能和坐标计算功能,但我立即将它们转换为弧度的算法和回度的使用在其他地方。

Can someone help me spot the mistake? I am passing in degrees to both the bearing function and the coordinate calculation function, but I'm converting them immediately to radians for the algorithm and back to degrees for usage elsewhere.

[更新:

在大多数情况下code来自这个例子:
<一href="http://stackoverflow.com/questions/877524/calculating-coordinates-given-a-bearing-and-a-distance">Calculating坐标给出一个轴承和一个距离

Most of the code came from this example:
Calculating coordinates given a bearing and a distance

在我看来,输出经度被标准化为-180到180,而我策划一个360度的空间,导致输出头所需的TRIG数学变化的轴承90和270有什么建议解决这一问题?]

It looks to me that the output longitude is being normalized to -180 to 180, which I'm plotting on a 360 degree space causing the outputs to head to the bearings 90 and 270. Any suggestions on the trig math change required to fix this?]

推荐答案

大约需要360.0

 double calcBearing =  (Math.toDegrees(Math.atan2(y, x))+360.0)%360.0;

这是kindof回答<一href="http://stackoverflow.com/questions/10119479/calculating-lat-and-long-from-bearing-and-distance">here

,你还有另外一个问题。你不考虑在地图上的任何倾斜。的为什么不直接用像素动画。不会有曲率太多失真。你有什么做的就是标记的像素位置。你必须添加标记时保存latlon或者你必须用 .setAnchor 添加标记,让你以像素为单位的偏移。如果你有标记放置的latlon那么你得到的点按。

You still have another issue. Your not considering any tilt in the map. Why not just animate with the pixels. There won't be too much distortion of curvature. What you have to do is get the pixel position of the marker. You'll have to save the latlon when adding the marker or you have to add the markers with .setAnchor which gives you an offset in pixels. If you have the latlon of the marker placement then you get the point by.

LatLon ll;
Point p = mMap.getProjection().toScreenLocation(ll);

这时你可以用code这样的动画标记。我通过插值y轴下方做一个标记反弹。你必须插两个AXI。

Then you can use code like this to animate the markers. I'm making a marker bounce below by interpolating the y axis. You'll have to interpolate both axi.

    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final long duration = 2500;

    final Interpolator interpolator = new BounceInterpolator();

    handler.post(new Runnable() {
        @Override
        public void run() {
            long elapsed = SystemClock.uptimeMillis() - start;
            float t = Math.max(
                    1 - interpolator.getInterpolation((float) elapsed
                            / duration), 0);

            marker.setAnchor(0.5f, 1.0f + 6 * t);

            if (t > 0.0) {
                // Post again 16ms later.
                handler.postDelayed(this, 16);
            }
        }
    });

以上code是这个<一个href="http://stackoverflow.com/questions/19723017/android-google-map-move-camera-from-position-to-another/19730872#19730872">question.我对你有当您使用上述方法的任何性能问题深表歉意。但是,你仍然可以使用的像素位置为更传统动画的方式。

The above code is from this question. I apologize for any performance issues you have when you use the above method. But you could still use the pixel positions for a more traditional animation approach.

我已经得到了几乎相同的公式,你在我动画的地图移动到基于位置方位和速度的预期位置另一个程序的工作。其计算公式为末比你稍有不同。我从<一提起它href="http://stackoverflow.com/questions/10119479/calculating-lat-and-long-from-bearing-and-distance">here并改为更长的名字。

I've got almost the same formulas as you working in another program where I animate a map to move to the expected location based on a location bearing and speed. The formula is slightly different at the end than yours. I lifted it from here and changed to longer names.

    // Define the callback method that receives location updates
@Override
public void onLocationChanged(Location location) {

    // Given the bearing, speed, and current location
    // calculate what the expected location is traveling for an
    // interval that is slightly larger than two times fastest interval of
    // the location provider and animate the map movement to the
    // expected location over the same slightly larger interval.

    // In Theory by using an interval that is slightly larger
    // than two times fastest interval of the location provider for the
    // animation length a new animation will start before the
    // currently running animation finishes. This should ensure a
    // smooth animation of the map while traveling under most
    // circumstances.

    // Negative acceleration (braking)
    // should have acceptable map animation because the map
    // animation in theory never finishes.

    // Note longer intervals, large negative accelerations, just
    // braking at the start of an interval may result in the map moving
    // backwards. But it will still be animated.

    // Some handhelds might not be able to keep up

    // TODO CHECK THE age of the location

    // location.getSpeed() =meters/second
    // interval 1/1000 seconds
    // distance in radians km/6371

    // changed.
    // (location.getSpeed()m/s)(1/1000 interval seconds)( 1/1000 km/m)
    // (1/6371 radians/km) = radians/6371000000.0
    double expectedDistance = location.getSpeed() * expectedDistMultiplier;
    // latitude in Radians
    double currentLatitude = Math.toRadians(location.getLatitude());
    // longitude in Radians
    double longitude1 = Math.toRadians(location.getLongitude());
    double bearing;
    bearing = (location.hasBearing()) ? Math.toRadians(location
            .getBearing()) : 0;

    // calculate the expected latitude and longitude based on staring
    // location
    // , bearing, and distance

    double expectedLatitude = Math.asin(Math.sin(currentLatitude)
            * Math.cos(expectedDistance) + Math.cos(currentLatitude)
            * Math.sin(expectedDistance) * Math.cos(bearing));
    double a = Math.atan2(
            Math.sin(bearing) * Math.sin(expectedDistance)
                    * Math.cos(currentLatitude),
            Math.cos(expectedDistance) - Math.sin(currentLatitude)
                    * Math.sin(expectedLatitude));
    double expectedLongitude = longitude1 + a;
    expectedLongitude = (expectedLongitude + 3 * Math.PI) % (2 * Math.PI)
            - Math.PI;

    // convert to degrees for the expected destination
    double expectedLongitudeDestination = Math.toDegrees(expectedLongitude);
    double expectedLatitudeDestination = Math.toDegrees(expectedLatitude);

    // log everything for testing.
    Log.d("Location", "Bearing in radians" + bearing);
    Log.d("Location", "distance in km" + expectedDistance);
    Log.d("Location", "Current Latitude = " + location.getLatitude()
            + " Current Longitude = " + location.getLongitude());
    Log.d("Location", "New Latitude = " + expectedLatitudeDestination
            + " New Longitude = " + expectedLongitudeDestination);

    // build a camera update to animate positioning map to the expected
    // destination
    LatLng ll = new LatLng(expectedLatitudeDestination,
            expectedLongitudeDestination);
    CameraPosition.Builder cb = CameraPosition.builder()
            .zoom(mMap.getCameraPosition().zoom)
            .bearing(mMap.getCameraPosition().bearing)
            .tilt(mMap.getCameraPosition().tilt).target(ll);
    if (location.hasBearing()) {
        cb.bearing(location.getBearing());
    }
    CameraPosition camera = cb.build();
    CameraUpdate update = CameraUpdateFactory.newCameraPosition(camera);
    mMap.animateCamera(update, interval, this);
}

这篇关于GeoMapping轴承和坐标计算的谷歌地图标记的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆