Google Maps Split Route Tool
Last Updated 15th December 2009
[Map Height : Small - Medium - Large]
Description
There is a need, when creating routes, to allow a new marker to be inserted into the route between points that have already been input. This can be achieved by splitting a single polyline into two polylines and adding a new marker mid-way between them. From then on the user can then drag each marker to a different location.
How To Use
- Draw a route by clicking points sequentially
- Once you have 2 or more points you can click the [Make a Split] option to start the split function
- Click the first...
- ...And second points in between which you wish to make the split. The order in which you click (1,2 or 2,1) is not important
- Drag the new marker (if required) to the correct location
How it Works
Icon.image="http://www.freemaptools.com/images/markers/freemaptools.png";
Icon.shadow="http://www.freemaptools.com/images/markers/shadow.png";
Icon.iconSize=new GSize(20,34);
Icon.shadowSize=new GSize(37,34);
Icon.iconAnchor=new GPoint(9,34);
Icon.infoWindowAnchor=new GPoint(9,2);
Icon.infoShadowAnchor=new GPoint(18,25);
var mapDiv=document.getElementById(\'mapDiv\');
var map;
var points=[];
var pointsx=[];
var pointsy=[];
var temp = new Array();
var markers=[];
var lines=[];
var polygonPoints=[];
var polygon=null;
var lineColor="#ff0000";
var lineWidth=5;
var earthRadiusMeters=6367460.0;
var radiansPerDegree=Math.PI/180.0
var degreesPerRadian=180.0/Math.PI;
var mode=0;
var splitpoint1;
var splitpoint2;
function Gload()
{
mapDiv.innerHTML=\'Loading ...\';
if(!GBrowserIsCompatible())
{
mapDiv.innerHTML=\'Sorry, your browser is not compatible with Google Maps.\';
return;
}
map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GScaleControl());
map.setCenter(new GLatLng(0,0), 2);
map.setMapType(G_HYBRID_MAP);
GEvent.addListener(map, "click", function(overlay,point,overlaylatlng)
{
if(point)
{
points.push(point);
mapDiv.innerHTML="Adding Point ("+(points.length)+")...";
CheckPointsForSplit(points.length);
Display();
}
else
{
if (mode==2)
{
mapDiv.innerHTML="Splitting";
mode=0;
splitpoint2=overlaylatlng;
SplitRoute(splitpoint1,splitpoint2);
}
if (mode==1)
{
mapDiv.innerHTML="Click on the second marker";
mode=2;
splitpoint1=overlaylatlng;
}
}
});
mapDiv.innerHTML=\'Ready\';
}
function SplitRoute(pnt1,pnt2)
{
var hwc=GreatCirclePoints(pnt1,pnt2).length;
var midpc=Math.ceil(hwc/2);
var midpf=Math.floor(hwc/2);
var pointsc=[];
var pointsf=[];
gcpoints=GreatCirclePoints(pnt1,pnt2);
var xh=x_half_distance_between_points(gcpoints[midpc],gcpoints[midpf]);
var yh=y_half_distance_between_points(gcpoints[midpc],gcpoints[midpf]);
var midpoint=new GLatLng(xh,yh);
var tmppoints=[];
var insertpoint=getlowestbetween(getindexofpoint(pnt1),getindexofpoint(pnt2));
for(var i=0;i<points.length;++i)
{
tmppoints.push(points[i]);
if (i==insertpoint)
{
tmppoints.push(midpoint);
}
}
points=tmppoints;
Display();
mapDiv.innerHTML="Split Complete";
}
function getlowestbetween(i1,i2)
{
if (i1>i2)
{
return (i2);
}
else
{
return (i1);
}
}
function getindexofpoint(point)
{
var index;
for(var i=0;i<points.length;++i)
{
if ((points[i].lat()==point.lat())&&(points[i].lng()==point.lng()))
{
index=i;
}
}
return (index);
}
function x_half_distance_between_points(p1,p2)
{
var a=p2.y+p1.y;
return a/2;
}
function y_half_distance_between_points(p1,p2)
{
var a=p2.x+p1.x;
return a/2;
}
function CheckPointsForSplit(nopoints)
{
if (nopoints>1)
{
document.getElementById("btn_split").disabled=false;
}
else
{
document.getElementById("btn_split").disabled=true;
}
}
function MakeSplit()
{
mapDiv.innerHTML="Click on the first marker";
mode=1;
}
function Display()
{
map.clearOverlays();
markers=[];
lines=[];
polygonPoints=[];
if(polygon!=null)
{
map.removeOverlay(polygon);
polygon=null;
}
for(var i=0;i<points.length;++i)
{
var marker=new GMarker(points[i],Icon);
markers.push(marker);
map.addOverlay(createMarker(points[i],i));
if(i>0&&points.length>1)
{
AddPolylines(lines,GreatCirclePoints(points[i-1],points[i]),lineColor,lineWidth);
}
}
}
function createMarker(point, number)
{
var marker=new GMarker(point,{icon:Icon,draggable:true});
GEvent.addListener(marker,"dragend",function()
{
points[number]=marker.getLatLng();
Display();
});
return marker;
}
function AddPolylines(lines,ps,lineColor,lineWidth)
{
var line=new GPolyline(ps,lineColor,lineWidth);
lines.push(line);
map.addOverlay(line);
for(var i=0;i<ps.length;++i)
{
polygonPoints.push(ps[i]);
}
}
function GreatCirclePoints(p1,p2)
{
var maxDistanceMeters=200000.0;
var ps=[];
if(p1.distanceFrom(p2)<=maxDistanceMeters)
{
ps.push(p1);
ps.push(p2);
}
else
{
var theta1=p1.lng()*radiansPerDegree;
var phi1=(90.0-p1.lat())*radiansPerDegree;
var x1=earthRadiusMeters*Math.cos(theta1)*Math.sin(phi1);
var y1=earthRadiusMeters*Math.sin(theta1)*Math.sin(phi1);
var z1=earthRadiusMeters*Math.cos(phi1);
var theta2=p2.lng()*radiansPerDegree;
var phi2=(90.0-p2.lat())*radiansPerDegree;
var x2=earthRadiusMeters*Math.cos(theta2)*Math.sin(phi2);
var y2=earthRadiusMeters*Math.sin(theta2)*Math.sin(phi2);
var z2=earthRadiusMeters*Math.cos(phi2);
var x3=(x1+x2)/2.0;
var y3=(y1+y2)/2.0;
var z3=(z1+z2)/2.0;
var r3=Math.sqrt(x3*x3+y3*y3+z3*z3);
var theta3=Math.atan2(y3,x3);
var phi3=Math.acos(z3/r3);
var p3=new GLatLng(90.0-phi3*degreesPerRadian,theta3*degreesPerRadian);
var s1=GreatCirclePoints(p1,p3);
var s2=GreatCirclePoints(p3,p2);
for(var i=0;i<s1.length;++i)
ps.push(s1[i]);
for(var i=1;i<s2.length;++i)
ps.push(s2[i]);
}
return ps;
}
function ClearMap()
{
points=[];
Display();
map.clearOverlays();
CheckPointsForSplit(points.length);
mode=0;
}
Relevant Links
http://www.google.com/apis/maps/
Further Uses and Ideas
- 24/11/2009 - Fix bug where high zoom causes split to occur on marker #2 rather then the mid-point
- 15/12/2009 - Fix another split bug
Version History
- Version 1 (28/09/2008)
- Version 1.1 (15/12/2009) - You are here
Previous Comments For This Page
No comments yet, be the first !
Add your own comment below and let others know what you think: