Reputation: 4325
There doesn't seem to be a length funciton for the Polyline in Google Maps anymore in V3.
Has anyone found a workaround for this functionality gap?
Upvotes: 1
Views: 20371
Reputation: 161334
There is now a method in the Google Maps Javascript API v3 geometry library to compute the distance between two google.maps.LatLng objects in meters google.maps.geometry.spherical.computeDistanceBetween
.
And a method in the Google Maps Javascript API v3 geometry library to compute the length of a polyline google.maps.geometry.poly.computeLength
.
Concept from the Google Maps JavaScript API v3 groups post referenced in Hamish's answer, but using the Google Maps Javascript API v3 geometry library method computeDistanceBetween:
google.maps.Polyline.prototype.inKm = function(n) {
var a = this.getPath(n),
len = a.getLength(),
dist = 0;
for (var i = 0; i < len - 1; i++) {
dist += google.maps.geometry.spherical.computeDistanceBetween(a.getAt(i), a.getAt(i + 1));
}
return dist / 1000;
}
The result is the length of the polyline in kilometers. The optional parameter is the path index of multi path polylines.
Using computeLength:
google.maps.geometry.spherical.computeLength(poly.getPath())/1000
code snippet:
var map;
var poly;
var gmarkers = [];
function initialize() {
map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(map, 'click', addLatLng);
var polyCoord = [
new google.maps.LatLng(41.86, 8.73),
new google.maps.LatLng(41.88, 8.75)
];
var bounds = new google.maps.LatLngBounds();
bounds.extend(polyCoord[0]);
bounds.extend(polyCoord[1]);
map.fitBounds(bounds);
google.maps.event.addListenerOnce(map, 'bounds_changed', function() {
map.setZoom(map.getZoom() - 2);
});
// Polyline
poly = new google.maps.Polyline({
path: polyCoord
});
poly.binder = new MVCArrayBinder(poly.getPath());
var marker0 = new google.maps.Marker({
position: event.latLng,
title: '#0',
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
marker0.bindTo('position', poly.binder, (0).toString());
google.maps.event.addListener(marker0, 'dragend', updateLength);
gmarkers.push(marker0);
var marker1 = new google.maps.Marker({
position: event.latLng,
title: '#1',
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
marker1.bindTo('position', poly.binder, (1).toString());
google.maps.event.addListener(marker1, 'dragend', updateLength);
gmarkers.push(marker1);
poly.setMap(map);
updateLength();
}
function updateLength() {
document.getElementById('length').value = (google.maps.geometry.spherical.computeLength(poly.getPath()) / 1000).toFixed(2);
};
google.maps.event.addDomListener(window, "load", initialize);
/**
* Handles click events on a map, and adds a new point to the Polyline.
* @param {MouseEvent} mouseEvent
*/
function addLatLng(event) {
var path = poly.getPath();
path.push(event.latLng);
var len = path.getLength();
var marker = new google.maps.Marker({
position: event.latLng,
title: '#' + len,
map: map,
icon: {
path: 'M256,320c-70.688,0-128-57.312-128-128c0-70.687,57.313-128,128-128c70.688,0,128,57.313,128,128C384,262.688,326.688,320,256,320z',
fillColor: 'white',
fillOpacity: 1,
scale: 0.025,
strokeColor: 'black',
strokeWeight: 1,
strokeOpacity: 1,
anchor: new google.maps.Point(200, 200)
},
draggable: true
});
gmarkers.push(marker);
marker.bindTo('position', poly.binder, (len - 1).toString());
google.maps.event.addListener(marker, 'dragend', updateLength);
document.getElementById('length').value = poly.inKm().toFixed(2);
}
/*
* Use bindTo to allow dynamic drag of markers to refresh poly.
*/
function MVCArrayBinder(mvcArray) {
this.array_ = mvcArray;
}
MVCArrayBinder.prototype = new google.maps.MVCObject();
MVCArrayBinder.prototype.get = function(key) {
if (!isNaN(parseInt(key))) {
return this.array_.getAt(parseInt(key));
} else {
this.array_.get(key);
}
}
MVCArrayBinder.prototype.set = function(key, val) {
if (!isNaN(parseInt(key))) {
this.array_.setAt(parseInt(key), val);
} else {
this.array_.set(key, val);
}
}
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<label>polyline length (km):</label>
<input id="length" type="text" />
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
Upvotes: 5
Reputation: 21
I went looking for the same information and found that the api call you're looking for is in the geometry.spherical namespace.
Here's the code I'm using:
//Path is the mvc array of lat/lng that makes up the polyline
var path = $scope.courseLine.getPath();
$scope.totalDistance = google.maps.geometry.spherical.computeLength(path);
$scope.totalMiles = ($scope.totalDistance * 0.00062137).toFixed(2) + " mi";
});
Upvotes: 2
Reputation: 2752
If you got the polyline from DirectionsService, check distance and duration in DirectionsLeg.
https://developers.google.com/maps/documentation/javascript/reference#DirectionsLeg
Upvotes: 1
Reputation: 271
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=true"></script>
... var path = poly.getPath(); // or:
var path = polygon.getPath();
... = google.maps.geometry.spherical.computeLength(path.getArray())
... = google.maps.geometry.spherical.computeArea(path.getArray())
--> distance for polyline, area for polygon
and between two points: computeDistanceBetween()
Don't forget to specify the geometry library (libraries=geometry)
http://code.google.com/apis/maps/documentation/javascript/geometry.html
Upvotes: 19
Reputation: 76669
here's the prototypes for the required function - hope this helps any further:
google.maps.Polygon.prototype.Distance = function() {
var dist = 0;
for (var i=1; i < this.getPath().getLength(); i++) {
dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
}
return dist;
}
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
//var R = 6371; // km (change this constant to get miles)
var R = 6378100; // meters
var lat1 = this.lat();
var lon1 = this.lng();
var lat2 = newLatLng.lat();
var lon2 = newLatLng.lng();
var dLat = (lat2-lat1) * Math.PI / 180;
var dLon = (lon2-lon1) * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
Upvotes: 5
Reputation: 30170
Get the distance between the 2 LatLngs it connects using the haversine formula
Upvotes: 0
Reputation: 23316
It has to be done segment by segment.
See this Google Maps JavaScript API v3 groups post for a suggested solution.
Upvotes: 4