Поиск пути / маршрута между двумя точками на MapKit в iPhone

Я пытаюсь найти путь между двумя местоположениями на Mapkit. У меня есть только два места. Теперь я должен найти точный путь между этими точками и нарисовать линию между этими точками с помощью MapKit. Я привел несколько примеров, в которых они используются .CSV-файл. В том. csv-файл они сохранили значения широты и долготы полного пути и линии рисования на основе этих значений.

но здесь я пытаюсь провести линию, не зная пути. Так есть любой способ найти путь динамически и нарисовать линию?

5 ответов


Ниже приведен код для поиска пути и рисует линию между двумя местоположениями.

для реализации ниже класса:

_mapRecord = [[PSMapDirection alloc] initWithFrame:CGRectMake(0.0, 49.0, 320.0, 411.0)];
[self.view addSubview:_mapRecord];

MapDirection.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "RegexKitLite.h"

@interface MapDirection : UIView<MKMapViewDelegate> 
{    
    MKMapView* mapView;
    NSArray* routes;    
    BOOL isUpdatingRoutes;
}

-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t;

@end

MapDirection.м

#import "MapDirection.h"

@interface MapDirection()
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) from to: (CLLocationCoordinate2D) to;
-(void) centerMap;

@end

- (id) initWithFrame:(CGRect) frame
{
    self = [super initWithFrame:frame];
    if (self != nil) 
    {
        mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        mapView.showsUserLocation = NO;
        [mapView setDelegate:self];
        [self addSubview:mapView];      
    }
    return self;
}

- (NSMutableArray *)decodePolyLine: (NSMutableString *)encoded 
{
    [encoded replaceOccurrencesOfString:@"\\" withString:@"\" options:NSLiteralSearch range:NSMakeRange(0, [encoded length])];
    NSInteger len = [encoded length];
    NSInteger index = 0;
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSInteger lat=0;
    NSInteger lng=0;
    while (index < len) 
    {
        NSInteger b;
        NSInteger shift = 0;
        NSInteger result = 0;
        do 
        {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lat += dlat;
        shift = 0;
        result = 0;
        do
        {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lng += dlng;
        NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
        NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
        //printf("[%f,", [latitude doubleValue]);
        //printf("%f]", [longitude doubleValue]);
        CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:loc];
    }   
    return array;
}

-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t 
{
    NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
    NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];

    NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
    NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
    //NSLog(@"api url: %@", apiUrl);
    NSError* error = nil;
    NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
    NSString *encodedPoints = [apiResponse stringByMatching:@"points:\\"([^\\"]*)\\"" capture:1L];   
    return [self decodePolyLine:[encodedPoints mutableCopy]];
}

-(void) centerMap
{
    MKCoordinateRegion region;
    CLLocationDegrees maxLat = -90.0;
    CLLocationDegrees maxLon = -180.0;
    CLLocationDegrees minLat = 90.0;
    CLLocationDegrees minLon = 180.0;
    for(int idx = 0; idx < routes.count; idx++)
    {
        CLLocation* currentLocation = [routes objectAtIndex:idx];
        if(currentLocation.coordinate.latitude > maxLat)
            maxLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.latitude < minLat)
            minLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.longitude > maxLon)
            maxLon = currentLocation.coordinate.longitude;
        if(currentLocation.coordinate.longitude < minLon)
            minLon = currentLocation.coordinate.longitude;
    }
    region.center.latitude     = (maxLat + minLat) / 2.0;
    region.center.longitude    = (maxLon + minLon) / 2.0;
    region.span.latitudeDelta = 0.01;
    region.span.longitudeDelta = 0.01;

    region.span.latitudeDelta  = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
    region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);
    [mapView setRegion:region animated:YES];
}

-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t 
{   
    if(routes) 
    {
    [mapView removeAnnotations:[mapView annotations]];
    }

    [mapView addAnnotation:f];
    [mapView addAnnotation:t];

    routes = [self calculateRoutesFrom:f.coordinate to:t.coordinate];
    NSInteger numberOfSteps = routes.count;

    CLLocationCoordinate2D coordinates[numberOfSteps];
    for (NSInteger index = 0; index < numberOfSteps; index++) 
    {
        CLLocation *location = [routes objectAtIndex:index];
        CLLocationCoordinate2D coordinate = location.coordinate;
        coordinates[index] = coordinate;
    }
    MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
    [mapView addOverlay:polyLine];
    [self centerMap];
}

#pragma mark MKPolyline delegate functions
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay 
{
    MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
    polylineView.strokeColor = [UIColor purpleColor];
    polylineView.lineWidth = 5.0;
    return polylineView;
}

@end

пример маршрута карты для отправные точки - "41.967659,-87.627869" и пункты назначения - "41.574361, -91.083069"

Map Route


здесь способ, которым я могу нарисовать направление между двумя точками (местоположение).


прежде всего загрузите GoogleMap sdk из этой ссылка и интеграция в ваше приложение.

теперь требуется ключ API, и вы можете создать по номиналу данные рекомендации по этой ссылка.

Ниже приведен код, который рисует направление на карте google между двумя местоположениями.


-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];


NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/directions/json?origin=%@&destination=%@&sensor=false&avoid=highways&mode=driving",saddr,daddr]];

NSError *error=nil;

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;

[request setURL:url];
[request setHTTPMethod:@"POST"];

NSURLResponse *response = nil;

NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error: &error];

NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONWritingPrettyPrinted error:nil];

return [self decodePolyLine:[self parseResponse:dic]];
}
- (NSString *)parseResponse:(NSDictionary *)response {
NSArray *routes = [response objectForKey:@"routes"];
NSDictionary *route = [routes lastObject];
if (route) {
    NSString *overviewPolyline = [[route objectForKey:
                                   @"overview_polyline"] objectForKey:@"points"];
    return overviewPolyline;
}
return @"";
}
-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr {
NSMutableString *encoded = [[NSMutableString alloc]
                            initWithCapacity:[encodedStr length]];
[encoded appendString:encodedStr];
[encoded replaceOccurrencesOfString:@"\\" withString:@"\"
                            options:NSLiteralSearch
                              range:NSMakeRange(0,
                                                [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
    NSInteger b;
    NSInteger shift = 0;
    NSInteger result = 0;
    do {
        b = [encoded characterAtIndex:index++] - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
    } while (b >= 0x20);
    NSInteger dlat = ((result & 1) ? ~(result >> 1)
                      : (result >> 1));
    lat += dlat;
    shift = 0;
    result = 0;
    do {
        b = [encoded characterAtIndex:index++] - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
    } while (b >= 0x20);
    NSInteger dlng = ((result & 1) ? ~(result >> 1)
                      : (result >> 1));
    lng += dlng;
    NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
    NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
    CLLocation *location = [[CLLocation alloc] initWithLatitude:
                            [latitude floatValue] longitude:[longitude floatValue]];
    [array addObject:location];
}
return array;
}
- (void)loadMapViewWithDirection {

float lat = 23.050671;
float lng = 72.541351;

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:lat
                                                        longitude:lng
                                                             zoom:10];

GMSMapView  * mapView = [GMSMapView mapWithFrame:CGRectMake(0, 75, 320, self.view.frame.size.height-kHeaderRect.size.height) camera:camera];
self.mapView.myLocationEnabled = YES;


float sourceLatitude = 23.050671;
float sourceLongitude = 72.541351;

float destLatitude = 23.036138;
float destLongitude = 72.603836;

GMSMarker *sourceMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude);
marker.map = self.mapView;

GMSMarker *destMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(destLatitude, destLongitude);
marker.map = self.mapView;

self.mapView.delegate = self;

   [self drawDirection:CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude) and:CLLocationCoordinate2DMake(destLatitude, destLongitude)];


[self.view addSubview:self.mapView];
}
- (void) drawDirection:(CLLocationCoordinate2D)source and:(CLLocationCoordinate2D) dest {


GMSPolyline *polyline = [[GMSPolyline alloc] init];
GMSMutablePath *path = [GMSMutablePath path];

NSArray * points = [self calculateRoutesFrom:source to:dest];

NSInteger numberOfSteps = points.count;

for (NSInteger index = 0; index < numberOfSteps; index++)
{
    CLLocation *location = [points objectAtIndex:index];
    CLLocationCoordinate2D coordinate = location.coordinate;
    [path addCoordinate:coordinate];
}

polyline.path = path;
polyline.strokeColor = [UIColor redColor];
polyline.strokeWidth = 2.f;
polyline.map = self.mapView;

// Copy the previous polyline, change its color, and mark it as geodesic.
polyline = [polyline copy];
polyline.strokeColor = [UIColor greenColor];
polyline.geodesic = YES;
polyline.map = self.mapView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadMapViewWithDirection];   
}

вы можете обратиться код, это именно то, что вы хотите.
EDIT: and это


Я не думаю, что вы можете сделать это локально. Реализация алгоритма поиска пути между двумя точками gps требует много входных данных (данных с карт), и у вас этого нет. Только поставщик карт может позволить себе реализовать такой алгоритм и предоставить API для его использования. Я думаю Google маршрутизация API, но я не играл с ним...


https://developers.google.com/maps/documentation/directions/

обратите внимание, что TOS говорят, что вы должны отображать результаты на карте Google, поэтому вам придется отключить функциональность в следующем выпуске iOS