Logic, but in a different way

Daft Logic

Google Maps Split Route Tool

Last Updated 28th September 2008

[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

  1. Draw a route by clicking points sequentially
  2. Once you have 2 or more points you can click the [Make a Split] option to start the split function
  3. Click the first...
  4. ...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
  5. Drag the new marker (if required) to the correct location

How it Works

var Icon=new GIcon(G_DEFAULT_ICON);
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

Version History

Previous Comments For This Page

No comments yet, be the first !

Add your own comment below and let others know what you think:

Comments :

Your Name (optional) :