Create elevation profile from GeoJson feature - javascript

I have a map which contains a GeoJson file with lines, displaying some trails. Is it possible to use Google Maps API Elevation Service to create elevation profiles for every feature line of the GeoJson file? I want the elevation profile to be displayed when I click one of the lines.
Something like this example: http://www.trailforks.com/region/la-bouilladisse/
My code, until now, looks like this:
google.load("visualization", "1", {packages: ["columnchart"]});
function initialize() {
var options = {
center: new google.maps.LatLng(44.701991, 22.624884),
zoom: 12,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById("map"), options);
trasee = new google.maps.Data()
trasee.loadGeoJson('http://googledrive.com/host/0B55_4P6vMjhITEU4Ym9iVG8yZUU/trasee.geojson')
trasee.setMap(map)
styling = (function(feature) {
var clasificare = feature.getProperty('Tip_drum');
var culoare;
if (clasificare == ('Poteca'))
(culoare = 'brown')
else if (clasificare == ('Drum forestier'))
(culoare = 'green')
else if (clasificare == ('Drum comunal (neasfaltat)'))
(culoare = 'brown')
else if (clasificare == ('Drum judetean (neasfaltat)'))
(culoare = 'brown')
else if (clasificare == ('Drum comunal (asfaltat)'))
(culoare = 'gray')
else if (clasificare == ('Drum judetean (asfaltat)'))
(culoare = 'gray')
else
(culoare = 'black')
return ({
strokeColor: culoare,
strokeWeight: 3
})
})
trasee.setStyle(styling)
elevator = new google.maps.ElevationService();
}
I know that I have to make a request like this:
var pathRequest = {
'path': source of latlng for creating the path
'samples': 256
}
So basically, I think that the GeoJson must be added somewhere in the pathRequest, but I don't know how, and how to create a different elevation plot for every feature in my GeoJson file.
fiddle of existing code
OK, so now I try to display the elevation charts along with the Tip_drum attribute in infowindows, when I click the data. I added this code:
map.data.addListener('click', function (event) {
document.getElementById('info').innerHTML = event.feature.getProperty('Tip_drum')
var content = document.createElement('div')
var elevations = document.getElementById('elevation_chart')
var types = document.getElementById('info')
content.appendChild(elevations)
content.appendChild(types)
infowindow.setContent(content)
infowindow.setPosition(event.latLng)
infowindow.setMap(map)
if (event.feature.getGeometry().getType() === 'LineString') {
drawPath(event.feature.getGeometry().getArray());
Everything works fine, until I manually close one of the infowindows. After that, the infowindows won't appear anymore.

get the path from the clicked feature (event.feature.getGeometry().getArray())
pass it to the elevation service (like the example in the elevations service documentation)
plot the returned data on a chart (like the example in the elevations service documentation)
remove the code from the Google elevation service example that creates a blue polyline over the polylines from the data layer.
(note that some of the above didn't work with your existing code, I modified it slightly to match the working examples in the documentation)
working fiddle
var elevator;
var map;
var chart;
var polyline;
// Load the Visualization API and the columnchart package.
google.load('visualization', '1', {
packages: ['columnchart']
});
function initialize() {
var options = {
center: new google.maps.LatLng(44.701991, 22.624884),
zoom: 12,
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById("map"), options);
trasee = new google.maps.Data();
map.data.loadGeoJson('http://googledrive.com/host/0B55_4P6vMjhITEU4Ym9iVG8yZUU/trasee.geojson');
// trasee.setMap(map);
styling = (function (feature) {
var clasificare = feature.getProperty('Tip_drum');
var culoare;
if (clasificare == ('Poteca'))
(culoare = 'brown');
else if (clasificare == ('Drum forestier'))
(culoare = 'green');
else if (clasificare == ('Drum comunal (neasfaltat)'))
(culoare = 'brown');
else if (clasificare == ('Drum judetean (neasfaltat)'))
(culoare = 'brown');
else if (clasificare == ('Drum comunal (asfaltat)'))
(culoare = 'gray');
else if (clasificare == ('Drum judetean (asfaltat)'))
(culoare = 'gray');
else(culoare = 'black');
return ({
strokeColor: culoare,
strokeWeight: 3
});
});
map.data.setStyle(styling);
// Set mouseover event for each feature.
map.data.addListener('click', function (event) {
document.getElementById('info').innerHTML = event.feature.getProperty('Tip_drum');
if (event.feature.getGeometry().getType() === 'LineString') {
drawPath(event.feature.getGeometry().getArray());
// calculate the directions once both origin and destination are set
// calculate();
}
});
// When the user hovers, tempt them to click by outlining the letters.
// Call revertStyle() to remove all overrides. This will use the style rules
// defined in the function passed to setStyle()
map.data.addListener('mouseover', function(event) {
map.data.revertStyle();
map.data.overrideStyle(event.feature, {strokeWeight: 8, strokeColor: 'blue'});
});
map.data.addListener('mouseout', function(event) {
map.data.revertStyle();
});
elevator = new google.maps.ElevationService();
// Draw the path, using the Visualization API and the Elevation service.
// drawPath();
}
function drawPath(path) {
// Create a new chart in the elevation_chart DIV.
chart = new google.visualization.ColumnChart(document.getElementById('elevation_chart'));
// Create a PathElevationRequest object using this array.
// Ask for 256 samples along that path.
var pathRequest = {
'path': path,
'samples': 256
};
// Initiate the path request.
elevator.getElevationAlongPath(pathRequest, plotElevation);
}
// Takes an array of ElevationResult objects, draws the path on the map
// and plots the elevation profile on a Visualization API ColumnChart.
function plotElevation(results, status) {
if (status != google.maps.ElevationStatus.OK) {
return;
}
var elevations = results;
// Extract the elevation samples from the returned results
// and store them in an array of LatLngs.
var elevationPath = [];
for (var i = 0; i < results.length; i++) {
elevationPath.push(elevations[i].location);
}
// Extract the data from which to populate the chart.
// Because the samples are equidistant, the 'Sample'
// column here does double duty as distance along the
// X axis.
var data = new google.visualization.DataTable();
data.addColumn('string', 'Sample');
data.addColumn('number', 'Elevation');
for (var i = 0; i < results.length; i++) {
data.addRow(['', elevations[i].elevation]);
}
// Draw the chart using the data within its DIV.
document.getElementById('elevation_chart').style.display = 'block';
chart.draw(data, {
height: 150,
legend: 'none',
titleY: 'Elevation (m)'
});
}
google.maps.event.addDomListener(window, 'load', initialize);

Related

Bing Maps v8 API - Zoom Level to show route and pushpin location

I am using the Bing Maps v8 API. I have a map that shows a driving route, and a pushpin of another location. I need to get the map to zoom out to show both the waypoint locations and the pushpin location. Right now, I can get the map to zoom to the waypoints of the pushpin location.
I am not sure how to get both to show on the map zoom. I know that I need to use the LocationRect class.
var searchManager;
var startingPoint = document.getElementById('startPoint').value;
var address = $("#addressLine").val();
var loc;
var patAddLoc;
var waypointLoc;
var pinsLocs = [];
// GET ROUTE BASED ON DIRECTION
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
//BING API KEY VIA AZURE
credentials: 'X',
zoom: 10,
});
// geocode patient address
geocodeQuery(address);
// look for patient address
function geocodeQuery(query) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
var pin = new Microsoft.Maps.Pushpin(r.results[0].location);
// get patient address location
patAddLoc = r.results[0].location;
map.entities.push(pin);
// add patient location to pushpin array
pinsLocs.push(patAddLoc);
// view is set with route location
//map.setView({ bounds: r.results[0].bestView });
}
// directions manager
// addWaypoint
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function addWaypoint() {
var directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
// if less than 2 point on the map
if (directionsManager.getAllWaypoints().length < 2) {
directionsManager.clearAll();
var startWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('startPoint').value });
directionsManager.addWaypoint(startWaypoint);
var endWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('endPoint').value });
directionsManager.addWaypoint(endWaypoint);
}
// Insert a waypoint
if (document.getElementById('wayPoints').value !== null) {
var addressList = JSON.parse(document.getElementById('wayPoints').value);
var arrayLength = addressList.length;
// insert waypoints from schedule
for (var i = 0; i < arrayLength; i++) {
//alert(addressList[i]);
var hvaddress = addressList[i];
var newWP = new Microsoft.Maps.Directions.Waypoint({ address: hvaddress });
directionsManager.addWaypoint(newWP, 1);
}
}
// Set the element in which the itinerary will be rendered - set autoupdatemapview to false to override autozoom to route
directionsManager.setRenderOptions({ itineraryContainer: document.getElementById('printoutPanel'), autoUpdateMapView: false });
directionsManager.calculateDirections();
var allWaypoints = directionsManager.getAllWaypoints();
// add way point to pinsLocs array
for (var i = 0; i < allWaypoints.length; i++) {
// returns nulls
alert(allWaypoints);
loc = allWaypoints[i].getLocation();
var showMeLoc = loc;
// showMeLoc = undefined.....?
alert(showMeLoc);
pinsLocs.push(loc);
}
// only the address search location is added to the array, waypoint locations are null
alert(pinsLocs);
//Create a LocationRect from array of locations and set the map view.
map.setView({
bounds: Microsoft.Maps.LocationRect.fromLocations(pinsLocs),
padding: 100 //Add a padding to buffer map to account for pushpin pixel dimensions
});
});
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}
}
UPDATE - HERE is the working code for those who have the same question!
var searchManager;
var startingPoint = document.getElementById('startPoint').value;
var address = $("#addressLine").val();
var patAddLoc;
// GET ROUTE BASED ON DIRECTION
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
//BING API KEY VIA AZURE
credentials: 'XXXXX',
zoom: 10,
});
// geocode patient address
geocodeQuery(address);
// look for patient address
function geocodeQuery(query) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
locs = [];
var pin = new Microsoft.Maps.Pushpin(r.results[0].location);
// get patient address location
patAddLoc = r.results[0].location;
map.entities.push(pin);
// add patient location to pushpin array
locs.push(r.results[0].location);
// view is set with route location
//map.setView({ bounds: r.results[0].bestView });
}
// directions manager
// addWaypoint
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function addWaypoint() {
var directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
// if less than 2 point on the map
if (directionsManager.getAllWaypoints().length < 2) {
directionsManager.clearAll();
var startWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('startPoint').value });
directionsManager.addWaypoint(startWaypoint);
var endWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('endPoint').value });
directionsManager.addWaypoint(endWaypoint);
}
// Insert a waypoint
if (document.getElementById('wayPoints').value !== null) {
var addressList = JSON.parse(document.getElementById('wayPoints').value);
var arrayLength = addressList.length;
// insert waypoints from schedule
for (var i = 0; i < arrayLength; i++) {
//alert(addressList[i]);
var hvaddress = addressList[i];
var newWP = new Microsoft.Maps.Directions.Waypoint({ address: hvaddress });
directionsManager.addWaypoint(newWP, 1);
}
}
// Set the element in which the itinerary will be rendered - set autoupdatemapview to false to override autozoom to route
directionsManager.setRenderOptions({ itineraryContainer: document.getElementById('printoutPanel'), autoUpdateMapView: false });
//Add event handlers to directions manager.
Microsoft.Maps.Events.addHandler(directionsManager, 'directionsError', directionsError);
Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', directionsUpdated);
// Calculate directions, which displays a route on the map
directionsManager.calculateDirections();
// get route boundaries
function directionsUpdated(e) {
//Get the current route index.
var routeIdx = directionsManager.getRequestOptions().routeIndex;
// get northeast bounding box corner
var bBoxNE = e.routeSummary[routeIdx].northEast;
locs.push(bBoxNE);
// get southwest bounding box corner
var bBoxSW = e.routeSummary[routeIdx].southWest;
locs.push(bBoxSW);
//SET MAP VIEW
//Create a LocationRect from array of locations and set the map view.
map.setView({
bounds: Microsoft.Maps.LocationRect.fromLocations(locs),
padding: 50 //Add a padding to buffer map to account for pushpin pixel dimensions
});
}
function directionsError(e) {
alert('Error: ' + e.message + '\r\nResponse Code: ' + e.responseCode)
}
});
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}
}
If I understand correctly, you want a view that the entirety of the route and the extra location are visible?
How about using directionsManager.getCurrentRoute().routePath to get all the locations on the route, and then using LocationRect.fromLocations(), which can take in an array of locations - in your case all locations of above plus the additional one.
Note that calculateDirections and geocode and asynchronous, so you may want to handle the dependency on patAddLoc (e.g. move the directions code into the geocode callback).
Reference:
https://msdn.microsoft.com/en-us/library/mt750375.aspx
https://msdn.microsoft.com/en-us/library/mt750645.aspx
https://msdn.microsoft.com/en-us/library/mt712644.aspx

