Skip to content

Instantly share code, notes, and snippets.

@psahni
Created October 1, 2011 14:15
Show Gist options
  • Save psahni/1256095 to your computer and use it in GitHub Desktop.
Save psahni/1256095 to your computer and use it in GitHub Desktop.
geodistance example
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Center of Geodesic Polyline</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="v3_gmaps_enhance.js"></script>
<script type="text/javascript">
var EarthRadiusMeters = 6378137.0; // meters
/* Based the on the Latitude/longitude spherical geodesy formulae & scripts
at http://www.movable-type.co.uk/scripts/latlong.html
(c) Chris Veness 2002-2010
*/
google.maps.LatLng.prototype.DestinationPoint = function (brng, dist) {
var R = EarthRadiusMeters; // earth's mean radius in meters
var brng = brng.toRad();
var lat1 = this.lat().toRad(), lon1 = this.lng().toRad();
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist/R) +
Math.cos(lat1)*Math.sin(dist/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist/R)*Math.cos(lat1),
Math.cos(dist/R)-Math.sin(lat1)*Math.sin(lat2));
return new google.maps.LatLng(lat2.toDeg(), lon2.toDeg());
}
// === A function which returns the bearing between two LatLng in radians ===
// === If v1 is null, it returns the bearing between the first and last vertex ===
// === If v1 is present but v2 is null, returns the bearing from v1 to the next vertex ===
// === If either vertex is out of range, returns void ===
google.maps.LatLng.prototype.Bearing = function(otherLatLng) {
var from = this;
var to = otherLatLng;
if (from.equals(to)) {
return 0;
}
var lat1 = from.latRadians();
var lon1 = from.lngRadians();
var lat2 = to.latRadians();
var lon2 = to.lngRadians();
var angle = - Math.atan2( Math.sin( lon1 - lon2 ) * Math.cos( lat2 ), Math.cos( lat1 ) * Math.sin( lat2 ) - Math.sin( lat1 ) * Math.cos( lat2 ) * Math.cos( lon1 - lon2 ) );
if ( angle < 0.0 ) angle += Math.PI * 2.0;
if ( angle > Math.PI ) angle -= Math.PI * 2.0;
return parseFloat(angle.toDeg());
}
function geodesicPolyline(start, end) {
bounds.extend(start);
bounds.extend(end);
var geodesicPoints = new Array();
with (Math) {
var lat1 = start.lat() * (PI/180);
var lon1 = start.lng() * (PI/180);
var lat2 = end.lat() * (PI/180);
var lon2 = end.lng() * (PI/180);
var d = 2*asin(sqrt( pow((sin((lat1-lat2)/2)),2) + cos(lat1)*cos(lat2)*pow((sin((lon1-lon2)/2)),2)));
for (var n = 0 ; n < 51 ; n++ ) {
var f = (1/50) * n;
// f = f.toFixed(6);
var A = sin((1-f)*d)/sin(d)
var B = sin(f*d)/sin(d)
var x = A*cos(lat1)*cos(lon1) + B*cos(lat2)*cos(lon2)
var y = A*cos(lat1)*sin(lon1) + B*cos(lat2)*sin(lon2)
var z = A*sin(lat1) + B*sin(lat2)
var latN = atan2(z,sqrt(pow(x,2)+pow(y,2)))
var lonN = atan2(y,x)
var p = new google.maps.LatLng(latN/(PI/180), lonN/(PI/180));
geodesicPoints.push(p);
bounds.extend(p);
}
}
return geodesicPoints;
}
/**
* Extend the Number object to convert degrees to radians
*
* @return {Number} Bearing in radians
* @ignore
*/
Number.prototype.toRad = function () {
return this * Math.PI / 180;
};
/**
* Extend the Number object to convert radians to degrees
*
* @return {Number} Bearing in degrees
* @ignore
*/
Number.prototype.toDeg = function () {
return this * 180 / Math.PI;
};
/**
* Normalize a heading in degrees to between 0 and +360
*
* @return {Number} Return
* @ignore
*/
Number.prototype.toBrng = function () {
return (this.toDeg() + 360) % 360;
};
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
function createMarker(latlng, html) {
var contentString = html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
bounds.extend(latlng);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
}
function drawArc(center, initialBearing, finalBearing, radius) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / EarthRadiusMeters) * r2d;
var rlng = rlat / Math.cos(center.lat() * d2r);
var extp = new Array();
var deltaBearing = (finalBearing - initialBearing)/points;
for (var i=0; (i < points+1); i++)
{
extp.push(center.DestinationPoint(initialBearing + i*deltaBearing, radius));
bounds.extend(extp[extp.length-1]);
}
return extp;
}
function drawCircle(point, radius) {
var d2r = Math.PI / 180; // degrees to radians
var r2d = 180 / Math.PI; // radians to degrees
var EarthRadiusMeters = 6378137.0; // meters
var earthsradius = 3963; // 3963 is the radius of the earth in miles
var points = 32;
// find the raidus in lat/lon
var rlat = (radius / EarthRadiusMeters) * r2d;
var rlng = rlat / Math.cos(point.lat() * d2r);
var extp = new Array();
for (var i=0; i < points+1; i++) // one extra here makes sure we connect the
{
var theta = Math.PI * (i / (points/2));
ey = point.lng() + (rlng * Math.cos(theta)); // center a + radius x * cos(theta)
ex = point.lat() + (rlat * Math.sin(theta)); // center b + radius y * sin(theta)
extp.push(new google.maps.LatLng(ex, ey));
bounds.extend(extp[extp.length-1]);
}
// alert(extp.length);
return extp;
}
var map = null;
var bounds = null;
function initialize() {
var myOptions = {
zoom: 10,
center: new google.maps.LatLng(-33.9, 151.2),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
bounds = new google.maps.LatLngBounds();
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
var startPoint = new google.maps.LatLng(0.0,0.0);
// var startPoint = new google.maps.LatLng(28.613889, 77.208889);
bounds.extend(startPoint);
//var endPoint = new google.maps.LatLng(42.00547,-122.61535);
var endPoint = new google.maps.LatLng(27.1804, 78.0079);
bounds.extend(endPoint);
createMarker(startPoint,"start: "+startPoint.toUrlValue(6)+"<br>Bearing: "+startPoint.Bearing(endPoint)+"<br><a href='javascript:map.setCenter(new google.maps.LatLng("+startPoint.toUrlValue(6)+"));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
createMarker(endPoint,"end: "+endPoint.toUrlValue(6)+"<br>Bearing: "+endPoint.Bearing(startPoint)+"<br><a href='javascript:map.setCenter(new google.maps.LatLng("+endPoint.toUrlValue(6)+"));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
var normalPolyline = new google.maps.Polyline({
path: [startPoint, endPoint],
strokeColor: "#0000FF",
strokeOpacity: 0.5,
strokeWeight: 2,
map: map
});
var geodesicPoly = new google.maps.Polyline({
path: [startPoint, endPoint],
strokeColor: "#00FF00",
strokeOpacity: 0.5,
strokeWeight: 2,
geodesic: true,
map: map
});
var calcGeodesic = geodesicPolyline(startPoint, endPoint);
var calcGeodesicPolyline =new google.maps.Polyline({
path: calcGeodesic,
strokeColor: "#FF0000",
strokeOpacity: 0.5,
strokeWeight: 2,
geodesic: true,
map: map
});
google.maps.event.addListener(map, 'projection_changed', function() {
// second part of initialization, after projection has loaded
var normalCenterPoint = normalPolyline.GetPointAtDistance(startPoint.distanceFrom(endPoint)/2);
createMarker(normalCenterPoint, "center of normal polyline<br><a href='javascript:map.setCenter(new google.maps.LatLng("+normalCenterPoint.toUrlValue(6)+"));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
var geodesicCenterPoint = calcGeodesicPolyline.GetPointAtDistance(startPoint.distanceFrom(endPoint)/2);
createMarker(geodesicCenterPoint, "center of geodesic polyline<br><a href='javascript:map.setCenter(new google.maps.LatLng("+geodesicCenterPoint.toUrlValue(6)+"));map.setZoom(20);'>zoom in</a> - <a href='javascript:map.fitBounds(bounds);'>zoom out</a>");
map.fitBounds(bounds);
});
map.fitBounds(bounds);
}
</script>
</head>
<body style="margin:0px; padding:0px;" onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-162157-1";
urchinTracker();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment