So, I use the directions API in my app. However, when I decode the polyline from the response, it does not show up correctly. Here is my code:
//Construct request URL
NSString *urlString = [NSString stringWithFormat:
#"%#?origin=%f,%f&destination=%f,%f&sensor=true&key=%#",
#"https://maps.googleapis.com/maps/api/directions/json",
userMarker.position.latitude,
userMarker.position.longitude,
place.coordinate.latitude,
place.coordinate.longitude,
#"AIzaSyDrtHA-AMiVVylUPcp46_Vf1eZJJFBwRCY"];
NSURL *directionsURL = [NSURL URLWithString:urlString];
//Get directions in JSON format
dispatch_async(dispatch_get_main_queue(), ^{
NSData* data = [NSData dataWithContentsOfURL:directionsURL];
NSError* error;
if(data){
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
//Parse JSON and plot route on map
NSDictionary *routes = [json objectForKey:#"routes"][0];
NSDictionary *route = [routes objectForKey:#"overview_polyline"];
NSString *overview_route = [route objectForKey:#"points"];
//Clear map from previous polylines
[self.mapView clear];
//Make polyline
GMSPath *path = [GMSPath pathFromEncodedPath:overview_route];
GMSPolyline *polyline = [GMSPolyline polylineWithPath:path];
polyline.strokeWidth = 4;
polyline.strokeColor = [UIColor darkGrayColor];
polyline.map = self.mapView;
});
And here is the polyline:
As you can,see it does not follow the road properly. However, to me it seems as if there are not enough points to have proper bends.
EDIT: This only happens 50% of the time, sometimes it shows up correctly, sometimes it does not.
What could I be doing wrong?
Going by this (which is using the js API instead of the json API that you're using):
Get a polyline from Google maps directions V3
It looks like you should use the lines in each of the steps of the legs in the response, instead of the overview_polyline which is probably meant to be just a rough approximate line.
Related
I am developing two apps similar to Ola/Uber, a driver app and the other one is a rider app. The driver app uses mapbox for navigation while the rider app uses simple mapkit and google APIs. My problem starts when the driver re-routes while undergoing a ride and the rider app has to trace the driver's new path also. Right now the logic applied is as following: in didRerouteAlongRoute delegate of mapbox the driver app informs the server that it has re-routed along this particular MBRoute route. The server in turn informs and passes this information to the rider app. Problem is that this MBRoute data type is not usable at the rider end as it uses mapkit and not mapbox and I have to convert this information somehow so that I can make the same new route as the driver app using MKPolyline at the rider end. Any help is appreciated.
This api is being used at the rider end for making the route polyline originally: https://maps.googleapis.com/maps/api/directions/json
Finally I managed a way to accomodate the requirements. It includes the following 3 steps:
At the driver app (using the mapbox framework), in the didRerouteAlongRoute delegate, create an array containing the new route's latitude/longitude dictionaries like this:
-(void)navigationViewController:(MBNavigationViewController*)navigationViewController didRerouteAlongRoute:(MBRoute*)route{
CLLocationCoordinate2D *routeCoordinates = malloc(route.coordinateCount *sizeof(CLLocationCoordinate2D));
[route getCoordinates:routeCoordinates];
NSMutableArray *routeArray = [NSMutableArray new];
for (NSValue *value in route.coordinates) {
CLLocationCoordinate2D coordinate;
[value getValue:&coordinate];
NSDictionary *coDic = #{#"latitude" : [NSNumber numberWithDouble: coordinate.latitude],
#"longitude": [NSNumber numberWithDouble: coordinate.longitude]};
[routeArray addObject:coDic];
}
}
Then send this new route's information to the server through an API after serialising this array (reRouteJSONString) as following:
NSError *error;
NSString *reRouteJSONString = #"";
NSData *reRouteJSONData = [NSJSONSerialization dataWithJSONObject: routeArray options:NSJSONWritingPrettyPrinted error:&error];
reRouteJSONString = [[NSString alloc] initWithData: reRouteJSONData encoding:NSUTF8StringEncoding] ;
And now at the rider app, manipulate this information as following and form your new route polyline:
-(void)makeReroutePolyline:(NSString*)serialisedString{
MKMapView *mapView;
mapView.delegate = self;
NSError *jsonError;
NSData *objectData = [serialisedString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *json = [NSJSONSerialization JSONObjectWithData:objectData options:NSJSONReadingMutableContainers error:&jsonError];
CLLocationCoordinate2D coordinates[json.count];
for (NSInteger index = 0; index < json.count; index++) {
CLLocationCoordinate2D coordinate = { [[json objectAtIndex:index][#"latitude"] doubleValue], [[json objectAtIndex:index][#"longitude"] doubleValue] };
coordinates[index] = coordinate;
}
MKPolyline *routeLine;
routeLine = [MKPolyline polylineWithCoordinates:coordinates count:json.count];
[mapView addOverlay:routeLine];
[mapView setVisibleMapRect:[routeLine boundingMapRect] edgePadding:UIEdgeInsetsZero animated:YES];
}
As the question says I am trying to add pins to my map based on the coordinates returned by my php file. Said file returns the following results
[{"dogid":"1","latitude":"15.435786","longitude":"-21.318447"},{"dogid":"1","latitude":"14.00000","longitude":"-18.536711"}]
What I am doing (well I believe i am) is taking the values from the link and saving them to a string. Secondly, save that string value to an array. Then, I go thru this array and save out the latitude and longitude and assign it to CLLocationCordinate 2dcoord. After whch I expect both pins to be dropped on whatever location they received.
However, what occurs is: Upon running the program, when it arrives on this lin
for (NSDictionary *row in locations) {
the loop is not run to assign the values, and it jumps to the end. Oddly, a single pin is dropped on the map (thou location doesnt appear to be the values that it waas passed).
Would appreciate a little incite into the matter.
Thanks
- (void)viewDidAppear:(BOOL)animated
{
NSMutableArray *annotations = [[NSMutableArray alloc] init];
NSURL *myURL =[NSURL URLWithString:#"link.php"];
NSError *error=nil;
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
CLLocationCoordinate2D coord;
NSArray *locations=[NSArray arrayWithContentsOfFile:str];
for (NSDictionary *row in locations) {
NSNumber *latitude = [row objectForKey:#"latitude"];
NSNumber *longitude = [row objectForKey:#"longitude"];
// NSString *title = [row objectForKey:#"title"];
//Create coordinates from the latitude and longitude values
coord.latitude = latitude.doubleValue;
coord.longitude = longitude.doubleValue;
}
MKPointAnnotation *pin = [[MKPointAnnotation alloc] init];
pin.coordinate = coord;
[self.mapView addAnnotation:pin];
}
It looks like you are trying to save api response to and Array.
Api always returns json string which is NSString.
You need to convert decode json string.
In your case
NSString *str=[NSString stringWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:&error];
you need to decode str with [NSJSONSerialization JSONObjectWithData:<#(NSData )#> options:<#(NSJSONReadingOptions)#> error:<#(NSError *)#>] which give you proper array of dictionary.
Hope it will help you
I'm getting the same issue as described in following SO questions:
(The route lines is not following the streets when I zoom in)
MapKit - Make route line follow streets when map zoomed in
and
Route drawing on Google Maps for iOS not following the street lines
But seems there are no any answer which solved mentioned issue.
I'm adding to points to the my GMSMapView map by following function:
-(void) addPointToMap:(CLLocationCoordinate2D) coordinate
{
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(
coordinate.latitude,
coordinate.longitude);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
marker.map = mapView_;
[waypoints_ addObject:marker];
NSString *positionString = [[NSString alloc] initWithFormat:#"%f,%f",
coordinate.latitude,coordinate.longitude];
[waypointStrings_ addObject:positionString];
if([waypoints_ count]>1){
NSString *sensor = #"false";
NSArray *parameters = [NSArray arrayWithObjects:sensor, waypointStrings_,
nil];
NSArray *keys = [NSArray arrayWithObjects:#"sensor", #"waypoints", nil];
NSDictionary *query = [NSDictionary dictionaryWithObjects:parameters
forKeys:keys];
MDDirectionService *mds=[[MDDirectionService alloc] init];
SEL selector = #selector(addDirections:);
[mds setDirectionsQuery:query
withSelector:selector
withDelegate:self];
}
}
and here are setDirectionsQuery function:
static NSString *kMDDirectionsURL = #"http://maps.googleapis.com/maps/api/directions/json?";
- (void)setDirectionsQuery:(NSDictionary *)query withSelector:(SEL)selector
withDelegate:(id)delegate{
NSArray *waypoints = [query objectForKey:#"waypoints"];
NSString *origin = [waypoints objectAtIndex:0];
int waypointCount = [waypoints count];
int destinationPos = waypointCount -1;
NSString *destination = [waypoints objectAtIndex:destinationPos];
NSString *sensor = [query objectForKey:#"sensor"];
NSMutableString *url =
[NSMutableString stringWithFormat:#"%#&origin=%#&destination=%#&sensor=%#",
kMDDirectionsURL,origin,destination, sensor];
if(waypointCount>2) {
[url appendString:#"&waypoints=optimize:true"];
int wpCount = waypointCount-2;
for(int i=1;i<wpCount;i++){
[url appendString: #"|"];
[url appendString:[waypoints objectAtIndex:i]];
}
}
url = [url
stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding];
_directionsURL = [NSURL URLWithString:url];
[self retrieveDirections:selector withDelegate:delegate];
}
Note: I have followed this Google tutorial and modified it a little bit:
https://www.youtube.com/watch?v=AdV7bCWuDYg
Thanks in advance, any help will be appreciated!
Finally I have found solution, Thanks to the WWJD's last edit in his question!
Route drawing on Google Maps for iOS not following the street lines
From the answer:
What I basically did before was that I was getting and working only with the information I'm receiving in the routes while if you check the JSON file you're receiving from Google Directions API, you'll see that you receive much more information in the and the . This is the information we need to produce the proper results and the right polyline.
I need to implement the map view in my app to locate the required place. I had tried with the SVGeocoder concept.
[SVGeocoder geocode:searchfield.text
completion:^(NSArray *placemarks, NSHTTPURLResponse *urlResponse, NSError *error) {
}
But suppose I am trying to search any restaurent then the result is nil.
I was looking on Google map sdk but don't know how to do search functionality on GMSCameraPosition class.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:latitude
longitude:longitude
zoom:5];
how to search with the address using google sdk.
Thanks in advance.
If I understood it correctly, you need the location co-ordinates from a address string. Its Forward geo-coding. You can take a look at Google's free api for this: Link1
You will need a API key from your google account to access this api and there is way to select a free or business plan depending on your number of requests.
You need to use a CLLocation object for getting co-ordinates from your address. I wrote a similar function. CLLocation* temp_location=[[CLLocation alloc]init];
temp_location=[GeoCoding findAddressCordinates:sourceAddressTxtField.text];
// Class GeoCoding to find Co-ordinates
#import <Foundation/Foundation.h>
#interface GeoCoding : NSObject {
}
+(CLLocation*)findAddressCordinates:(NSString*)addressString;
#end
#import "GeoCoding.h"
#import <CoreLocation/CLAvailability.h>
#implementation GeoCoding
+(CLLocation*)findAddressCordinates:(NSString*)addressString {
CLLocation *location;
NSString *url = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true", addressString];
url = [url stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL *wurl = [NSURL URLWithString:url];
NSData *data = [NSData dataWithContentsOfURL: wurl];
// Fail to get data from server
if (nil == data) {
NSLog(#"Error: Fail to get data");
}
else{
// Parse the json data
NSError *error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
// Check status of result
NSString *resultStatus = [json valueForKey:#"status"];
// If responce is valid
if ( (nil == error) && [resultStatus isEqualToString:#"OK"] ) {
NSDictionary *locationDict=[json objectForKey:#"results"] ;
NSArray *temp_array=[locationDict valueForKey:#"geometry"];
NSArray *temp_array2=[temp_array valueForKey:#"location"];
NSEnumerator *enumerator = [temp_array2 objectEnumerator];
id object;
while ((object = [enumerator nextObject])) {
double latitude=[[object valueForKey:#"lat"] doubleValue];
double longitude=[[object valueForKey:#"lng"] doubleValue];
location=[[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
NSLog(#"CLLocation lat is %f -------------& long %f",location.coordinate.latitude, location.coordinate.longitude);
}
}
}
return location;
}
#end
You can then use this co-ordinates in your Google Map to focus your camera position.
I am using Google Map API to get the Latitudes and Longitude of near By ATM. I have get Google API key by my Google credentials. I am requesting by my app with Code
NSString *url = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search /json?location=%f,%f&radius=%#&types=%#&sensor=true&key=%#", currentCentre.latitude, currentCentre.longitude, [NSString stringWithFormat:#"%i", currenDist], googleType, kGOOGLE_API_KEY];
NSURL *googleRequestURL=[NSURL URLWithString:url];
NSData* data = [NSData dataWithContentsOfURL: googleRequestURL];
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
and I am getting
{
"debug_info" = (
);
"html_attributions" = (
);
results = (
);
status = "REQUEST_DENIED";
} as response.
please let me know what to do??
I think you need to use the Google Place API for getting the ATM location look for the link below
How to get 20+ result from Google Places API?