Rysowanie trasy w MapKit w iPhone SDK

Chcę narysować trasę między dwoma lokalizacjami na mapie. Coś jak przewodnik. Kiedy turysta kliknie w inną lokalizację, chcę być w stanie narysować trasę; a także poinformować o odległości od aktualnej lokalizacji.

Znam strony w Internecie, które mówią, Jak narysować polilinię na mapie. Ale większość przykładów miała wstępnie załadowany .plik csv o różnych współrzędnych.

Czy istnieje alternatywny sposób, aby uzyskać współrzędne z Google lub innego dostawca, ponieważ lokalizacja jest wybierana dynamicznie.

Jeśli nie, jak uzyskać informacje o współrzędnych pośrednich?

Czy iOS 6 zapewnia jakiś bezpośredni sposób na ten problem?

Author: Peter Mortensen, 2010-05-14

9 answers

To jest trudne. Nie da się tego zrobić z MapKit: rysowanie linii jest dość łatwe, gdy znasz współrzędne, ale MapKit nie daje dostępu do dróg ani innych informacji o wyznaczaniu trasy. Powiedziałbym, że musisz zadzwonić do zewnętrznego API, aby uzyskać dane.

I ' ve been playing with cloudmade.com API. Serwer Vector stream powinien zwrócić to, czego potrzebujesz, a następnie możesz narysować to na mapie. Jednak rozbieżności między mapami Google a mapami OSM używanymi przez cloudmade może sprawić, że będziesz chciał używać map cloudmade do końca: mają odpowiednik MapKit.

P. S.: inni dostawcy map-Google, Bing itp. może również dostarczać równoważne kanały danych. Ostatnio oglądałem OSM / Cloudmade.

P. P. S.: nic z tego nie jest trywialne newbie rzeczy! Powodzenia!

 24
Author: Andiih,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 22:33:19

Następujące viewDidLoad ustawią dwie lokalizacje, (2) usuną wszystkie poprzednie adnotacje i (3) wywołają zdefiniowane przez użytkownika funkcje pomocnicze (aby uzyskać punkty trasy i narysować trasę).

-(void)viewDidLoad
{
    [super viewDidLoad];

    // Origin Location.
    CLLocationCoordinate2D loc1;
    loc1.latitude = 29.0167;
    loc1.longitude = 77.3833;
    Annotation *origin = [[Annotation alloc] initWithTitle:@"loc1" subTitle:@"Home1" andCoordinate:loc1];
    [objMapView addAnnotation:origin];

    // Destination Location.
    CLLocationCoordinate2D loc2;
    loc2.latitude = 19.076000;
    loc2.longitude = 72.877670;
    Annotation *destination = [[Annotation alloc] initWithTitle:@"loc2" subTitle:@"Home2" andCoordinate:loc2];
    [objMapView addAnnotation:destination];

    if(arrRoutePoints) // Remove all annotations
        [objMapView removeAnnotations:[objMapView annotations]];

    arrRoutePoints = [self getRoutePointFrom:origin to:destination];
    [self drawRoute];
    [self centerMap];
}

Poniżej znajduje się metoda MKMapViewDelegate, która rysuje nakładkę (iOS 4.0 i nowsze).

/* MKMapViewDelegate Meth0d -- for viewForOverlay*/
- (MKOverlayView*)mapView:(MKMapView*)theMapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineView *view = [[MKPolylineView alloc] initWithPolyline:objPolyline];
    view.fillColor = [UIColor blackColor];
    view.strokeColor = [UIColor blackColor];
    view.lineWidth = 4;
    return view;
}

Następująca funkcja pobierze zarówno lokalizacje, jak i przygotuje adres URL, aby uzyskać wszystkie punkty trasy. I oczywiście, zadzwoni do stringWithURL.

/* This will get the route coordinates from the Google API. */
- (NSArray*)getRoutePointFrom:(Annotation *)origin to:(Annotation *)destination
{
    NSString* saddr = [NSString stringWithFormat:@"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
    NSString* daddr = [NSString stringWithFormat:@"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];

    NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
    NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];

    NSError *error;
    NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
    NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L];

    return [self decodePolyLine:[encodedPoints mutableCopy]];
}