Speed up Google Map

I have a asp.net 4.0 page that loads a Google map, with over 6,000 markers (and growing!)
I am loading the markers from my SQL DB, using a repeater control in the javascript like in this [this example:] (http://www.aspsnippets.com/Articles/ASPNet-Populate-Google-Maps-V3-with-Multiple-Markers-using-Address-Latitude-and-Longitude-values-stored-in-database.aspx)
I have already added marker clustering and done everything I can think of to speed it up.
Some of the markers are added during the initial load, but are not displayed on the map until the user zooms in. (via height:1 width:1 for the cluster icon)
Here is what I want to do, but I'm not sure if it is possible. I want to have my vb codebehind/asp:Repeater load the markers that will display initially. Then in the "Idle" listner, have it load the other markers so that they are ready once the map is zoomed in.
BUT, I can't figure out how to accomplish this. Any ideas?
Here is the bulk of the javascript:
// configure options
var map;
var locations = new Array();
var markers = new Array();
var markerCluster1 = null;
var markerCluster2 = null;
var markerCluster3 = null;
var markerCluster4 = null;
var Style1 = [{url: '../images/m1.png',
height: 48,
width: 48
}];
var Style2 = [{url: '../images/m2.png',
height: 48,
width: 48
}];
var Style3 = [{url: '../images/m3.png',
height: 48,
width: 48
}];
var Style4 = [{url: '../images/m4.png',
textSize: 1,
height: 1,
width: 1
}];
var mcOA1 = {gridSize: 50, maxZoom: 10, styles: Style1};
var mcOA2 = {gridSize: 50, maxZoom: 10, styles: Style2};
var mcOA3 = {gridSize: 50, maxZoom: 10, styles: Style3};
var mcOA4 = {gridSize: 300, maxZoom: 9, styles: Style4, minimumClusterSize: 2};
var infoWindow = new google.maps.InfoWindow();
<asp:Repeater ID="rptMarkers" runat="server" EnableViewState = false>
<ItemTemplate>locations[<%# Eval("i")%>]=new Array(),locations[<%# Eval("i")%>][0]='<%# Eval("PType")%>',locations[<%# Eval("i")%>][1]='<%# Eval("Lat")%>',locations[<%# Eval("i")%>][2]='<%# Eval("Lon")%>',locations[<%# Eval("i")%>][3]='<div class=\"info-window\"><%# Eval("MDesc")%></div>',locations[<%# Eval("i")%>][4]='<%# Eval("Name") %>';
</ItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
function initialize() {
var myOptions =
<asp:Repeater ID="MapOptions" runat="server">
<ItemTemplate>
{
center: new google.maps.LatLng(<%# Eval("center")%>),
zoom: <%# Eval("zoom")%>,
streetViewControl: false,
mapTypeId: <%# Eval("mapTypeId")%>
}
</ItemTemplate>
</asp:Repeater>
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
for (i = 1; i < locations.length; i++) {
if (typeof(locations[i]) == 'object') {
var icon = "";
switch (locations[i][0]) {
case "A1":
icon = "../images/A13.png";
break;
case "A2":
icon = "../images/A23.png";
break;
case "A3":
icon = "../images/A33.png";
break;
case "A4":
icon="../images/A44.png"
break;
case "Furniture":
icon="../images/Furniture3.png"
break;
case "Property Manager":
icon="../images/PropertyManager3.png"
break;
default:
icon="../images/A13.png"
break;
}
var point = new google.maps.LatLng(locations[i][1], locations[i][2]);
markers[i] = new google.maps.Marker({
position: point,
icon: new google.maps.MarkerImage(icon),
animation: google.maps.Animation.DROP,
title: locations[i][4]
});
markers[i].setMap(map);
google.maps.event.addListener(markers[i], 'click', function() {infoWindow.setContent(locations[i][3]);infoWindow.open(map, markers[i]);});
}
} // for
// check to see which category is selected
var location_selector = document.getElementsByName('loc_sel');
for (var i=0; i < location_selector.length; i++) {
if (location_selector[i].checked) {
var location_type = location_selector[i].value;
}
}
show_markers(location_type);
} // function initialize() {
function show_markers (location_type) {
var temp_markers1 = new Array();
var temp_markers2 = new Array();
var temp_markers3 = new Array();
var temp_markers4 = new Array();
// if the markerClusterer object doesn't exist, create it with empty temp_markers
if (markerCluster1 == null) {
markerCluster1 = new MarkerClusterer(map, temp_markers1, mcOA1);
}
if (markerCluster2 == null) {
markerCluster2 = new MarkerClusterer(map, temp_markers1, mcOA2);
}
if (markerCluster3 == null) {
markerCluster3 = new MarkerClusterer(map, temp_markers1, mcOA3);
}
if (markerCluster4 == null) {
markerCluster4 = new MarkerClusterer(map, temp_markers1, mcOA4);
}
// clear all markers
markerCluster1.clearMarkers();
markerCluster2.clearMarkers();
markerCluster3.clearMarkers();
markerCluster4.clearMarkers();
// iterate through all locations, setting only those in the selected category
for (i = 1; i < locations.length; i++) {
if (typeof(locations[i]) == 'object') {
if (locations[i][0] == location_type) {
markers[i].setVisible(true);
if (locations[i][0] == "A1") {temp_markers1.push(markers[i]);}
if (locations[i][0] == "A2") {temp_markers2.push(markers[i]);}
if (locations[i][0] == "A3") {temp_markers3.push(markers[i]);}
if (locations[i][0] == "A4") {temp_markers4.push(markers[i]);}
} else {
markers[i].setVisible(false);
if (locations[i][0] == "A4") {markers[i].setVisible(true);
temp_markers4.push(markers[i]);}
}
}
} // for
// add all current markers to cluster
markerCluster1.addMarkers(temp_markers1);
markerCluster2.addMarkers(temp_markers2);
markerCluster3.addMarkers(temp_markers3);
markerCluster4.addMarkers(temp_markers4);
} // function show_markers
Thank you all!
One probable solution to this problem may be to fire a query to the SQL DB to fetch all the markers when the map is in the idle state.
google.maps.event.addListener(map, 'idle', function() {
fetchMarkersfromDB();
});
And in the initialize() function pass both this listener and also the showMarker() function call. So that whenever the maps are initialized and displayed the markers at current zoom position would be displaced and during the idle phase the query in the backgroud would fetch remaining markers that can be shown in the next or consequent zoom levels. This way the markers would be ready and performance will be better.
Hope this would help!!

Remove markers out of viewport

I have to manage a map of about 80.000 markers concentrated in France.
To do that, I decided to get the bounds of the viewport and call a dynamic-JSON (with PHP) which contains the markers inside the viewport. And this on the "idle" event.
I faced a problem with this solution. Indeed, the markers which already exist was re-plotted (at the same position), which consequently weigh the map for nothing...
To solve it, the markers list before and after the JSON query are compared (thanks to jQuery), in order to plot only the new markers. And it works!
Now, I would want to remove the markers which are not currently shown on the map. Or a list of markers (I get it thanks to jQuery) designated by an ID which is also the title of the marker. So, how can a delete markers like that ? I specify that I am using MarkerManager.
Otherwise, you guess that if I do not remove these markers, they will be re-plotted in some cases... For example, you are viewing the city A, you move the map to view the city B, and you get back to the city A...
Here is the code:
var map;
var mgr;
var markers = [];
function initialize(){
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(46.679594, 2.109375)
};
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: false };
mgr = new MarkerManager(map, mgrOptions);
google.maps.event.addListener(map, 'idle', function() {
mapEvent();
});
}
function mapEvent(){
if( map.getZoom() >= 8 ){
var bounds = map.getBounds();
getSupports(bounds.getNorthEast(), bounds.getSouthWest());
} else {
// Todo
}
}
var markerslistID = new Array();
var markerslistData = {};
function getSupports(ne, sw){
newMarkerslistID = new Array();
newMarkerslistData = {};
// Getting the markers of the current view
$.getJSON('./markerslist.php?nelat='+ne.lat()+'&nelng='+ne.lng()+'&swlat='+sw.lat()+'&swlng='+sw.lng(), function(data) {
for (var i = 0; i < data.points.length; i++) {
var val = data.points[i];
newMarkerslistID.push(val.id);
newMarkerslistData[val.id] = new Array(val.lat, val.lng, val.icon);
}
// List of New Markers TO PLOT
var diffNewMarkers = $(newMarkerslistID).not(markerslistID).get();
// List of Old markers TO REMOVE
var diffOldMarkers = $(markerslistID).not(newMarkerslistID).get();
// Plotting the NEW MARKERS
for( var i = 0; i < diffNewMarkers.length; i++ ){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(newMarkerslistData[diffNewMarkers[i]][0], newMarkerslistData[diffNewMarkers[i]][1]),
title : diffNewMarkers[i],
icon : './images/'+newMarkerslistData[diffNewMarkers[i]][2]+'.png'
});
mgr.addMarker(marker, 0);
}
/*****************************************
HERE WE HAVE TO REMOVE
THE MARKERS CONTAINED IN diffOldMarkers
*****************************************/
mgr.refresh();
// Switching the new list to the old, for the next event
markerslistID = newMarkerslistID;
markerslistData = newMarkerslistData;
});
}
Thank you for your help.
A one-liner to hide all markers that ar not in the current viewport.
!map.getBounds().contains(marker.getPosition()) && marker.setVisible(false);
Or,
if (map.getBounds().contains(marker.getPosition()) && !marker.getVisible()) {
marker.setVisible(true);
}
else if (!map.getBounds().contains(marker.getPosition()) && marker.getVisible()) {
marker.setVisible(false);
}

