谷歌地图API v.3从一点到多点查找最近点 [英] Google map API v.3 find nearest point from one point to point on polyline
问题描述
我找到一个好的图书馆 http:/ /wtp2.appspot.com/cSnapToRouteDemo.html ,但该库适用于Google API版本。 2,我正在使用Google API版本。 3. Google API版本还有其他选择吗? 3? Google地图Javascript API有一个 / documentation / javascript / geometryrel =nofollow>几何库。
几何库有一个 isLocationOnEdge
函数。请参阅文档。
要确定点是否落在折线上或附近多边形上,或在多边形的边上或附近,请将该点,折线/多边形以及可选的公差值(以度为单位)
google.maps.geometry.poly.isLocationOnEdge()
。如果该点与线或边上最近点之间的距离在指定的容差范围内,该函数返回true。默认的容差值是10 -9 度。
您必须以这种方式包含库:
< script type =text / javascript
src =https://maps.googleapis.com/maps / API / JS键= YOUR_API_KEY&安培;库=几何>
< / script>
如果您需要多个库,例如:
< script type =text / javascript
src =https://maps.googleapis.com/maps/api/js?key= YOUR_API_KEY&安培;库=几何,地点>
< / script>
完整文档为 here 。
如果您需要查找点在Polyline上,你可以使用这个移植到你在你的问题中提到的库的v3版本:
var mapRoute;
var rtPoints;
var centerMAP = new google.maps.LatLng(-7.402438,110.446957);
函数gLatLngFromEN(e,n){
var ogbLL = NEtoLL(e,n);
var pc = OGBToWGS84(ogbLL.lat,ogbLL.lon,0);
返回新的google.maps.LatLng(pc.lat,pc.lon);
函数routeMap(){
mapRoute = new google.maps.Map(document.getElementById('mapRoute'),{
center :centerMAP,
zoom:14,
mapTypeId:google.maps.MapTypeId.SATELLITE
});
mapRoute.setCenter(gLatLngFromEN(469000,169000),13);
var rtPoints = new Array();
rtPoints.push(gLatLngFromEN(468000,168000));
rtPoints.push(gLatLngFromEN(468000,170000));
rtPoints.push(gLatLngFromEN(470000,170000));
rtPoints.push(gLatLngFromEN(470000,168000));
var rtPoly = new google.maps.Polyline({
路径:rtPoints,
strokeColor:#0000FF,
strokeWeight:3,
map:mapRoute
});
var container = document.createElement(div);
container.style.fontFamily ='Arial';
container.style.fontSize ='XX-Small';
var ptr = document.createElement(INPUT);
ptr.style.width =100px;
ptr.type =文字;
ptr.readOnly = true;
ptr.id =distPtr;
container.appendChild(ptr);
document.getElementById(control)。appendChild(container);
google.maps.event.addListener(mapRoute,'mousemove',function(point){
document.getElementById('distPtr')。value = Math.round bdccGeoDistanceToPolyMtrs(rtPoly,point.latLng));
});
}
google.maps.event.addDomListener(window,'load',routeMap);
//用于查找纬度/经度点与纬度/经度点间距离的代码
//全部用WGS84表示。免费用于任何用途。
//
// Bill Chadwick 2007
//更新为Google Maps API v3,Lawrence Ross 2014
//根据其经度和纬度构建bdccGeo度
函数bdccGeo(lat,lon)
{
var theta =(lon * Math.PI / 180.0);
var rlat = bdccGeoGeocentricLatitude(lat * Math.PI / 180.0);
var c = Math.cos(rlat);
this.x = c * Math.cos(theta);
this.y = c * Math.sin(theta);
this.z = Math.sin(rlat);
}
bdccGeo.prototype = new bdccGeo();
//内部帮助函数===================================== ====
//将地理转换为以地心为中心的纬度(弧度)。
函数bdccGeoGeocentricLatitude(geographicLatitude)
{
var flattening = 1.0 / 298.257223563; // WGS84
var f =(1.0 - flattening)*(1.0 - flattening);
return Math.atan((Math.tan(geographicLatitude)* f));
}
//从地心坐标转换为地理纬度(弧度)
函数bdccGeoGeographicLatitude(geocentricLatitude)
{
var flattening = 1.0 / 298.257223563; / / WGS84
var f =(1.0 - 展平)*(1.0 - 展平);
return Math.atan(Math.tan(geocentricLatitude)/ f);
}
//返回由圆弧geo1到geo2和
// geo3到geo4定义的两个很好的
//圆圈的两个对极点。返回一个点作为Geo,使用.antipode获取另一个点
函数bdccGeoGetIntersection(geo1,geo2,geo3,geo4)
{
var geoCross1 = geo1.crossNormalize(geo2);
var geoCross2 = geo3.crossNormalize(geo4);
返回geoCross1.crossNormalize(geoCross2);
}
//从Radians到Meters
函数bdccGeoRadiansToMeters(rad)
{
return rad * 6378137.0; // WGS84赤道半径(以米为单位)
}
//从米到弧度
函数bdccGeoMetersToRadians(m)
{
return m / 6378137.0; // WGS84赤道半径(以米为单位)
}
//属性=========================== ======================
bdccGeo.prototype.getLatitudeRadians = function()
{
return(bdccGeoGeographicLatitude(Math.atan2(this.z,
Math.sqrt((this.x * this.x)+(this.y * this.y)))));
}
bdccGeo.prototype.getLongitudeRadians = function()
{
return(Math.atan2(this.y,this.x));
}
bdccGeo.prototype.getLatitude = function()
{
return this.getLatitudeRadians()* 180.0 / Math.PI;
}
bdccGeo.prototype.getLongitude = function()
{
return this.getLongitudeRadians()* 180.0 / Math.PI;
}
//方法================================== ===============
//数学
bdccGeo.prototype.dot =函数(b)
{
返回((this.x * bx)+(this.y * by)+(this.z * bz));
}
//更多数学
bdccGeo.prototype.crossLength =函数(b)
{
var x =(this.y * bz) - (this.z * by);
var y =(this.z * b.x) - (this.x * b.z);
var z =(this.x * b.y) - (this.y * b.x);
return Math.sqrt((x * x)+(y * y)+(z * z));
}
//更多数学
bdccGeo.prototype.scale =函数
{
var r = new bdccGeo(0,0) ;
r.x = this.x * s;
r.y = this.y * s;
r.z = this.z * s;
return r;
//更多数学
bdccGeo.prototype.crossNormalize =函数(b)
{
var x =(this.y * bz) - (this.z * by);
var y =(this.z * b.x) - (this.x * b.z);
var z =(this.x * b.y) - (this.y * b.x);
var L = Math.sqrt((x * x)+(y * y)+(z * z));
var r = new bdccGeo(0,0);
r.x = x / L;
r.y = y / L;
r.z = z / L;
return r;
}
//指向这个点的世界另一端
bdccGeo.prototype.antipode = function()
{
return this。规模(-1.0);
}
//以弧度为单位的距离,从这点到点v2
bdccGeo。 prototype.distance = function(v2)
{
return Math.atan2(v2.crossLength(this),v2.dot(this));
}
//以米为单位返回此点与线段geo1-geo2
//的垂直距离的最小值,以及此点到线段的距离在geo1和geo2中结束
bdccGeo.prototype.distanceToLineSegMtrs =函数(geo1,geo2)
{
//单位球体上方原点和法线到地平面的点geo1,geo2
//可以是飞机的任一侧
var p2 = geo1.crossNormalize(geo2);
//使用GC geo1 / geo2通过p传递给geo1 / geo2的GC法线交点
var ip = bdccGeoGetIntersection(geo1,geo2,this,p2);
//需要检查ip或其反对象在p1和p2之间
var d = geo1.distance(geo2);
var d1p = geo1.distance(ip);
var d2p = geo2.distance(ip);
//window.status = d +,+ d1p +,+ d2p; ((d> = d1p)&(d> = d2p))
返回bdccGeoRadiansToMeters(this.distance(ip));
else
{
ip = ip.antipode();
d1p = geo1.distance(ip);
d2p = geo2.distance(ip); ((d> = d1p)&&(d> = d2p))
返回bdccGeoRadiansToMeters(this.distance(ip));
}
。
else
return bdccGeoRadiansToMeters(Math.min(geo1.distance(this),geo2.distance(this)));
}
//与GLatLng指向GPolyline或GPolygon的距离(单位:百万)b
bc函数bdccGeoDistanceToPolyMtrs(poly,point)
{
var d = 999999999 ;
var i;
var p = new bdccGeo(point.lat(),point.lng()); ($)
for(i = 0; i <(poly.getPath()。getLength() - 1); i ++)
{
var p1 = poly.getPath()。getAt(i) ;
var l1 = new bdccGeo(p1.lat(),p1.lng());
var p2 = poly.getPath()。getAt(i + 1);
var l2 = new bdccGeo(p2.lat(),p2.lng());
var dp = p.distanceToLineSegMtrs(l1,l2);
if(dp d = dp;
}
return d;
}
//获得一个新的GLatLng距离指南针距离GLatLng点的azimuthDegrees
//的距离 - 精确到140米(14米20米处)的200米以内英国
函数bdccGeoPointAtRangeAndBearing(point,distanceMeters,azimuthDegrees)
{
var latr = point.lat()* Math.PI / 180.0;
var lonr = point.lng()* Math.PI / 180.0;
var coslat = Math.cos(latr);
var sinlat = Math.sin(latr);
var az = azimuthDegrees * Math.PI / 180.0;
var cosaz = Math.cos(az);
var sinaz = Math.sin(az);
var dr = distanceMeters / 6378137.0; //使用WGS84的弧度距离Equalsial Radius
var sind = Math.sin(dr);
var cosd = Math.cos(dr); $(Math.asin((sinlat * cosd)+(coslat * sind * cosaz))* 180.0 / Math.PI,
(Math.atan2( (sind * sinaz),(coslat * cosd) - (sinlat * sind * cosaz))+ lonr)* 180.0 / Math.PI);
}
致信Bill Chadwick 2007和Lawrence Ross 2014 v3版。和@geocodezip找到它。
I`ve got a map with a polyline. The server will responds me with a LatLng point on a map. I need to check if the point from the server situated on a polyline edge. If not, i need to find the nearest point on the polyline and place a marker on the nearest point on the polyline. For example, if the server responds me with a point A, i need to place a marker to a point B.
I find a good library http://wtp2.appspot.com/cSnapToRouteDemo.html, but this library is for Google API ver. 2, and i'm using Google API ver. 3. Is there any alternative for Google API ver. 3 ? Thank's.
The Google Maps Javascript API has a Geometry library.
The Geometry library has a isLocationOnEdge
function. See the documentation.
To determine whether a point falls on or near a polyline, or on or near the edge of a polygon, pass the point, the polyline/polygon, and optionally a tolerance value in degrees to
google.maps.geometry.poly.isLocationOnEdge()
. The function returns true if the distance between the point and the closest point on the line or edge falls within the specified tolerance. The default tolerance value is 10-9 degrees.
You must include the library this way:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry">
</script>
And if you need more than one library, for example:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=geometry,places">
</script>
Full documentation is here.
If you need to find the point on the Polyline, you can use this ported to v3 version of the library you mentioned in your question:
var mapRoute;
var rtPoints;
var centerMAP = new google.maps.LatLng(-7.402438, 110.446957);
function gLatLngFromEN(e, n) {
var ogbLL = NEtoLL(e, n);
var pc = OGBToWGS84(ogbLL.lat, ogbLL.lon, 0);
return new google.maps.LatLng(pc.lat, pc.lon);
}
function routeMap() {
mapRoute = new google.maps.Map(document.getElementById('mapRoute'), {
center: centerMAP,
zoom: 14,
mapTypeId: google.maps.MapTypeId.SATELLITE
});
mapRoute.setCenter(gLatLngFromEN(469000, 169000), 13);
var rtPoints = new Array();
rtPoints.push(gLatLngFromEN(468000, 168000));
rtPoints.push(gLatLngFromEN(468000, 170000));
rtPoints.push(gLatLngFromEN(470000, 170000));
rtPoints.push(gLatLngFromEN(470000, 168000));
var rtPoly = new google.maps.Polyline({
path: rtPoints,
strokeColor: "#0000FF",
strokeWeight: 3,
map: mapRoute
});
var container = document.createElement("div");
container.style.fontFamily = 'Arial';
container.style.fontSize = 'XX-Small';
var ptr = document.createElement("INPUT");
ptr.style.width = "100px";
ptr.type = "Text";
ptr.readOnly = true;
ptr.id = "distPtr";
container.appendChild(ptr);
document.getElementById("control").appendChild(container);
google.maps.event.addListener(mapRoute, 'mousemove', function (point) {
document.getElementById('distPtr').value = Math.round(bdccGeoDistanceToPolyMtrs(rtPoly, point.latLng));
});
}
google.maps.event.addDomListener(window, 'load', routeMap);
// Code to find the distance in metres between a lat/lng point and a polyline of lat/lng points
// All in WGS84. Free for any use.
//
// Bill Chadwick 2007
// updated to Google Maps API v3, Lawrence Ross 2014
// Construct a bdccGeo from its latitude and longitude in degrees
function bdccGeo(lat, lon)
{
var theta = (lon * Math.PI / 180.0);
var rlat = bdccGeoGeocentricLatitude(lat * Math.PI / 180.0);
var c = Math.cos(rlat);
this.x = c * Math.cos(theta);
this.y = c * Math.sin(theta);
this.z = Math.sin(rlat);
}
bdccGeo.prototype = new bdccGeo();
// internal helper functions =========================================
// Convert from geographic to geocentric latitude (radians).
function bdccGeoGeocentricLatitude(geographicLatitude)
{
var flattening = 1.0 / 298.257223563;//WGS84
var f = (1.0 - flattening) * (1.0 - flattening);
return Math.atan((Math.tan(geographicLatitude) * f));
}
// Convert from geocentric to geographic latitude (radians)
function bdccGeoGeographicLatitude (geocentricLatitude)
{
var flattening = 1.0 / 298.257223563;//WGS84
var f = (1.0 - flattening) * (1.0 - flattening);
return Math.atan(Math.tan(geocentricLatitude) / f);
}
// Returns the two antipodal points of intersection of two great
// circles defined by the arcs geo1 to geo2 and
// geo3 to geo4. Returns a point as a Geo, use .antipode to get the other point
function bdccGeoGetIntersection( geo1, geo2, geo3, geo4)
{
var geoCross1 = geo1.crossNormalize(geo2);
var geoCross2 = geo3.crossNormalize(geo4);
return geoCross1.crossNormalize(geoCross2);
}
//from Radians to Meters
function bdccGeoRadiansToMeters(rad)
{
return rad * 6378137.0; // WGS84 Equatorial Radius in Meters
}
//from Meters to Radians
function bdccGeoMetersToRadians(m)
{
return m / 6378137.0; // WGS84 Equatorial Radius in Meters
}
// properties =================================================
bdccGeo.prototype.getLatitudeRadians = function()
{
return (bdccGeoGeographicLatitude(Math.atan2(this.z,
Math.sqrt((this.x * this.x) + (this.y * this.y)))));
}
bdccGeo.prototype.getLongitudeRadians = function()
{
return (Math.atan2(this.y, this.x));
}
bdccGeo.prototype.getLatitude = function()
{
return this.getLatitudeRadians() * 180.0 / Math.PI;
}
bdccGeo.prototype.getLongitude = function()
{
return this.getLongitudeRadians() * 180.0 / Math.PI ;
}
// Methods =================================================
//Maths
bdccGeo.prototype.dot = function( b)
{
return ((this.x * b.x) + (this.y * b.y) + (this.z * b.z));
}
//More Maths
bdccGeo.prototype.crossLength = function( b)
{
var x = (this.y * b.z) - (this.z * b.y);
var y = (this.z * b.x) - (this.x * b.z);
var z = (this.x * b.y) - (this.y * b.x);
return Math.sqrt((x * x) + (y * y) + (z * z));
}
//More Maths
bdccGeo.prototype.scale = function( s)
{
var r = new bdccGeo(0,0);
r.x = this.x * s;
r.y = this.y * s;
r.z = this.z * s;
return r;
}
// More Maths
bdccGeo.prototype.crossNormalize = function( b)
{
var x = (this.y * b.z) - (this.z * b.y);
var y = (this.z * b.x) - (this.x * b.z);
var z = (this.x * b.y) - (this.y * b.x);
var L = Math.sqrt((x * x) + (y * y) + (z * z));
var r = new bdccGeo(0,0);
r.x = x / L;
r.y = y / L;
r.z = z / L;
return r;
}
// point on opposite side of the world to this point
bdccGeo.prototype.antipode = function()
{
return this.scale(-1.0);
}
//distance in radians from this point to point v2
bdccGeo.prototype.distance = function( v2)
{
return Math.atan2(v2.crossLength(this), v2.dot(this));
}
//returns in meters the minimum of the perpendicular distance of this point from the line segment geo1-geo2
//and the distance from this point to the line segment ends in geo1 and geo2
bdccGeo.prototype.distanceToLineSegMtrs = function(geo1, geo2)
{
//point on unit sphere above origin and normal to plane of geo1,geo2
//could be either side of the plane
var p2 = geo1.crossNormalize(geo2);
// intersection of GC normal to geo1/geo2 passing through p with GC geo1/geo2
var ip = bdccGeoGetIntersection(geo1,geo2,this,p2);
//need to check that ip or its antipode is between p1 and p2
var d = geo1.distance(geo2);
var d1p = geo1.distance(ip);
var d2p = geo2.distance(ip);
//window.status = d + ", " + d1p + ", " + d2p;
if ((d >= d1p) && (d >= d2p))
return bdccGeoRadiansToMeters(this.distance(ip));
else
{
ip = ip.antipode();
d1p = geo1.distance(ip);
d2p = geo2.distance(ip);
}
if ((d >= d1p) && (d >= d2p))
return bdccGeoRadiansToMeters(this.distance(ip));
else
return bdccGeoRadiansToMeters(Math.min(geo1.distance(this),geo2.distance(this)));
}
// distance in meters from GLatLng point to GPolyline or GPolygon poly
function bdccGeoDistanceToPolyMtrs(poly, point)
{
var d = 999999999;
var i;
var p = new bdccGeo(point.lat(),point.lng());
for(i=0; i<(poly.getPath().getLength()-1); i++)
{
var p1 = poly.getPath().getAt(i);
var l1 = new bdccGeo(p1.lat(),p1.lng());
var p2 = poly.getPath().getAt(i+1);
var l2 = new bdccGeo(p2.lat(),p2.lng());
var dp = p.distanceToLineSegMtrs(l1,l2);
if(dp < d)
d = dp;
}
return d;
}
// get a new GLatLng distanceMeters away on the compass bearing azimuthDegrees
// from the GLatLng point - accurate to better than 200m in 140km (20m in 14km) in the UK
function bdccGeoPointAtRangeAndBearing (point, distanceMeters, azimuthDegrees)
{
var latr = point.lat() * Math.PI / 180.0;
var lonr = point.lng() * Math.PI / 180.0;
var coslat = Math.cos(latr);
var sinlat = Math.sin(latr);
var az = azimuthDegrees* Math.PI / 180.0;
var cosaz = Math.cos(az);
var sinaz = Math.sin(az);
var dr = distanceMeters / 6378137.0; // distance in radians using WGS84 Equatorial Radius
var sind = Math.sin(dr);
var cosd = Math.cos(dr);
return new google.maps.LatLng(Math.asin((sinlat * cosd) + (coslat * sind * cosaz)) * 180.0 / Math.PI,
(Math.atan2((sind * sinaz), (coslat * cosd) - (sinlat * sind * cosaz)) + lonr) * 180.0 / Math.PI);
}
Credits to Bill Chadwick 2007 and Lawrence Ross 2014 for the v3 version. And @geocodezip for finding it.
这篇关于谷歌地图API v.3从一点到多点查找最近点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!