Poniższy kod to prawdziwa magia (dekoder dla odpowiedź jaką otrzymaliśmy z API). Nie zmieniłbym tego kodu chyba, że wiem co robię:)

- (NSMutableArray *)decodePolyLine:(NSMutableString *)encodedString
{
    [encodedString replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                  options:NSLiteralSearch
                                    range:NSMakeRange(0, [encodedString length])];
    NSInteger len = [encodedString 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 = [encodedString 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 = [encodedString 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("\n[%f,", [latitude doubleValue]);
        printf("%f]", [longitude doubleValue]);
        CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:loc];
    }
    return array;
}

Ta funkcja narysuje trasę i doda nakładkę.

- (void)drawRoute
{
    int numPoints = [arrRoutePoints count];
    if (numPoints > 1)
    {
        CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < numPoints; i++)
        {
            CLLocation* current = [arrRoutePoints objectAtIndex:i];
            coords[i] = current.coordinate;
        }

        self.objPolyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
        free(coords);

        [objMapView addOverlay:objPolyline];
        [objMapView setNeedsDisplay];
    }
}

Poniższy kod wyśrodkuje mapę.

- (void)centerMap
{
    MKCoordinateRegion region;

    CLLocationDegrees maxLat = -90;
    CLLocationDegrees maxLon = -180;
    CLLocationDegrees minLat = 90;
    CLLocationDegrees minLon = 180;

    for(int idx = 0; idx < arrRoutePoints.count; idx++)
    {
        CLLocation* currentLocation = [arrRoutePoints 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;
    region.center.longitude    = (maxLon + minLon) / 2;
    region.span.latitudeDelta  = maxLat - minLat;
    region.span.longitudeDelta = maxLon - minLon;

    [objMapView setRegion:region animated:YES];
}
Mam nadzieję, że to komuś pomoże.
 61
Author: viral,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 08:14:53

Andiih ma rację. MapKit ci na to nie pozwoli. Niestety, Google też nie pozwoli Ci robić tego, co chcesz.

Kiedy Apple ogłosiło MapKit i w ogóle, wyraźnie stwierdziło, że wszelkie aplikacje nawigacyjne będą BYOM: Przynieś własne mapy, więc każda aplikacja nawigacyjna korzysta z własnego zestawu narzędzi do mapowania.

Warunki korzystania z usługi Google ograniczają nawet wyświetlanie tras na ich mapy:

Http://code.google.com/intl/de/apis/maps/iphone/terms.html

Ograniczenia Licencyjne:

10.9 korzystanie z usługi lub treści z dowolnymi produktami, systemami lub aplikacjami Dla lub w związku z:

(a) nawigacja w czasie rzeczywistym lub trasa wytyczne, w tym między innymi prowadzenie trasy krok po kroku, czyli zsynchronizowane z położeniem urządzenie obsługujące czujnik użytkownika;

B) dowolne systemy lub funkcje dla automatyczne lub autonomiczne sterowanie zachowanie pojazdu; lub

C) dyspozytornia, zarządzanie flotą, śledzenie zasobów biznesowych lub podobne aplikacje dla przedsiębiorstw (Google API Map może być używane do śledzenia zasobów (takie jak samochody, autobusy lub inne pojazdów) tak długo, jak śledzenie wniosek jest udostępniony do publiczne bez opłat. Na przykład, możesz zaoferować bezpłatne, publiczne API Map Implementacja, która wyświetla w czasie rzeczywistym transport publiczny lub inne transport informacje o stanie.

Niestety, obejmuje to to, co chciałbyś zrobić. Mam nadzieję, że pewnego dnia MapKit zostanie rozszerzony, aby umożliwić takie funkcje... chociaż mało prawdopodobne.

Powodzenia.

 12
Author: Daniel Amitay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-14 18:54:27

Możesz rzucić okiem na https://github.com/leviathan/nvpolyline[[2]} To rozwiązanie jest szczególnie skierowane do wersji iPhone OS przed V.4. 0

Chociaż może być również używany w V. 4. 0 nadzieję, że to pomoże.

 5
Author: leviathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-10 22:54:02
 4
Author: iOS_User,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-20 22:35:34

MapQuest ma SDK, który jest zamiennikiem MapKit. Jest obecnie w fazie beta, ale w fazie aktywnego rozwoju.

Umożliwia nakładki, routing i geokodowanie.

MapQuest iOS Maps API

 3
Author: Fabian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-04 23:45:09

Tak dla jasności, wygląda na to, że jest kilka rzeczy, które są omawiane. Jednym z nich jest sposób na zdobycie wierzchołków trasy, a drugim jest narysowanie Nakładki na mapie za pomocą tych wierzchołków. Znam API MapQuest, więc mam kilka linków do tych poniżej-Google i Bing mają odpowiedniki, myślę.

1) uzyskanie wierzchołków trasy
Jeśli szukasz nowych współrzędnych trasy, aby narysować nakładkę trasy, możesz użyć połączenia usługi internetowej do sieci wyznaczania tras usługa-zakładam, że używasz JavaScript tutaj, aby wyświetlić mapę. Jeśli używasz kodu natywnego, nadal możesz uruchomić usługę internetową lub użyć połączenia natywnego(to znaczy, MapQuest iPhone SDK ma natywne połączenie z trasą).