google maps v3: Invalid value for constructor parameter 0 while drawing polylines

I have a problem when constructing a polygon. The error message says something like:
Invalid value for constructor parameter 0: (49.27862248020283, -122.79301448410035),(49.277964542440955, -122.79370112960816),(49.278524490028595, -122.7950207764435)
It must be something ridiculously simple, but I just can't see it. Any tips you have are useful.
I'm basically painting a map inside an iframe on a modal window (with wicket). Everything is ok, but when I'm trying show a polygon (the points are loaded from a database and sent by webservice) I get the error message.
iframe code: (only the relevant)
/**
* Draws the polygon.
*/
function drawPolygon() {
if (order >= 3) {
deleteMarkers();
// Construct the polygon
// Note that we don't specify an array or arrays, but instead just
// a simple array of LatLngs in the paths property
polygonObject = new google.maps.Polygon({
paths: polygonCoords,
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35
});
polygonObject.setMap(map);
isPolygonDrawed = true;
//After we create the polygon send the points to wicket
parent.sendPoints();
//Change the message on the top label
controlText.style.color = '#ADAAAA';
controlText.innerHTML = polygonCreated;
//With this we make sure no other markers are created after the polygon is drawed.
//Is assigned (order - 1) because when this code is called the order has already been added 1.
MAX_POLYGON_VERTEX = order - 1;
//Disable the create polygon button.
enable = false;
createControlText.style.color = '#ADAAAA';
}
else alert(alertMessage);
}
Now the code on the parent (the modal window)
/**
* Show the polygon on map.
*/
function showPolygon(zoneId) {
var url = applicationRootUrl + 'zonePointsOnMap?zoneId=' + zoneId;
$.getJSON(url, function(data) {
if(data.length == 0) {
return false;
}
frames['zoneMapIFrame'].order = parseInt(data.length);
alert(data.length);
$.each(data, function(i, item) {
if(item != null) {
if(item.latitude != null && item.longitude != null) {
var lat = parseFloat(item.latitude);
var lng = parseFloat(item.longitude);
var latlng = new google.maps.LatLng(lat, lng);
var pointOrder = item.order;
frames['zoneMapIFrame'].polygonCoords[pointOrder] = latlng;
alert(item.order + " point " + latlng);
frames['zoneMapIFrame'].bounds.extend(latlng);
}
}
});
});
setTimeout("frames['zoneMapIFrame'].drawPolygon()", 200);
setTimeout("frames['zoneMapIFrame'].fitMapZoomPolygon()", 300);
}
I can see that the points are loaded ok with alerts, but I keep getting the error message.
Help me!
I was having the same problem.
Don't know if its the best solution, probably not, but it worked for me.
The problem was that the Latlng weren't being recognized. So I recreated the array.
var lats = [];
var lat_size = steps[step].lat_lngs.length;
for (var t=0; t <lat_size; t++) {
lats.push(new google.maps.LatLng(steps[step].lat_lngs[t].lat(), steps[step].lat_lngs[t].lng()))
}
var polylineOptions = {
map: map,
path: lats
}
new google.maps.Polyline(polylineOptions);

