Launch Safari browser with StreetView for a given latitude longitude - google-maps

I would like to launch Google StreetView in the Safari browser from my native iOS app. I have the street address and latitude longitude available. I know it is relatively easy to find panorama ID using an API, but unfortunately I can't use any Google API. I need to launch the google maps website outside of my app with the given address or latitude longitude.
The url for street view (for 40.535673,-74.209823) on desktop looks something like this:
https://www.google.com/maps?es_sm=91&um=1&ie=UTF-8&q=719+Ramona+ave+new+york&layer=c&z=17&iwloc=A&sll=40.535673,-74.209823&cbp=13,354.4,0,0,0&cbll=40.535462,-74.209796&sa=X&ei=BMdjVIaPMIn5yASA64Jw&ved=0CCAQxB0wAA
How can construct this url without using any Google Maps API? If I simply try to replace the latitude longitude above the street view ends up facing in the incorrect direction. Any way to get the heading just right?

The way I solved this was to first call the following API to get a panoId and best_view_direction_deg. Here's an example url for that API:
http://maps.google.com/cbk?output=json&ll=40.766200,-73.982500
Here's a piece of ObjC code I used to convert the pano ID and direction into a url:
+ (NSString *)bestStreetViewWebUrlForCoordinate:(CLLocationCoordinate2D)coordinate panoId:(NSString *)panoId bestViewDirectionDeg:(NSString *)bestViewDirectionDeg
{
NSString *streetViewUrlString = nil;
if (panoId != nil)
{
streetViewUrlString = [NSString stringWithFormat:#"https://maps.gstatic.com/m/streetview/?panoid=%#&cbp=0,%#,0,0,0", panoId, bestViewDirectionDeg];
}
else
{
streetViewUrlString = [NSString stringWithFormat:#"https://maps.gstatic.com/m/streetview/?q=&layer=c&cbll=%f,%f&cbp=11,0,0,0,0&output=classic&dg=brw",coordinate.latitude, coordinate.longitude];
}
return streetViewUrlString;
}
Output looks like:
https://maps.gstatic.com/m/streetview/?panoid=fB883QwmW5xNsXRuEHxmHw&cbp=0,207.478,0,0,0

Related

How to extract route GPX from a Google Maps route?

My objective is to extract a route which some user would have created on Google Maps into a GPX file containing latitude longitudes for further use in other apps.
The route will be shared via a link like this - https://goo.gl/maps/HcikiDXFwN2coeFN8
Interestingly, this app is already doing what I want to do - https://mapstogpx.com/ and https://www.gpsvisualizer.com/convert_input?convert_format=gpx. I just want to know how they are doing it so that I can emulate it for my own needs.
Since both the tools I've mentioned also require providing a Google Maps API key with the directions API enabled, my initial guess is that these tools first parse the webpage for the waypoints and then use those waypoints in a Directions API call to get all the route trackpoints.
Thanks
The solution lies in the "data" param in the expanded url for the google maps route link.
Lets take this URL for example - https://goo.gl/maps/zrcP5gL1cd2AHGoq8
This expands to https://www.google.com/maps/dir/Eiffel+Tower,+Paris,+France/Palais+Garnier,+Pl.+de+l'Op%C3%A9ra,+75009+Paris,+France/#48.8606129,2.2961092,14z/am=t/data=!4m29!4m28!1m20!1m1!1s0x47e6701f7e8337b5:0xa2cb58dd28914524!2m2!1d2.2930458!2d48.8560934!3m4!1m2!1d2.3122286!2d48.8490916!3s0x47e6702fa62d0bc5:0xd2d94ed604f2e5a0!3m4!1m2!1d2.3035972!2d48.8729816!3s0x47e66fc1755cf609:0x3c5040f902b41a5f!3m4!1m2!1d2.3235117!2d48.8581242!3s0x47e66e2ac3bca3ed:0x1c289763e3096e61!1m5!1m1!1s0x47e66e30d4668339:0xa9abf21c286d0767!2m2!1d2.3316014!2d48.8719697!3e0
On closer examination, you will see that the data param has lat-lng coordinates embedded in it. For example this
!1d2.2930458!2d48.8560934 or !1d2.3122286!2d48.8490916. These are longitude latitude pairs representing various waypoints on the route. The longitude always starts with !1d and ends with !2d and the latitude starts with !2d and ends with !3.
Here is a small kotlin method to extract all the coordinates :
//https://stackoverflow.com/a/62191093/3090120
fun String?.indexesOf(pat: String, ignoreCase: Boolean = true): List<Int> =
pat.toRegex(if (ignoreCase) setOf(RegexOption.IGNORE_CASE) else emptySet())
.findAll(this ?: "")
.map { it.range.first }
.toList()
fun extractCoordinates(expandedUrl: String): List<LatLng> {
val latLngList = arrayListOf<LatLng>()
val indexes = expandedUrl.indexesOf("!1d")
indexes.forEach {
val coordinatesStr = expandedUrl.substring(it + 3).substringBefore("!3").split("!2d")
latLngList.add(LatLng(coordinatesStr[1].toDouble(), coordinatesStr[0].toDouble()))
}
return latLngList
}
The result with this string would be
[lat/lng: (48.8560934,2.2930458), lat/lng: (48.8490916,2.3122286), lat/lng: (48.8729816,2.3035972), lat/lng: (48.8581242,2.3235117), lat/lng: (48.8719697,2.3316014)]
Once we have all the lat-lng pairs we can simply fire off a Google Maps Directions API call and recreate the route in the link and export it as a GPX file.

Google maps destination SwiftUI

I am working on a project where users can add the addresses of their clients. I managed to make these addresses to be interactive so that when you tap on them a sheet shows the option to open either GoogleMaps or Apple Maps. However I am not sure how to set the specific address I tap to be the destination when the map opens. This is what I have:
.actionSheet(isPresented: $showingSheet){
let latitude = 51.49
let longitude = -30
let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
//let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"
let googleItem = ("Google Map", URL(string:googleURL)!)
//let wazeItem = ("Waze", URL(string:wazeURL)!)
var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]
if UIApplication.shared.canOpenURL(googleItem.1) {
installedNavigationApps.append(googleItem)
}
// if UIApplication.shared.canOpenURL(wazeItem.1) {
// installedNavigationApps.append(wazeItem)
// }
var buttons: [ActionSheet.Button] = []
for app in installedNavigationApps {
let button: ActionSheet.Button = .default(Text(app.0)) {
UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
}
buttons.append(button)
}
let cancel: ActionSheet.Button = .cancel()
buttons.append(cancel)
return ActionSheet(title: Text("Navigate"), message: Text("Select an app..."), buttons: buttons)
Any suggestions?
Both Apple Maps and Google Maps have a similar URL scheme for opening their map for driving directions.
Apple Maps reference: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
Google Maps URL scheme for iOS: https://developers.google.com/maps/documentation/urls/ios-urlscheme#directions
In both cases, the daddr value you're passing can be sent a full address, which the Maps product will then geocode and pinpoint.
You're currently sending a stringified version of your lat/lng coordinates in that string, which each maps product can use to derive a location. But there neither scheme seems to support an option of "here are the coordinates I want to use, and this is the address I want to show" – it's one or the other.
So if you take the address you have and enter it as a single string (don't forget to URL encode it – you may find it easiest to assemble your URL using the URLComponents and URLQueryItem helper objects) you ought to be able to use that encoded string as a new daddr value.

Database instead of kml file

I wonder, is it possible to connect a db to google maps api to render polygons, points etc?
If a store all kml coordinates connected to polygons, will it be possible to render it fra database or do i need to create a kml file to visualize it?
Is there any example?
Thanks!
A KML file is not required to visualize points, polygons, etc using Google Maps API. However, the KML layer is a useful way to represent complex geospatial features.
A backend database with HTTP access could return a list of map coordinates that your client code can render into appropriate shapes using Google Maps API.
The Google Maps API provides examples to create various shapes.
Example to create simple point marker:
https://developers.google.com/maps/documentation/javascript/examples/marker-simple
Example to create simple polygon:
https://developers.google.com/maps/documentation/javascript/examples/polygon-simple
The client code will need to query the data from the database such as from a servlet with access to the database. Database will most likely be running on a different port or from a different server so javascript won't be able to access it directly.
Your server-side component could query a database and return formatted KML or it could return a JSON result that your client code would render. Depends on whether you want to write more backend server code or JavaScript code on the client.
hmmm... I am using another solution now (data from DB to show on Google earth which is default application for KML file) and hope this help :
( may refer to https://sites.google.com/site/canadadennischen888/home/kml/auto-refresh-3d-tracking )(plus, in my other page, there is sample java code)
Details as :
prepare a RestFul service to generate KML file from DB (KML sample as inside above link)
My other jsp code will generate a KMZ file which has a link to my Restful service. KMZ file has onInterval ( as in the bottom)
Jsp web page allow user to download KMZ file.
When Google Earth open KMZ file, Google Earth will auto refresh to get new data from that Restful service
Everytime refreshing, server will send the latest update KML data with new data to GE.
KMZ sample:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2"
xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<NetworkLink>
<name>Dennis_Chen_Canada#Hotmail.com</name>
<open>1</open>
<Link>
<href>http://localhost:9080/google-earth-project/rest/kml/10001/20002</href>
<refreshMode>onInterval</refreshMode>
</Link>
</NetworkLink>
</kml>
result as :
Thanks for you're answer. I don't know if i get somewhat wiser of this, but at least i know that it is possible.
I have used Shape2Sql to save the coordinates in the database.
But as i understand, i need someway to convert this to geojson before it can render in Google maps? if i understand correct?
As i understand to render geojson is mostly the same as to render kml when it comes to files. But i don't know how to Connect to a database.
I make a list from database:
var adresses = _unitOfWork.GeoAddressRepository.Get(q => q.GeoRouteNorpost.Code == "3007106", includeProperties: "GeoRouteNorpost").ToList();
var points = new List<LatLong>();
foreach (var address in adresses)
{
points.Add(new LatLng() { Lat = "59.948261", Lng = "10.750699" });
points.Add(new LatLng() { Lat = "59.943128", Lng = "10.755814" });
points.Add(new LatLng() { Lat = "59.941245", Lng = "10.746084" });
points.Add(new LatLng() { Lat = "59.943527", Lng = "10.742786" });
points.Add(new LatLng() { Lat = "59.946824", Lng = "10.744435" });
points.Add(new LatLng() { Lat = "59.946813", Lng = "10.744446" });
points.Add(new LatLng() { Lat = "59.947107", Lng = "10.748241" });
points.Add(new LatLng() { Lat = "59.947827", Lng = "10.749525" });
points.Add(new LatLng() { Lat = "59.948248", Lng = "10.750699" });
}
This example show a polygon on a map. But i'm not sure how to get this coordinates out of the database and how to solve it when it is serveral polygons.
As i have written, i have saved the coordinates in the db With shape2Sql. So now i have a Field for geometry. If i look at the spatial result in sql server this looks correct. But how can i display this in Google maps?
I am grateful for all help:)

Iphone is not able to open link to google maps directions

i have this code:
if(navigator.platform.indexOf("iPhone") != -1 || navigator.platform.indexOf("iPod") != -1 || navigator.platform.indexOf("iPad") != -1) {
window.open("https://maps.google.com?saddr=Current+Location&daddr=" + lat + "," + lon);
}
else {
window.open("https://www.google.com/maps/dir/Current+Location/" + lat + "," + lon);
//window.open("https://maps.google.com?saddr=Current+Location&daddr=" + lat + "," + lon);
}
I know that lon and lat have correct values. it works on all desktop browsers and on an android phone i have tested (gives me the directions), but when i window.open runs on the iphone it loads google maps and it says "route not found"..
is this code not supposed to work on and ios device?
You have two methods to embed Google Maps URL in your iOS app.
Using OpenInGoogleMapsController class.
URL Scheme method.
In the first one it is easy to build links to open a map (or display Street View or directions) directly in Google Maps for iOS. Rather than creating URLs by hand, you can create map requests using Objective-C classes and types, so you can take advantage of all the type-checking and code hinting you've come to expect from Xcode.
For Direction follow this code:
GoogleDirectionsDefinition *defn = [[GoogleDirectionsDefinition alloc] init];
defn.startingPoint =
[GoogleDirectionsWaypoint waypointWithQuery:#"221B Baker Street, London"];
defn.destinationPoint = [GoogleDirectionsWaypoint
waypointWithLocation:CLLocationCoordinate2DMake(51.498511, -0.133091)];
defn.travelMode = kGoogleMapsTravelModeBiking;
[[OpenInGoogleMapsController sharedInstance] openDirections:defn];
To launch the Google Maps app for iOS and optionally perform one of the supported functions, use a URL scheme of the following form:
comgooglemaps://?parameters
Use the Display Direction scheme to request and display directions between two locations. You can also specify the transportation mode.
An example URL is below to display transit directions between Google NYC and JFK Airport:
comgooglemaps://?saddr=Google+Inc,+8th+Avenue,+New+York,+NY&daddr=John+F.+Kennedy+International+Airport,+Van+Wyck+Expressway,+Jamaica,+New+York&directionsmode=transit
Hope tat Helps!!

Cannot find POI via google-places-api that can be found on google-maps and google-plus

I am trying to find a specific listing via the google-maps-places API, but I don't get any results. This is strange to me, as there is a Google+ page and also a google-maps entry.
Let's take a look at the links:
Google+:
https://plus.google.com/115673722468988785755/about
Maps:
https://www.google.de/maps/place/AMWAY+Beratung+%26+Vertrieb+Haegebarth/#53.171976,9.465828,17z/data=!3m1!4b1!4m2!3m1!1s0x47b106116fc69d69:0xe17811ab2780c71d
If I use the very same coordinates from the maps entry in my nearby search and use the name from the entry as the keyword (or location for what it's worth) the results is empty.
Places-API (with exact same coordinates):
https://maps.googleapis.com/maps/api/place/nearbysearch/json?sensor=false&radius=2000&name=amway&location=53.171976,9.465828&language=de-DE&key=YOURKEY
I can of course imagine that the db for the Google+ POIs is a different one. But then again I don't see how the maps api does not find what I can find on the maps web app.
Thanks a lot for any help!
Try something like this:
map.places.nearbySearch({
location: latLng,
rankBy: google.maps.places.RankBy.DISTANCE,
types: ['shop'], // optional
name: "AMWAY Beratung & Vertrieb Haegebarth" // optional
},function(results, status){
if (status == google.maps.places.PlacesServiceStatus.OK) {
// The thing you need should be result[0]
// console.log(results[0]);
if (results[0].name == "AMWAY Beratung & Vertrieb Haegebarth") { // optionally check the type
// You have your place :)
}
}
}
What a workaround! Rumours are that the Google Maps JS API v3.20 or later will allow us to trigger click events on POIs, thereby getting Place objects directly.