I am using HERE maps to calculate routes but I use Google maps to display the route. In v7 getRoutingService used to return
result.response.route[0].shape
which is an array of coordinates which I pass to google services to draw it on map.
Here is how it looks in V7:
var router = hServicePlatform.getRoutingService();
router.calculateRoute(
routingParameters,
function (result, err_extras) {
const routeShape = result.response.route[0].shape; // coordinates array
show_routePolyline(routeShape); // this draws the polyline on Google maps
}
);
Using HERE v8, getRoutingService doesnt seem to return any coordinates at all. Is there a way to get the coordinates in V8?
An encrypted polyline can be returned using the polyline function however this then needs to be decoded to output meaningful co-ordinates.
Referenced in the Migration guide here.
https://developer.here.com/documentation/routing-api/migration_guide/index.html
Is there any way to put the longitude and latitude from a passed URL into a marker. So essentially a user would copy and paste the 'Share' URL from Google maps.
E.G. Places: https://www.google.co.nz/maps/place/The+White+House/#38.8976763,-77.0387238,17z/data=!3m1!4b1!4m5!3m4!1s0x89b7b7bcdecbb1df:0x715969d86d0b76bf!8m2!3d38.8976763!4d-77.0365298?hl=en
or Direct Location:
https://www.google.co.nz/maps/place/38%C2%B054'53.8%22N+77%C2%B006'01.6%22W/#38.914936,-77.102638,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d38.914936!4d-77.100444?hl=en
I would like the initialisation code create a marker at that shared URL location.
So far from other question's I've seen the use of GeoCode API but I'm not sure how the example URL's above can be parsed and the data extracted in JS. Any examples of Ajax calls to API or something like this being done would be appreciated.
The URLs contain the latitude and longitude, so you can extract them easily. Calling putMarkerAtURLCoordinates(SHARED_URL) will place a marker at the coordinates of the url assuming your google maps instance is called "map".
function putMarkerAtURLCoordinates(url){
//get the latlng object from url
var myLatLng = getLatLngFromURL(url)
//create the marker and assign it to the map
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'Marker title here'
});
}
function getLatLngFromURL(url){
//decode url incase its urlencoded
url = decodeURIComponent(url)
//find index of # character
var atindex = url.indexOf("#")
//cut off the part before the # and split the rest up by the comma separator
var urlparts = url.slice(atindex+1).split(",")
//parse the values as floats
var lat = parseFloat(urlparts[0])
var lng = parseFloat(urlparts[1])
//return as object
return {lat:lat,lng:lng}
}
This isn't a stable solution though... If google changes their URL scheme this won't work anymore.
I'm trying to use Maps JavaScript API with response from Google Maps Directions API to display driving routes passing some waypoints.
I wrote this code below to get waypoints' order using Google Maps Directions API, which is working well.
google_directions.rb
def initialize(origin, destination, waypoints, opts=##default_options)
#origin = origin
#destination = destination
#waypoints = 'optimize:true' + waypoints
#options = opts.merge({:origin => #origin, :destination => #destination, :waypoints => #waypoints})
#url = ##base_url + '?' + #options.to_query + '&key=' + Rails.application.secrets.google_maps_api_key
#response = open(#url).read
#jdata = JSON.parse(#response)
#status = #jdata['status']
end
def public_response
#response
end
Now, I get json response(#response) from Google Maps Directions API, so I want to reuse it to display the routes on the google map with Maps JavaScript API.
index.html.erb
<script type="text/javascript">
handler = Gmaps.build('Google');
handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
markers = handler.addMarkers(<%=raw #hash.to_json %>);
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
toRender(<%=raw #response.to_json %>)
});
function toRender(response){
directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setDirections(response);
}
</script>
I'm gessing I should pass #response to directionsDisplay.setDirections() as an argument, but it's not working. Could anyone show me the best way to solve this??
I found this Q&A, which says I need to translate the JavaScript API JSON response into a DirectionsResult object. Does anyone know how to do it??
Displaying results of google direction web service without using javascript api
Here is my Google Maps Directions API response from #url request.
Google Maps Directions API Response
I am trying to fetch the address components using Google Maps APIs.
geocoder = new google.maps.Geocoder();
marker = new google.maps.Marker(...);
geocoder.geocode({'latLng': marker.getPosition()}, function(...);
But for some cases when I drag the marker to point to exact location, I get few parts of address_components in response of GeoCoding API in localised versions even though the map language is set to "en" (English).
Is there any way I can pass in language param while creating Geocoder instance to force it to return address components in english only.
NOTE: I am not using geocoding webservice to get the address_components.
The Google Maps JavaScript version 3 API library documentation clearly explains:
The Google Maps API supports the KML
and GeoRSS data formats for displaying
geographic information. These data
formats are displayed on a map using a
KmlLayer object, whose constructor
takes the URL of a publicly accessible
KML or GeoRSS file.
There are even several Stack Overflow questions about how to load local data:
Loading a local .kml file using google maps?
Google Maps kml files
Some of the answers have pointed to third party libraries which can parse KML locally without the file needing to be public:
geoxml3
GeoXML
EGeoXml
And while these solutions are good if you have a need to keep your data private, I simply want to make development easier. When running locally I obviously cannot parse my KML and therefore lose functionality that I am trying to test. I've posted a single generic KML file on a publicly available site, but then have to have different development code to render one thing vs. something else when running for real.
What are my options for local development to render what would be publicly available dynamically generated KML files?
It seems like you've outlined the options pretty well:
If you want to work with local data, without involving a publicly accessible webserver, you'll need to use a javascript-based approach to parse the KML and load it onto the map. While this won't perfectly replicate the Google functionality, it is likely good enough for initial development if you only care about displaying the KML features. In this case, I'd probably set up a stub class, like this:
// I'll assume you have a global namespace called MyProject
MyProject.LOCAL_KML = true;
MyProject.KmlLayer = function(url) {
// parse the KML, maybe caching an array of markers or polygons,
// using one of the libraries you list in your question
};
// now stub out the methods you care about, based on
// http://code.google.com/apis/maps/documentation/javascript/reference.html#KmlLayer
MyProject.KmlLayer.prototype.setMap = function(map) {
// add the markers and polygons to the map, or remove them if !map
}
// etc
Now either put a switch in the code, or comment/uncomment, or use a build script to switch, or whatever your current process is for switching between dev and production code:
var kmlPath = "/my.kml";
var kmlLayer = MyProject.LOCAL_KML ?
new MyProject.KmlLayer(MyProject.LOCAL_KML_HOST + kmlPath) :
new google.maps.KmlLayer(MyProject.PRODUCTION_KML_HOST + kmlPath);
kmlLayer.setMap(myMap);
If, on the other hand, you need all of the functionality in the Google KmlLayer, or you want to make sure things work with the production setup, or you don't want to bother stubbing out the functionality Google provides, then you'll need to upload it to a publicly available server, so that Google can do its server-side processing.
Aside from the obvious options (FTP, a command-line script to upload your new KML file, etc), most of which require you to do something manually before you load your map page, you might consider building the update into the page you're loading. Depending on the platform you're using, this might be easier to do on the back-end or the front-end; the key would be to have a script on your public server that would allow the KML to be updated:
Get KML string from request.POST
Validate the KML string (just so you aren't opening your server to attacks)
Write to a single file, e.g. "my.kml"
Then, when you view your map page, update the remote KML based on the data from localhost. Here's a client-side version, using jQuery:
// again, you'd probably have a way to kill this block in production
if (MyProject.UPDATE_KML_FROM_LOCALHOST) {
// get localhost KML
$.get(MyProject.LOCAL_KML_HOST + kmlPath, function(data) {
// now post it to the remote server
$.post(
MyProject.DEV_KML_HOST + '/update_kml.php',
{ kml: data },
function() {
// after the post completes, get the KML layer from Google
var kmlLayer new google.maps.KmlLayer(MyProject.DEV_KML_HOST + kmlPath);
kmlLayer.setMap(myMap);
}
);
})
}
Admittedly, there are a lot of round-trips here (page -> localhost, page -> remote server, Google -> remote server, Google -> page), so this is going to be slow. But it would allow you to have Google's code properly render dynamic KML data produced on localhost, without having to take a separate manual step every time you reload the page.
Definitely, Google Maps KmlLayer is designed for you to send your data to them.
https://developers.google.com/maps/documentation/javascript/kml
Have a look the following log.
//console
var src = 'https://developers.google.com/maps/documentation/javascript/examples/kml/westcampus.kml';
var kmlLayer = new google.maps.KmlLayer(src, {
suppressInfoWindows: true,
preserveViewport: false,
map: your_gmap_object
});
Creating Marker, Polygon, they are all browser side parsing and rendering.
As you can see from next network log, KmlLayer class send source URL to Google Server to parse it and (do something in their end) and send the parsed result back to your browser to render.
//REQUEST from browser
https://maps.googleapis.com/maps/api/js/KmlOverlayService.GetOverlays?1shttps%3A%2F%2Fdevelopers.google.com%2Fmaps%2Fdocumentation%2Fjavascript%2Fexamples%2Fkml%2Fwestcampus.kml&callback=_xdc_._lidt3k&key=AIzaSyBeLTP20qMgxsQFz1mwLlzNuhrS5xD_a_U&token=103685
//RESPONSE from google server
/**/_xdc_._lidt3k && _xdc_._lidt3k( [0,"kml:cXOw0bjKUSmlnTN2l67v0Sai6WfXhSSWuyNaDD0mAzh6xfi2fYnBo78Y2Eg","|ks:;dc:tg;ts:51385071|kv:3|api:3",...
["KmlFile"],[[37.423017,-122.0927],[37.424194,-122.091498]],[["g74cf1503d602f2e5"],["g58e8cf8fd6da8d29"],["ge39d22e72437b02e"]],1,[["client","2"]],-21505,[["ks",";dc:tg;ts:51385071"],["kv","3"],["api","3"]]] )
As #capdragon mentioned above, it would be better parse KML by yourself.
UPDATE
Here is compact KML parser code.
This only for google.maps Marker and Polygon.
html
<input type='file' accept=".kml,.kmz" onchange="fileChanged()">
script, I used typescript but it is pretty same with javascript
file: any
fileChanged(e) {
this.file = e.target.files[0]
this.parseDocument(this.file)
}
parseDocument(file) {
let fileReader = new FileReader()
fileReader.onload = async (e: any) => {
let result = await this.extractGoogleCoords(e.target.result)
//CREATE MARKER OR POLYGON WITH result here
console.log(result)
}
fileReader.readAsText(file)
}
async extractGoogleCoords(plainText) {
let parser = new DOMParser()
let xmlDoc = parser.parseFromString(plainText, "text/xml")
let googlePolygons = []
let googleMarkers = []
if (xmlDoc.documentElement.nodeName == "kml") {
for (const item of xmlDoc.getElementsByTagName('Placemark') as any) {
let placeMarkName = item.getElementsByTagName('name')[0].childNodes[0].nodeValue.trim()
let polygons = item.getElementsByTagName('Polygon')
let markers = item.getElementsByTagName('Point')
/** POLYGONS PARSE **/
for (const polygon of polygons) {
let coords = polygon.getElementsByTagName('coordinates')[0].childNodes[0].nodeValue.trim()
let points = coords.split(" ")
let googlePolygonsPaths = []
for (const point of points) {
let coord = point.split(",")
googlePolygonsPaths.push({ lat: +coord[1], lng: +coord[0] })
}
googlePolygons.push(googlePolygonsPaths)
}
/** MARKER PARSE **/
for (const marker of markers) {
var coords = marker.getElementsByTagName('coordinates')[0].childNodes[0].nodeValue.trim()
let coord = coords.split(",")
googleMarkers.push({ lat: +coord[1], lng: +coord[0] })
}
}
} else {
throw "error while parsing"
}
return { markers: googleMarkers, polygons: googlePolygons }
}
output
markers: Array(3)
0: {lat: 37.42390182131783, lng: -122.0914977709329}
...
polygons: Array(1)
0: Array(88)
0: {lat: -37.79825999283025, lng: 144.9165994157198}
...