Google map with route-trace loading data instead of adding it on click

In this map
http://econym.org.uk/gmap/example_snappath.htm
source:
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(53.7877, -2.9832),13)
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
var dirn = new GDirections();
var firstpoint = true;
var gmarkers = [];
var gpolys = [];
var dist = 0;
GEvent.addListener(map, "click", function(overlay,point) {
// == When the user clicks on a the map, get directiobns from that point to itself ==
if (!overlay) {
if (firstpoint) {
dirn.loadFromWaypoints([point.toUrlValue(6),point.toUrlValue(6)],{getPolyline:true});
} else {
dirn.loadFromWaypoints([gmarkers[gmarkers.length-1].getPoint(),point.toUrlValue(6)],{getPolyline:true});
}
}
});
// == when the load event completes, plot the point on the street ==
GEvent.addListener(dirn,"load", function() {
// snap to last vertex in the polyline
var n = dirn.getPolyline().getVertexCount();
var p=dirn.getPolyline().getVertex(n-1);
var marker=new GMarker(p);
map.addOverlay(marker);
// store the details
gmarkers.push(marker);
if (!firstpoint) {
map.addOverlay(dirn.getPolyline());
gpolys.push(dirn.getPolyline());
dist += dirn.getPolyline().Distance();
document.getElementById("distance").innerHTML="Path length: "+(dist/1000).toFixed(2)+" km. "+(dist/1609.344).toFixed(2)+" miles.";
}
firstpoint = false;
});
GEvent.addListener(dirn,"error", function() {
GLog.write("Failed: "+dirn.getStatus().code);
});
}
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
//]]>
</script>
You can click and add paths that trace routes.
I would like to use the trace-road-functionality, but pre-define the data using coordinates instead. How would I do this?

Categories

Resources