Created
October 25, 2012 21:43
-
-
Save romuloceccon/3955626 to your computer and use it in GitHub Desktop.
Google maps javascript api path editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
x1, y1 = 1.0, 2.2 | |
x2, y2 = 5.0, 3.3 | |
x3, y3 = -10.0, -100.0 | |
dx12 = x1 - x2 | |
dy12 = y1 - y2 | |
den = dx12 ** 2 + dy12 ** 2 | |
x4 = (x3 * dx12 ** 2 - dy12 * (x1 * (y2 - y3) - x2 * (y1 - y3))) / den | |
y4 = (y3 * dy12 ** 2 - dx12 * (y1 * (x2 - x3) - y2 * (x1 - x3))) / den | |
print x4, " ", y4, "\n" | |
dx12 = x1 - x2 | |
dy12 = y1 - y2 | |
k = (dx12 * (y3 - y1) - dy12 * (x3 - x1)) / (dx12 ** 2 + dy12 ** 2) | |
x4 = x3 + k * dy12 | |
y4 = y3 - k * dx12 | |
print x4, " ", y4, "\n" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> | |
<meta charset="UTF-8"> | |
<style type="text/css"> | |
html { height: 100% } | |
body { height: 100%; margin: 0; padding: 0 } | |
#map_canvas { height: 100% } | |
</style> | |
<script type="text/javascript" | |
src="http://maps.googleapis.com/maps/api/js?key=AIzaSyDflN5fMc6kgt5C1vSt8Durt1zNFp2IGN0&sensor=false"> | |
</script> | |
<script> | |
var map; | |
var directionsService; | |
var startPoint = null; | |
var poly; | |
var polyPath; | |
var drawMode = 'r'; | |
var segments = []; | |
var markers = []; | |
var stops = []; | |
var actionList; | |
var streetView; | |
var circleIcon = { path: google.maps.SymbolPath.CIRCLE, scale: 3 }; | |
var stopIcon = { path: 'M 0,0 0,-20 A 10,10 0 1 1 0,-40 A 10,10 0 1 1 0,-20', strokeWeight: 3, strokeColor: 'blue' }; | |
var linkIcon = { path: google.maps.SymbolPath.CIRCLE, scale: 3, strokeColor: 'red' }; | |
var attachedStopIcon = { path: 'M 0,0 0,-20 A 10,10 0 1 1 0,-40 A 10,10 0 1 1 0,-20', strokeWeight: 3, strokeColor: 'green' }; | |
var routeCursor = 'pointer'; | |
var stopCursor = 'crosshair'; | |
var eraseCursor = 'not-allowed'; | |
var curitiba = new google.maps.LatLng(-25.40, -49.27); | |
var mapOptions = { | |
zoom: 15, | |
mapTypeId: google.maps.MapTypeId.ROADMAP, | |
center: curitiba, | |
draggableCursor: routeCursor | |
}; | |
var polyOptions = { | |
strokeColor: '#000000', | |
strokeOpacity: 0.7, | |
strokeWeight: 2, | |
icons: [{ | |
icon: { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, scale: 1.5 }, | |
offset: '99px', | |
repeat: '100px' }] | |
}; | |
var linkOptions = { | |
strokeColor: 'red', | |
strokeOpacity: 1.0, | |
strokeWeight: 2, | |
}; | |
// ============================================================ | |
var wb = {}; | |
wb.ActionList = function() { | |
this.actions = []; | |
this.current = -1; | |
}; | |
wb.ActionList.prototype.do = function(action) { | |
action.do(); | |
var s = this.current + 1; | |
this.actions.splice(s, this.actions.length - s, action); | |
this.current = this.actions.length - 1; | |
}; | |
wb.ActionList.prototype.undo = function() { | |
if (this.current >= 0) | |
{ | |
this.actions[this.current].undo(); | |
this.current -= 1; | |
} | |
}; | |
wb.ActionList.prototype.redo = function() { | |
if (this.actions.length > this.current + 1) | |
{ | |
this.actions[this.current + 1].do(); | |
this.current += 1; | |
} | |
}; | |
wb.DrawStartPoint = function(position) { | |
this.position = position; | |
}; | |
wb.DrawStartPoint.prototype.do = function() { | |
startPoint = this.position; | |
redrawPath(); | |
}; | |
wb.DrawStartPoint.prototype.undo = function() { | |
startPoint = null; | |
redrawPath(); | |
}; | |
wb.DrawRouteSegment = function(segment) { | |
this.segment = segment; | |
}; | |
wb.DrawRouteSegment.prototype.do = function() { | |
segments.push(this.segment); | |
redrawPath(); | |
}; | |
wb.DrawRouteSegment.prototype.undo = function() { | |
segments.pop(); | |
redrawPath(); | |
}; | |
wb.DrawBusStop = function(position) { | |
var m = new google.maps.Marker({ | |
position: position, | |
icon: stopIcon | |
}); | |
var s = { marker: m, link: null }; | |
google.maps.event.addListener(m, 'click', function () { | |
if (drawMode == 'x') | |
{ | |
actionList.do(new wb.EraseBusStop(s, stops.indexOf(s))); | |
} | |
else if (drawMode == 'p') | |
{ | |
streetView.getPanorama().setPosition(m.getPosition()); | |
} | |
else if (!stop.link) | |
{ | |
var p1 = m.getPosition(); | |
var p2 = closestPointFromPoly(p1); | |
if (p1 != null && p2 != null) | |
actionList.do(new wb.DrawBusStopLink(s, p2)); | |
} | |
}); | |
this.stop = s; | |
}; | |
wb.DrawBusStop.prototype.do = function() { | |
this.stop.marker.setMap(map); | |
stops.push(this.stop); | |
}; | |
wb.DrawBusStop.prototype.undo = function() { | |
this.stop.marker.setMap(null); | |
stops.splice(stops.indexOf(this.stop), 1); | |
}; | |
wb.DrawBusStopLink = function(stop, p2) { | |
var p1 = stop.marker.getPosition(); | |
var o = []; | |
var line = new google.maps.Polyline(linkOptions); | |
line.getPath().push(p1); | |
line.getPath().push(p2); | |
o.push(new google.maps.Marker({ position: p1, icon: linkIcon })); | |
o.push(new google.maps.Marker({ position: p2, icon: linkIcon })); | |
o.push(line); | |
var f = function() { | |
if (drawMode == 'x') | |
actionList.do(new wb.EraseBusStopLink(stop)); | |
}; | |
o.forEach(function(a) { google.maps.event.addListener(a, 'click', f) }); | |
this.stop = stop; | |
this.objs = o; | |
}; | |
wb.DrawBusStopLink.prototype.do = function() { | |
this.objs.forEach(function(a) { a.setMap(map) }); | |
this.stop.link = this.objs; | |
}; | |
wb.DrawBusStopLink.prototype.undo = function() { | |
this.objs.forEach(function(a) { a.setMap(null) }); | |
this.stop.link = this.objs; | |
}; | |
wb.EraseBusStop = function(stop, index) { | |
this.stop = stop; | |
this.index = index; | |
}; | |
wb.EraseBusStop.prototype.do = function() { | |
this.stop.marker.setMap(null); | |
if (this.stop.link) | |
this.stop.link.forEach(function(a) { a.setMap(null) }); | |
stops.splice(this.index, 1); | |
}; | |
wb.EraseBusStop.prototype.undo = function() { | |
this.stop.marker.setMap(map); | |
if (this.stop.link) | |
this.stop.link.forEach(function(a) { a.setMap(map) }); | |
stops.splice(this.index, 0, this.stop); | |
}; | |
wb.EraseBusStopLink = function(stop) { | |
this.stop = stop; | |
this.objs = stop.link; | |
}; | |
wb.EraseBusStopLink.prototype.do = function() { | |
this.objs.forEach(function(a) { a.setMap(null) }); | |
this.stop.link = null; | |
}; | |
wb.EraseBusStopLink.prototype.undo = function() { | |
this.objs.forEach(function(a) { a.setMap(map) }); | |
this.stop.link = this.objs; | |
}; | |
wb.StreetView = function(ownerMap) { | |
var container = document.createElement('div'); | |
container.style.padding = '5px'; | |
container.style.display = 'none'; | |
container.index = 1; | |
var previewDiv = document.createElement('div'); | |
previewDiv.style.minWidth = '400px'; | |
previewDiv.style.minHeight = '300px'; | |
container.appendChild(previewDiv); | |
var panorama = new google.maps.StreetViewPanorama(previewDiv, | |
{ position: curitiba, pov: { heading: 0, pitch: 10, zoom: 1 }, visible: false }); | |
ownerMap.setStreetView(panorama); | |
ownerMap.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(container); | |
google.maps.event.addListener(panorama, 'visible_changed', function() { | |
if (panorama.getVisible()) | |
{ | |
drawMode = 'p'; | |
container.style.display = ''; | |
} | |
else | |
{ | |
if (drawMode == 'p') | |
drawMode = 'r'; | |
container.style.display = 'none'; | |
} | |
}); | |
this.panorama = panorama; | |
this.container = container; | |
}; | |
wb.StreetView.prototype.getPanorama = function() { | |
return this.panorama; | |
}; | |
// ============================================================ | |
function initialize() { | |
directionsService = new google.maps.DirectionsService(); | |
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions); | |
poly = new google.maps.Polyline(polyOptions); | |
poly.setMap(map); | |
polyPath = poly.getPath(); | |
actionList = new wb.ActionList(); | |
streetView = new wb.StreetView(map); | |
google.maps.event.addListener(map, 'click', onMapClick); | |
} | |
function keypress(e) { | |
var code; | |
if (!e) | |
var e = window.event; | |
if (e.keyCode) | |
code = e.keyCode; | |
else if (e.which) | |
code = e.which; | |
var character = String.fromCharCode(code); | |
if (character == 's' || character == 't' || character == 'x') | |
streetView.getPanorama().setVisible(false); | |
if (character == 'u') | |
{ | |
actionList.undo(); | |
} | |
else if (character == 'r') | |
{ | |
actionList.redo(); | |
} | |
else if (character == 'p') | |
{ | |
drawMode = 'p'; | |
map.setOptions({ draggableCursor: routeCursor }) | |
streetView.getPanorama().setVisible(true); | |
} | |
else if (character == 's') | |
{ | |
drawMode = 's'; | |
map.setOptions({ draggableCursor: stopCursor }) | |
} | |
else if (character == 't') | |
{ | |
drawMode = 'r'; | |
map.setOptions({ draggableCursor: routeCursor }) | |
} | |
else if (character == 'x') | |
{ | |
drawMode = 'x'; | |
map.setOptions({ draggableCursor: eraseCursor }) | |
} | |
} | |
function redrawPath() { | |
while (null != polyPath.pop()) | |
; | |
for (var m = markers.pop(); m != null; m = markers.pop()) | |
m.setMap(null); | |
if (segments.length == 0) | |
{ | |
if (startPoint != null) | |
drawCircle(startPoint); | |
} | |
else | |
{ | |
drawCircle(segments[0][0]); | |
} | |
for (var i = 0; i < segments.length; i++) | |
{ | |
for (var j = 0; j < segments[i].length; j++) | |
polyPath.push(segments[i][j]); | |
drawCircle(segments[i][segments[i].length - 1]); | |
} | |
} | |
function drawCircle(position) { | |
var m = new google.maps.Marker({ | |
position: position, | |
map: map, | |
icon: circleIcon | |
}); | |
markers.push(m); | |
} | |
// searches the closest polyline point to latLng, considering the | |
// coordinate system as an euclidean space (won't work across big | |
// distances or near the poles) | |
function closestPointFromPoly(latLng) { | |
if (polyPath.length == 0) | |
return null; | |
if (polyPath.length == 1) | |
return polyPath.getAt(0); | |
var minDistanceLatLng = polyPath.getAt(0); | |
var minDistance = google.maps.geometry.spherical.computeDistanceBetween( | |
latLng, minDistanceLatLng); | |
for (var i = 0; i < polyPath.length - 1; i++) | |
{ | |
var p1 = polyPath.getAt(i); | |
var p2 = polyPath.getAt(i + 1); | |
var dx12 = p1.Ya - p2.Ya; | |
var dy12 = p1.Za - p2.Za; | |
var k = (dx12 * (latLng.Za - p1.Za) - dy12 * (latLng.Ya - p1.Ya)) / | |
(dx12 * dx12 + dy12 * dy12); | |
var p4 = new google.maps.LatLng(latLng.Ya + k * dy12, latLng.Za - k * dx12); | |
var p; | |
// is p4 between p1 and p2? (takes into account horizontal/vertical lines) | |
if (Math.abs(p1.Ya - p2.Ya) > 0.00001 && (p1.Ya - p4.Ya) * (p4.Ya - p2.Ya) >= 0 || | |
Math.abs(p1.Za - p2.Za) > 0.00001 && (p1.Za - p4.Za) * (p4.Za - p2.Za) >= 0) | |
p = p4; | |
else | |
p = p2; | |
var distance = google.maps.geometry.spherical.computeDistanceBetween( | |
latLng, p); | |
if (distance < minDistance) | |
{ | |
minDistance = distance; | |
minDistanceLatLng = p; | |
} | |
} | |
return minDistanceLatLng; | |
}; | |
function onMapClick(event) { | |
if (drawMode == 's') | |
{ | |
actionList.do(new wb.DrawBusStop(event.latLng)); | |
return; | |
} | |
if (drawMode == 'r') | |
{ | |
if (startPoint == null) | |
{ | |
actionList.do(new wb.DrawStartPoint(event.latLng)); | |
} | |
else | |
{ | |
var request = { | |
origin: startPoint, | |
destination: event.latLng, | |
travelMode: google.maps.DirectionsTravelMode.DRIVING | |
}; | |
if (segments.length == 0) | |
{ | |
request.origin = startPoint; | |
} | |
else | |
{ | |
var s = segments[segments.length - 1]; | |
request.origin = s[s.length - 1]; | |
} | |
directionsService.route(request, onRouteResult); | |
} | |
} | |
} | |
function onRouteResult(response, status) { | |
if (status != google.maps.DirectionsStatus.OK) | |
return; | |
var segment = []; | |
var legs = response.routes[0].legs; | |
if (legs.length == 0) | |
return; | |
var steps = legs[0].steps; | |
for (var step = 0; step < steps.length; step++) | |
{ | |
path = steps[step].path; | |
for (p = 0; p < path.length; p++) | |
{ | |
if (step == 0 || p > 0) | |
segment.push(path[p]); | |
} | |
} | |
if (segment.length > 0) | |
actionList.do(new wb.DrawRouteSegment(segment)); | |
}; | |
google.maps.event.addDomListener(window, 'load', initialize); | |
google.maps.event.addDomListener(window, 'keypress', keypress); | |
</script> | |
</head> | |
<body> | |
<div id="map_canvas" style="width:100%; height:100%"></div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment