计算谷歌地图V3中两点之间的距离
如何计算Google maps V3中两个标记之间的距离? (类似于V2中的distanceFrom
函数。)
谢谢..
如果你想自己计算,那么你可以使用Haversine公式:
var rad = function(x) { return x * Math.PI / 180; }; var getDistance = function(p1, p2) { var R = 6378137; // Earth's mean radius in meter var dLat = rad(p2.lat() - p1.lat()); var dLong = rad(p2.lng() - p1.lng()); var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong / 2) * Math.sin(dLong / 2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; return d; // returns the distance in meter };
实际上似乎在GMap3中有一种方法。 这是google.maps.geometry.spherical
命名空间的静态方法。
它采用两个LatLng
对象作为参数,并将使用6378137米的默认地球半径,但如果需要,默认半径可以用自定义值覆盖。
确保你包括:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry"></script>
在你的头部。
电话会是:
google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);
在新的V3几何graphics库中有computeDistanceBetween(lat,lng)
使用GPS纬度/经度2点的示例。
var latitude1 = 39.46; var longitude1 = -0.36; var latitude2 = 40.40; var longitude2 = -3.68; var distance = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(latitude1, longitude1), new google.maps.LatLng(latitude2, longitude2));
只需将其添加到JavaScript代码的开头即可:
google.maps.LatLng.prototype.distanceFrom = function(latlng) { var lat = [this.lat(), latlng.lat()] var lng = [this.lng(), latlng.lng()] var R = 6378137; var dLat = (lat[1]-lat[0]) * Math.PI / 180; var dLng = (lng[1]-lng[0]) * Math.PI / 180; var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat[0] * Math.PI / 180 ) * Math.cos(lat[1] * Math.PI / 180 ) * Math.sin(dLng/2) * Math.sin(dLng/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d = R * c; return Math.round(d); }
然后使用这样的function:
var loc1 = new GLatLng(52.5773139, 1.3712427); var loc2 = new GLatLng(52.4788314, 1.7577444); var dist = loc2.distanceFrom(loc1); alert(dist/1000);
这是这个论坛的C#实现
public class DistanceAlgorithm { const double PIx = 3.141592653589793; const double RADIO = 6378.16; /// <summary> /// This class cannot be instantiated. /// </summary> private DistanceAlgorithm() { } /// <summary> /// Convert degrees to Radians /// </summary> /// <param name="x">Degrees</param> /// <returns>The equivalent in radians</returns> public static double Radians(double x) { return x * PIx / 180; } /// <summary> /// Calculate the distance between two places. /// </summary> /// <param name="lon1"></param> /// <param name="lat1"></param> /// <param name="lon2"></param> /// <param name="lat2"></param> /// <returns></returns> public static double DistanceBetweenPlaces( double lon1, double lat1, double lon2, double lat2) { double dlon = Radians(lon2 - lon1); double dlat = Radians(lat2 - lat1); double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2)); double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a)); return (angle * RADIO) * 0.62137;//distance in miles } }
与谷歌,你可以使用球形的API , google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);
。
但是,如果球形投影或半正弦波解的精度对于您来说不够精确(例如,如果您靠近杆或计算较长的距离),则应该使用不同的库。
关于这个主题的大部分信息我在维基百科发现。
看看任何给定的algorithm的精度是否足够的一个技巧是填写地球的最大和最小半径,看看差异是否可能会导致您的使用情况的问题。 更多的细节可以在这篇文章中find
最后,google api或者haversine将在没有任何问题的情况下用于大多数目的。
// p1和p2是google.maps.LatLng(x,y)对象
function calcDistance(p1, p2) { var d = (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2); console.log(d); }
用Javascript实现的Vincentyalgorithm可以提高处理时间,从而获得较高的精度。
使用PHP,你可以使用这个简单的函数来计算距离:
//计算两个纬度和经度之间的距离 函数calculate_distance($ lat1,$ lon1,$ lat2,$ lon2,$ unit ='N') { $ theta = $ lon1 - $ lon2; (dist2rad($ lat1))* sin(deg2rad($ lat2))+ cos(deg2rad($ lat1))* cos(deg2rad($ lat2))* cos(deg2rad($ theta)); $ dist = acos($ dist); $ dist = rad2deg($ dist); $ miles = $ dist * 60 * 1.1515; $ unit = strtoupper($ unit); if($ unit ==“K”){ 回报($ miles * 1.609344); } else if($ unit ==“N”){ 回报($ miles * 0.8684); } else { 返回$英里; } } //function在这里结束
脱机解决scheme – Haversinealgorithm
在Javascript中
var _eQuatorialEarthRadius = 6378.1370; var _d2r = (Math.PI / 180.0); function HaversineInM(lat1, long1, lat2, long2) { return (1000.0 * HaversineInKM(lat1, long1, lat2, long2)); } function HaversineInKM(lat1, long1, lat2, long2) { var dlong = (long2 - long1) * _d2r; var dlat = (lat2 - lat1) * _d2r; var a = Math.pow(Math.sin(dlat / 2.0), 2.0) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r) * Math.pow(Math.sin(dlong / 2.0), 2.0); var c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0 - a)); var d = _eQuatorialEarthRadius * c; return d; } var meLat = -33.922982; var meLong = 151.083853; var result1 = HaversineInKM(meLat, meLong, -32.236457779983745, 148.69094705162837); var result2 = HaversineInKM(meLat, meLong, -33.609020205923713, 150.77061469270831);
C#
using System; public class Program { public static void Main() { Console.WriteLine("Hello World"); var meLat = -33.922982; double meLong = 151.083853; var result1 = HaversineInM(meLat, meLong, -32.236457779983745, 148.69094705162837); var result2 = HaversineInM(meLat, meLong, -33.609020205923713, 150.77061469270831); Console.WriteLine(result1); Console.WriteLine(result2); } static double _eQuatorialEarthRadius = 6378.1370D; static double _d2r = (Math.PI / 180D); private static int HaversineInM(double lat1, double long1, double lat2, double long2) { return (int)(1000D * HaversineInKM(lat1, long1, lat2, long2)); } private static double HaversineInKM(double lat1, double long1, double lat2, double long2) { double dlong = (long2 - long1) * _d2r; double dlat = (lat2 - lat1) * _d2r; double a = Math.Pow(Math.Sin(dlat / 2D), 2D) + Math.Cos(lat1 * _d2r) * Math.Cos(lat2 * _d2r) * Math.Pow(Math.Sin(dlong / 2D), 2D); double c = 2D * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1D - a)); double d = _eQuatorialEarthRadius * c; return d; } }
参考: https : //en.wikipedia.org/wiki/Great-circle_distance
必须这样做…动作脚本的方式
//just make sure you pass a number to the function because it would accept you mother in law... public var rad = function(x:*) {return x*Math.PI/180;} protected function distHaversine(p1:Object, p2:Object):Number { var R:int = 6371; // earth's mean radius in km var dLat:Number = rad(p2.lat() - p1.lat()); var dLong:Number = rad(p2.lng() - p1.lng()); var a:Number = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2); var c:Number = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); var d:Number = R * c; return d; }
在我的情况下,最好在SQL Server中计算这个值,因为我想取当前位置,然后在距当前位置一定距离内search所有的邮政编码。 我也有一个DB包含一个邮政编码列表和它们的长度。 干杯
--will return the radius for a given number create function getRad(@variable float)--function to return rad returns float as begin declare @retval float select @retval=(@variable * PI()/180) --print @retval return @retval end go --calc distance --drop function dbo.getDistance create function getDistance(@cLat float,@cLong float, @tLat float, @tLong float) returns float as begin declare @emr float declare @dLat float declare @dLong float declare @a float declare @distance float declare @c float set @emr = 6371--earth mean set @dLat = dbo.getRad(@tLat - @cLat); set @dLong = dbo.getRad(@tLong - @cLong); set @a = sin(@dLat/2)*sin(@dLat/2)+cos(dbo.getRad(@cLat))*cos(dbo.getRad(@tLat))*sin(@dLong/2)*sin(@dLong/2); set @c = 2*atn2(sqrt(@a),sqrt(1-@a)) set @distance = @emr*@c; set @distance = @distance * 0.621371 -- i needed it in miles --print @distance return @distance; end go --get all zipcodes within 2 miles, the hardcoded #'s would be passed in by C# select * from cityzips a where dbo.getDistance(29.76,-95.38,a.lat,a.long) <3 order by zipcode
//JAVA public Double getDistanceBetweenTwoPoints(Double latitude1, Double longitude1, Double latitude2, Double longitude2) { final int RADIUS_EARTH = 6371; double dLat = getRad(latitude2 - latitude1); double dLong = getRad(longitude2 - longitude1); double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(getRad(latitude1)) * Math.cos(getRad(latitude2)) * Math.sin(dLong / 2) * Math.sin(dLong / 2); double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return (RADIUS_EARTH * c) * 1000; } private Double getRad(Double x) { return x * Math.PI / 180; }
查看GLatLng对象上的distanceFrom函数; v2和v3之间的函数参数略有变化。
要计算Google地图上的距离,您可以使用路线API。 这将是最简单的方法之一。 要从Google Server获取数据,您可以使用Retrofit或Volley。 两者都有自己的优势。 看看下面的代码,我已经使用retrofit来实现它:
private void build_retrofit_and_get_response(String type) { String url = "https://maps.googleapis.com/maps/"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); RetrofitMaps service = retrofit.create(RetrofitMaps.class); Call<Example> call = service.getDistanceDuration("metric", origin.latitude + "," + origin.longitude,dest.latitude + "," + dest.longitude, type); call.enqueue(new Callback<Example>() { @Override public void onResponse(Response<Example> response, Retrofit retrofit) { try { //Remove previous line from map if (line != null) { line.remove(); } // This loop will go through all the results and add marker on each location. for (int i = 0; i < response.body().getRoutes().size(); i++) { String distance = response.body().getRoutes().get(i).getLegs().get(i).getDistance().getText(); String time = response.body().getRoutes().get(i).getLegs().get(i).getDuration().getText(); ShowDistanceDuration.setText("Distance:" + distance + ", Duration:" + time); String encodedString = response.body().getRoutes().get(0).getOverviewPolyline().getPoints(); List<LatLng> list = decodePoly(encodedString); line = mMap.addPolyline(new PolylineOptions() .addAll(list) .width(20) .color(Color.RED) .geodesic(true) ); } } catch (Exception e) { Log.d("onResponse", "There is an error"); e.printStackTrace(); } } @Override public void onFailure(Throwable t) { Log.d("onFailure", t.toString()); } }); }
以上是用于计算距离的函数build_retrofit_and_get_response的代码。 下面是相应的改造界面:
package com.androidtutorialpoint.googlemapsdistancecalculator; import com.androidtutorialpoint.googlemapsdistancecalculator.POJO.Example; import retrofit.Call; import retrofit.http.GET; import retrofit.http.Query; public interface RetrofitMaps { /* * Retrofit get annotation with our URL * And our method that will return us details of student. */ @GET("api/directions/json?key=AIzaSyC22GfkHu9FdgT9SwdCWMwKX1a4aohGifM") Call<Example> getDistanceDuration(@Query("units") String units, @Query("origin") String origin, @Query("destination") String destination, @Query("mode") String mode);
}
我希望这解释你的查询。 祝一切顺利 :)
来源: 谷歌地图距离计算器