2

我在计算提供的第二点的纬度/经度以及计算第一点和距离的纬度/经度时仍然存在问题。

我在 Javascript 中找到了一种解决方案,我尝试转换为 Java。但结果不准确,看来我做错了什么。

如何计算距离另一点一定距离的点的纬度?

public class Misc {





        double EARTH_RADIUS_METERS= 6378.1 *1024;

        private double toRad(double value) {
           return  value*  (Math.PI/ 180);
        }

        private double toDeg (double value) {
           return value*  (180 / Math.PI);
        }


        /*-------------------------------------------------------------------------
         * Given a starting lat/lon point on earth, distance (in meters)
         * and bearing, calculates destination coordinates lat2/lon2.
         *
         * all params in radians
         *-------------------------------------------------------------------------*/
         GPoint destCoordsInRadians(double lat1, double lon1, 
                                 double distanceMeters, double bearing
                                 /*,double* lat2, double* lon2*/)
        {
            //-------------------------------------------------------------------------
            // Algorithm from http://www.geomidpoint.com/destination/calculation.html
            // Algorithm also at http://www.movable-type.co.uk/scripts/latlong.html
            //
            // Spherical Earth Model
            //   1. Let radiusEarth = 6372.7976 km or radiusEarth=3959.8728 miles
            //   2. Convert distance to the distance in radians.
            //      dist = dist/radiusEarth
            //   3. Calculate the destination coordinates.
            //      lat2 = asin(sin(lat1)*cos(dist) + cos(lat1)*sin(dist)*cos(brg))
            //      lon2 = lon1 + atan2(sin(brg)*sin(dist)*cos(lat1), cos(dist)-sin(lat1)*sin(lat2))
            //-------------------------------------------------------------------------
            double distRadians = distanceMeters / EARTH_RADIUS_METERS;

            double lat2 = Math.asin( Math.sin(lat1) * Math.cos(distRadians) + Math.cos(lat1) * Math.sin(distRadians) * Math.cos(bearing));

            double  lon2 = lon1 + Math.atan2( Math.sin(bearing) * Math.sin(distRadians) * Math.cos(lat1), 
                    Math.cos(distRadians) - Math.sin(lat1) * Math.sin(lat2) );  

            return new  GPoint( lat2  , lon2 );

        }

        /*-------------------------------------------------------------------------
         * Given a starting lat/lon point on earth, distance (in meters)
         * and bearing, calculates destination coordinates lat2/lon2.
         *
         * all params in degrees
         *-------------------------------------------------------------------------*/
         GPoint destCoordsInDegrees(double lat1, double lon1, 
                                 double distanceMeters, double bearing/*,
                                 double* lat2, double* lon2*/)
        {
            GPoint gPoint2=destCoordsInRadians(/*Deg_to_*/toRad(lat1), /*Deg_to_*/toRad(lon1),
                                distanceMeters, /*Deg_to_*/toRad(bearing)/*,
                                lat2, lon2*/);

            gPoint2.lat = /*Rad_to_*/toDeg( gPoint2.lat );
            gPoint2.lon = normalize180( /*Rad_to_*/toDeg( gPoint2.lon )) ;

            return gPoint2;
        }


        /*-------------------------------------------------------------------------
         * Given two lat/lon points on earth, calculates the heading
         * from lat1/lon1 to lat2/lon2.  
         * 
         * lat/lon params in radians
         * result in radians
         *-------------------------------------------------------------------------*/
        double headingInRadians(double lat1, double lon1, double lat2, double lon2)
        {
            //-------------------------------------------------------------------------
            // Algorithm found at http://www.movable-type.co.uk/scripts/latlong.html
            //
            // Spherical Law of Cosines
            //
            // Formula: ? = atan2(  sin(?lon) * cos(lat2),
            //                      cos(lat1) * sin(lat2) ? sin(lat1) * cos(lat2) * cos(?lon) )
            // JavaScript:  
            //  
            //  var y = Math.sin(dLon) * Math.cos(lat2);
            //  var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
            //  var brng = Math.atan2(y, x).toDeg();
            //-------------------------------------------------------------------------
            double dLon = lon2 - lon1;
            double y = Math.sin(dLon) * Math.cos(lat2);
            double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);

            return Math.atan2(y, x);
        }

        /*-------------------------------------------------------------------------
         * Given two lat/lon points on earth, calculates the heading
         * from lat1/lon1 to lat2/lon2.  
         * 
         * lat/lon params in degrees
         * result in degrees
         *-------------------------------------------------------------------------*/
        double headingInDegrees(double lat1, double lon1, double lat2, double lon2)
        {
            return /*Rad_to_*/toDeg( headingInRadians(/*Deg_to_*/toRad(lat1), 
                    /*Deg_to_*/toRad(lon1), 
                    /*Deg_to_*/toRad(lat2),
                    /*Deg_to_*/toRad(lon2)) );
        }

        // Normalize a heading in degrees to be within -179.999999° to 180.00000°
        double normalize180(double heading)
        {
            while (true) {
                if (heading <= -180) {
                    heading += 360;
                } else if (heading > 180) {
                    heading -= 360;
                } else {
                    return heading;
                }
            }
        }

        // Normalize a heading in degrees to be within -179.999999° to 180.00000°
        float normalize180f(float heading)
        {
            while (true) {
                if (heading <= -180) {
                    heading += 360;
                } else if (heading > 180) {
                    heading -= 360;
                } else {
                    return heading;
                }
            }
        }

        // Normalize a heading in degrees to be within 0° to 359.999999°
        double normalize360(double heading)
        {
            while (true) {
                if (heading < 0) {
                    heading += 360;
                } else if (heading >= 360) {
                    heading -= 360;
                } else {
                    return heading;
                }
            }
        }

        // Normalize a heading in degrees to be within 0° to 359.999999°
        float normalize360f(float heading)
        {
            while (true) {
                if (heading < 0) {
                    heading += 360;
                } else if (heading >= 360) {
                    heading -= 360;
                } else {
                    return heading;
                }
            }
        }

}
4

2 回答 2

5

您还需要一个参数,即“轴承”。然后:

var d = radius/6378800; // 6378800 is Earth radius in meters
var lat1 = (PI/180)* centerLat;
var lng1 = (PI/180)* centerLng;

// Go around a circle from 0 to 360 degrees, every 10 degrees or set a to your desired bearing, in degrees.
for (var a = 0 ; a < 361 ; a+=10 ) {
    var tc = (PI/180)*a;
    var y = asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc));
    var dlng = atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(y));
    var x = ((lng1-dlng+PI) % (2*PI)) - PI ;
    var lat = y*(180/PI);
    var lon = x*(180/PI);

    // Convert the lat and lon to pixel, if needed. (x,y) 
}

最初来自另一个 SO 线程: 如何将 1 米更改为像素距离?

于 2012-07-18T12:07:34.880 回答
1

是这个问题的好答案:

你可以使用android-maps-utils的方法:

SphericalUtil.computeOffset(latLng, dist, brng)

如果你想自己做:

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));
    }
于 2017-04-13T08:58:00.377 回答