Większość usług kierunkowych powinna zwracać "punkty kształtu" trasy, aby można było rysować.

Oto kilka przykładów użycia MapQuest- Dojazd usługa internetowa, aby uzyskać punkty shape (patrz obiekt zwracający kształt) - http://www.mapquestapi.com/directions/

2) rysowanie nakładki
Gdy masz swoje wierzchołki, musisz je narysować. Myślę, że większość API map JavaScript będzie miała jakąś klasę nakładki. Oto MapQuest: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) robienie tego jednym wywołaniem
MapQuest ma również kilka wygodnych funkcji do połączenia trasy i narysowania linii dla Ciebie - nie mogę wysłać więcej niż dwóch linki! Przejdź więc do powyższego linku i poszukaj "routingu" w pasku nawigacyjnym po lewej stronie.

 3
Author: Roman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 08:12:35

Dzięki interfejsowi API iOS 7 uzyskanie i narysowanie trasy na mapie jest bardzo proste:]}

MKDirectionsRequest *directionsRequest = [[MKDirectionsRequest alloc] init];

// Set the origin of the route to be current user location
[directionsRequest setSource:[MKMapItem mapItemForCurrentLocation]];

// Set the destination point of the route
CLLocationCoordinate2D destinationCoordinate = CLLocationCoordinate2DMake(34.0872, 76.235);
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoordinate addressDictionary:nil];
[directionsRequest setDestination:[[MKMapItem alloc] initWithPlacemark:destinationPlacemark]];

MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];

// Requesting route information from Apple Map services
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
    if (error) {
        NSLog(@"Cannot calculate directions: %@",[error localizedDescription]);
    } else {
        // Displaying the route on the map
        MKRoute *route = [response.routes firstObject];
        [mapView addOverlay:route.polyline];
    }
}];
 3
Author: NAlexN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-14 16:46:24

Aby zaktualizować to pytanie, nie ma potrzeby zewnętrznego apk od iOS7.

Tutaj bardzo proste i skuteczne rozwiązanie:

Http://technet.weblineindia.com/mobile/draw-route-between-2-points-on-map-with-ios7-mapkit-api/2/

Wiem, że pytanie dotyczyło iOS 6, ale wierzę, że to rozwiązanie będzie przydatne dla wielu osób.

Jedyną rzeczą, której brakuje w tym rozwiązaniu, jest implementacja następującej metody delegata do wyświetlania początku i końca pin

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
 2
Author: Omaty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-25 08:30:01