How to iterate over the path from Google Directions API? - ios

I am trying to move the marker along two selected markers with their coordinates set.
I am getting the path from this code:
GMSPath *path1 =[GMSPath pathFromEncodedPath:self.dataReceive[#"routes"][0][#"overview_polyline"][#"points"]];
When i am using the for loop to move first marker to the position of second marker. It is taking a straight path but it should move along the path coordinates that has been fetched from the google directions API.
for (int i = 0; i< path1.count; i++) {
CLLocationCoordinate2D position = [path1 coordinateAtIndex:i];
[CATransaction begin];
[CATransaction setAnimationDuration:50];
self.marker.position = position;
self.marker.map = self.mapView;
[CATransaction commit];
}
Thanks.

Try this code Objective C.
- (void)showPathFromCurrentLocationForCoordinate:(CLLocationCoordinate2D)coord{
CLLocationCoordinate2D destination = coord;
NSMutableString *urlString = [[NSMutableString alloc] initWithString:#"https://maps.googleapis.com/maps/api/directions/json?"];
[urlString appendString:[NSString stringWithFormat:#"origin=%f,%f&destination=%f,%f&sensor=true",self.deviceLocation.latitude,self.deviceLocation.longitude,destination.latitude,destination.longitude]];
[RestApi getPath:urlString withParameter:nil withHandler:^(id responseObject, NSError *error, NSURLResponse *response) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
NSDictionary *json = responseObject;
NSArray *routes = [json objectForKey:#"routes"];
if (routes != nil && routes.count > 0) {
NSDictionary *route = [routes objectAtIndex:0];
long distance = 0;
NSArray *legs = [route objectForKey:#"legs"];
for (NSDictionary *leg in legs) {
long dist = [leg[#"distance"][#"value"] longValue];
distance = distance + dist;
}
GMSPath *path =[GMSPath pathFromEncodedPath:route[#"overview_polyline"][#"points"]];
GMSPolyline *line = [GMSPolyline polylineWithPath:path];
line.strokeColor = PATH_STROKE_COLOR;
line.strokeWidth = PATH_STROKE_WIDTH;
line.map = mapView;
GMSMutablePath *markerpath = [GMSMutablePath path];
[markerpath addCoordinate: self.deviceLocation];
[markerpath addCoordinate: marker.position];
GMSCoordinateBounds *bonds = [[GMSCoordinateBounds alloc] initWithPath:markerpath];
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat: 1.0] forKey:kCATransactionAnimationDuration];
[mapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bonds withPadding:MAP_BOUNDS_OFFSET_PADDING]];
[CATransaction commit];
}
else{
NSLog(#"Google direction API failed.");
}
}
else if (error != nil){
NSLog(#"%#",error.localizedDescription);
}
});
}];
}

Related

Google maps polyline not rendering perfectly

I am drawing polyline using latest google maps API for iOS. I am constructing polyline point by point but it is not rendering properly as when i zoom out the polyline vanishes(not in literal terms) from the map and when i zoom in it simply shows the line.
This is how polyline appears when zoomed in
This is how it appears when zoomed out
here is my function for drawing polyline
RCPolyline *polyline = [[RCPolyline alloc] init];
[polyline drawPolylineFromPoint:self.selectedEmployee.location toPoint:location];
i have override init: for RCPolyline to be something like this
- (instancetype)init {
self = [super init];
if (self) {
self.strokeWidth = 5.0f;
self.strokeColor = UIColor.redColor;
self.geodesic = YES;
self.map = [RCMapView sharedMapView];
}
return self;}
and drawPolylineFromPoint:toPoint: does this
- (void)drawPolylineFromPoint:(CLLocation *)pointX toPoint:(CLLocation *)pointY {
GMSMutablePath *path = [GMSMutablePath path];
[path addCoordinate:pointX.coordinate];
[path addCoordinate:pointY.coordinate];
self.path = path;}
I found the glitch, i was making local instance of RCPolyline class and was calling the method for constructing polyline from that what i wanted was to have a global object for RCPolyline instance and update the GMSPath for the RCPolyline class instance
something like this:
- (instancetype)initWithMap:(GMSMapView *)mapView {
self = [super init];
if (self) {
self.strokeWidth = 4.0f;
self.strokeColor = [UIColor redColor];
self.geodesic = YES;
self.map = mapView;
self.mutablePath = [GMSMutablePath path];
}
return self;}
and now i am calling this method from that same instance.
- (void)appendPolylineWithCoordinate:(CLLocation *)location {
[self.mutablePath addCoordinate:location.coordinate];
self.path = self.mutablePath;}
PS: RCPolyline is subclass of GMSPolyline
Try this code.
- (void)fetchPolylineWithOrigin:(CLLocation *)origin destination:(CLLocation *)destination {
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:lat longitude:longg zoom:12];
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView.myLocationEnabled = YES;
self.view = mapView;
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(-33.86, 151.20);
marker.map = mapView;
NSString *originString = [NSString stringWithFormat:#"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
NSString *destinationString = [NSString stringWithFormat:#"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];
NSString *directionsAPI = #"https://maps.googleapis.com/maps/api/directions/json?";
NSString *directionsUrlString = [NSString stringWithFormat:#"%#&origin=%#&destination=%#&mode=driving&key=%#&alternatives=true", directionsAPI, originString, destinationString,#"YOUR API KEY"];
NSURL *directionsUrl = [NSURL URLWithString:directionsUrlString];
NSURLSessionDataTask *fetchDirectionsTask = [[NSURLSession sharedSession] dataTaskWithURL:directionsUrl completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error)
{
return;
}
NSArray *routesArray = [json objectForKey:#"routes"];
GMSPolyline *polyline = nil;
int i=1;
for (id route in routesArray)
{
NSDictionary *routeDict = [route valueForKey:#"overview_polyline"];
NSString *points = [routeDict objectForKey:#"points"];
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
GMSPath *path = [GMSPath pathFromEncodedPath:points];
polyline = [GMSPolyline polylineWithPath:path];
polyline.strokeWidth = 3;
if(i==1)
{
polyline.strokeColor = [UIColor greenColor];
}else if(i==2)
{
polyline.strokeColor = [UIColor redColor];
}else{
polyline.strokeColor = [UIColor blueColor];
}
i = i+1;
bounds = [bounds includingCoordinate:marker.position];
polyline.map=mapView;
}
}];
[fetchDirectionsTask resume];
}

Adding a marker image to Google Maps on IOS Objective-C app

I have a map to show directions. I am able to tap on a direction to view an annotation with the instructions but what I am trying to do is add a marker to the directions coordinates. Here is the code I am currently using:
-(void) getDirectionsFromStart: (CLLocation*) start toEnd: (CLLocation*) end
{
NSString *mapDir = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=false", start.coordinate.latitude, start.coordinate.longitude, end.coordinate.latitude, end.coordinate.longitude];
if ([self.directionsArray count] == 0) {
//parse the string response and then draw the points on a map
NSError *error;
NSString *response = [NSString stringWithContentsOfURL:[NSURL URLWithString:mapDir] encoding:NSUTF8StringEncoding error:&error];
if (response == nil) {
NSLog(#"Google Maps error: %#", [error localizedDescription]);
NSLog(#"Google Maps recovery: %#", [error localizedRecoverySuggestion]);
//[self getDirectionsFromStart:nil toEnd:nil];
}
self.directionsArray = [gMapsJsonDirectionsParser parseJsonToMapDirections:response];
}
for (gMapsJourneyLeg *leg in self.directionsArray) {
#autoreleasepool {
self.directionsHeader.text = [NSString stringWithFormat:#"To %# Taking: %#", leg.end_address, leg.duration.text];
for (gMapsStep *step in leg.steps ) {
MKPolyline *polyLine = [gMapsJsonDirectionsParser polylineWithEncodedString:step.polyLine];
MKPolylineView *line = [[MKPolylineView alloc] initWithPolyline: polyLine];
line.fillColor = [UIColor blueColor];
line.strokeColor = [UIColor blueColor];
line.lineWidth = 5;
[self.mapView addOverlay:polyLine];
//[self.mapView setVisibleMapRect:polyLine.boundingMapRect];
//map point code
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = step.end_location.coordinate;
point.title = step.htmlInstructions;
[[self.mapView viewForAnnotation:point] setTag:1];
UIImage *image = [UIImage imageNamed:#"marker_red.png"];
[[self.mapView viewForAnnotation:point] setImage:image];
[self.mapView addAnnotation:point];
}
}
}
[self.tableView reloadData];
}
To be clear, the annotations and polyline are both fine it's just the marker is never shown.
Base on the code in the Google Docs for Markers:
Here is the sample code for adding markers with custom image.
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(51.5, -0.127);
GMSMarker *london = [GMSMarker markerWithPosition:position];
london.title = #"London";
london.icon = [UIImage imageNamed:#"house"];
london.map = mapView_;
May be you have not set the GMSMarker *london = [GMSMarker markerWithPosition:position]; that is why your marker is not visible.
Kindly check the marker without a custom image if it will show up, if not try adding the markerPosition property.

MKPolygon and point contains

I have a KML file that contains all the polygons coordinates for all countries.
Some countries have more than 1 <coordinates> tag.
What I am trying to accomplish here is to get a coordinates and find in which polygon is located. I got an idea on this post but my problem is that my algorithm is wrong and returns that my coordinates are located on more than 1 polygons.
This is my code:
-(void)parseCoordinates:(NSString*)str{
coordinatesArray = [str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSInteger coordinatesCount = [coordinatesArray count];
CLLocationCoordinate2D *cord2d = malloc(sizeof(CLLocationCoordinate2D) * coordinatesCount);
for(int i=0; i<coordinatesCount;i++){
NSString *st = [coordinatesArray objectAtIndex:i];
if ([st isEqualToString:#""]) {
continue;
}
NSArray *strArray = [st componentsSeparatedByString:#","];
if ([strArray count]>1) {
cord2d[i] = CLLocationCoordinate2DMake([[strArray objectAtIndex:1] doubleValue], [[strArray objectAtIndex:0] doubleValue]);
}
strArray=nil;
}
free(cord2d);
coordinatesArray = nil;
MKPolygon* poly2 = [MKPolygon polygonWithCoordinates:cord2d count:coordinatesCount];
CLLocationCoordinate2D mapCoordinate = CLLocationCoordinate2DMake(39.1274378,-100.9945566);
MKMapPoint mapPoint = MKMapPointForCoordinate(mapCoordinate);
MKPolygonRenderer *polygonView = [[MKPolygonRenderer alloc]initWithPolygon:poly2];
CGPoint polygonViewPoint = [polygonView pointForMapPoint:mapPoint];
BOOL mapCoordinateIsInPolygon =
CGPathContainsPoint(polygonView.path, NULL, polygonViewPoint, NO);
NSLog(#"Country: %#", country);
NSLog(#"is it inside? %d",mapCoordinateIsInPolygon);
}

iOS Multiple Polyline Overlay causes memory issue

I’m using mkmapview in my application it contains multiple polyline overlay and multiple custom annotations, while running the application receiving memory warning oftenly, I struggled a lot
Thanks in advance.
for (int i = 0; i<[latArray count]-1; i++)
{
NSString *lat1 = [latArray objectAtIndex:i];
NSString *longi1 = [longArray objectAtIndex:i];
firstPlace = CLLocationCoordinate2DMake([lat1 doubleValue], [longi1 doubleValue]);
NSString *lat2 = [latArray objectAtIndex:i+1];
NSString *longi2 = [longArray objectAtIndex:i+1];
secPlace = CLLocationCoordinate2DMake([lat2 doubleValue], [longi2 doubleValue]);
[self directionRequest:firstPlace :secPlace index:i];
}
-(void)directionRequest:(CLLocationCoordinate2D )firstCord :(CLLocationCoordinate2D )secCord index:(int)index
{
#try
{
MKPlacemark *source=[[MKPlacemark alloc]initWithCoordinate:firstCord addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *sourceMapItem=[[MKMapItem alloc]initWithPlacemark:source];
[sourceMapItem setName:#""];
MKPlacemark *destination=[[MKPlacemark alloc]initWithCoordinate:secCord addressDictionary:[NSDictionary dictionaryWithObjectsAndKeys:#"",#"", nil]];
MKMapItem *destinationMapitem=[[MKMapItem alloc]initWithPlacemark:destination];
[destinationMapitem setName:#""];
MKDirectionsRequest *dirRequest=[[MKDirectionsRequest alloc]init];
[dirRequest setSource:sourceMapItem];
[dirRequest setDestination:destinationMapitem];
// dirRequest.requestsAlternateRoutes = YES;
[dirRequest setTransportType:MKDirectionsTransportTypeAutomobile];
MKDirections *direction=[[MKDirections alloc]initWithRequest:dirRequest];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error)
{
// NSLog(#"response = %#",response);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[iMapView addOverlay:line];
}];
}];
}
#catch (NSException *exception)
{
}
}

how to draw line between x number of moving annotations?

Hai am new to xcode am developing an iOS app for vehicle tracking using mkmap I need to draw lines between the annotations for every 5 seconds based on the vehicle moving, My prob is it draw the line for the first time only and from the second refresh interval it it won't works my code is below,
- (void)viewDidLoad
{
[super viewDidLoad];
aTimer = [NSTimer scheduledTimerWithTimeInterval:5
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
-(void)timerFired:(NSTimer *) theTimer
{
NSArray *existingpoints = MapViewC.annotations;
if ([existingpoints count])
[MapViewC removeAnnotations:existingpoints];
NSString *urlMapString=[NSString stringWithFormat:#"http://www.logix.com/logix_webservice/map.php?format=json&truckno=%#",nam2];
NSURL *urlMap=[NSURL URLWithString:urlMapString];
NSData *dataMap=[NSData dataWithContentsOfURL:urlMap];
NSError *errorMap;
NSDictionary *jsonMap = [NSJSONSerialization JSONObjectWithData:dataMap options:kNilOptions error:&errorMap]; NSArray *resultsMap = [jsonMap valueForKey:#"posts"];
NSArray *resMap = [resultsMap valueForKey:#"post"];
NSArray *latitudeString=[resMap valueForKey:#"latitude"];
NSString *latOrgstring = [latitudeString objectAtIndex:0];
latitude=[latOrgstring doubleValue];
NSArray *longitudeString=[resMap valueForKey:#"longitude"];
NSString *longOrgstring = [longitudeString objectAtIndex:0];
longitude=[longOrgstring doubleValue];
NSString *ignation=[[resMap valueForKey:#"ignition"]objectAtIndex:0];
//MAP VIEW Point
MKCoordinateRegion myRegion;
//Center
CLLocationCoordinate2D center;
center.latitude=latitude;
center.longitude=longitude;
//Span
MKCoordinateSpan span;
span.latitudeDelta=0.01f;
span.longitudeDelta=0.01f;
myRegion.center=center;
myRegion.span=span;
//Set our mapView
[MapViewC setRegion:myRegion animated:YES];
//Annotation
//1.create coordinate for use with the annotation
//CLLocationCoordinate2D wimbLocation;
wimbLocation1.latitude=latitude;
wimbLocation1.longitude=longitude;
Annotation * myAnnotation= [Annotation alloc];
CLLocation *someLocation=[[CLLocation alloc]initWithLatitude:latitude longitude:longitude];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:someLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSDictionary *dictionary = [[placemarks objectAtIndex:0] addressDictionary];
addressOutlet=[dictionary valueForKey:#"Street"];
City=[dictionary valueForKey:#"City"];
State=[dictionary valueForKey:#"State"];
myAnnotation.coordinate=wimbLocation1;
if (addressOutlet!=NULL&&City!=NULL)
{
myAnnotation.title=addressOutlet;
myAnnotation.subtitle=[NSString stringWithFormat:#"%#,%#", City, State];
}
[self.MapViewC addAnnotation:myAnnotation];
[self line];
}];
}
-(void)line
{
CLLocationCoordinate2D coordinateArray[2];
coordinateArray[0] = CLLocationCoordinate2DMake(latitude, longitude);
coordinateArray[1] = CLLocationCoordinate2DMake(latitude, longitude);
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:2];
[self.MapViewC addOverlay:self.routeLine];
}
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
if(overlay == self.routeLine)
{
if(nil == self.routeLineView)
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.fillColor = [UIColor redColor];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}
return nil;
}
Kindly advice me to correct my errors. Thanks in advance...
Try this.... this will help you...
-(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay
{
{
self.routeLineView = [[MKPolylineView alloc] initWithPolyline:self.routeLine];
self.routeLineView.strokeColor = [UIColor redColor];
self.routeLineView.lineWidth = 5;
}
return self.routeLineView;
}

Resources