Desen un traseu în MapKit în iPhone SDK

voturi
53

Vreau să atrag o rută între două locații de pe hartă. Ceva de genul un ghid turistic. În cazul în care turistul face clic pe altă locație, vreau să fie în măsură să atragă un traseu; precum și, informați cu privire la distanța de la locația curentă.

Sunt conștient de site-uri de pe Internet, care spun cum să atragă polilinii pe hartă. Dar, de cele mai multe exemple au avut un fișier .csv preîncărcate cu diferite coordonate.

Există o modalitate alternativă de a obține coordonatele de la Google sau de orice alt furnizor, ca locație este selectată în mod dinamic.

Dacă NU, cum pot obține informațiile pentru coordonatele intermediare?

Are iOS 6 oferă nici o modalitate directă pentru această problemă?

Întrebat 14/05/2010 la 14:37
sursa de către utilizator
În alte limbi...                            


9 răspunsuri

voturi
61

Următoarele viewDidLoadva (1) a stabilit două locații, (2) îndepărtați toate adnotările anterioare, și funcțiile helper (3) utilizatori de apel definit (pentru a obține puncte de rută și să tragă ruta).

-(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];
}

Următoarele este MKMapViewDelegatemetoda, care atrage overlay (iOS 4.0 și mai târziu).

/* 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;
}

Funcția următoare va primi atât locațiile și să se pregătească URL-ul pentru a obține toate punctele de rută. Și, desigur, va suna 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]];
}

Codul de mai jos este real magic (decodor pentru răspunsul am primit de la API). Nu aș modifica acest cod dacă nu știu ce fac :)

- (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;
}

Această funcție va desena o cale și se va adăuga o suprapunere.

- (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];
    }
}

Codul de mai jos va centrati harta.

- (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];
}

Sper că acest lucru ar ajuta pe cineva.

Publicat 12/08/2012 la 18:21
sursa de către utilizator

voturi
24

Acesta este unul complicat. Nu există nici o modalitate de a face acest lucru cu MapKit: este destul de ușor pentru a desena linii atunci când știi coordonatele, dar MapKit nu va da acces la drumuri sau alte informații de rutare. Aș spune că trebuie să suni un API extern pentru a obține datele.

Am jucat cu API - ul cloudmade.com. Serverul flux vectorial ar trebui să se întoarcă ceea ce aveți nevoie, și apoi puteți desena că peste harta. Cu toate acestea, discrepanțe între hărțile Google și OSM hărțile folosite de CloudMade pot face să vă doriți să utilizați hărți CloudMade tot felul: ei au un echivalent cu MapKit.

PS: Alți furnizori de cartografiere - Google, Bing, etc poate furniza, de asemenea, date echivalente feed-uri. Tocmai am uitat la OSM / CloudMade recent.

PPS: Nici unul dintre aceste lucruri este newbie banal! Mult noroc!

Publicat 14/05/2010 la 14:59
sursa de către utilizator

voturi
12

Andiih a avut dreptate. MapKit nu va lăsa să faci asta. Din păcate, Google nu va lasa sa faci ceea ce vrei să faci, fie.

Atunci când Apple a anunțat MapKit și toate, de asemenea, au afirmat în mod explicit că orice aplicații de navigație ar fi BYOM: Adu Hărților proprii, astfel încât orice aplicație de navigare utilizează propriul set de instrumente de cartografiere.

Termenii Serviciului Google restricționa chiar afișarea rute pe partea de sus a hărților lor:

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

Restricții de licență:

10.9 utilizați Serviciul sau Conținutul cu orice produse, sisteme sau aplicații pentru sau în legătură cu:

(A) de navigație în timp real sau de orientare pe traseu, inclusiv, dar fără a se limita la turn-by-turn de ghidare traseu care este sincronizat cu poziția dispozitivului cu senzor al unui utilizator;

(B) orice sisteme sau funcții pentru controlul automat sau autonom al comportamentului vehiculului; sau

(C) expedierea, gestionarea parcului auto, de urmărire a activelor de afaceri sau aplicații enterprise similare (API-ul Google Maps poate fi folosit pentru a urmări active (cum ar fi mașini, autobuze sau alte vehicule), atât timp cât cererea de urmărire este pus la dispoziția publicului, fără taxa. de exemplu, s-ar putea oferi unui public Hărți de punere în aplicare liberă, API-ul care afișează transportul public în timp real sau alte informații de stare de transport.

Din păcate, acest lucru include ceea ce doriți să faceți. Să sperăm că o MapKit zi va fi extins pentru a permite astfel de caracteristici ... deși puțin probabil.

Mult noroc.

Publicat 14/05/2010 la 19:54
sursa de către utilizator

voturi
5

S-ar putea dori să aibă o privire la https://github.com/leviathan/nvpolyline Această soluție este orientată în special la versiunile iPhone OS înainte de versiunea 4.0

Cu toate că poate fi folosită și în Hope this ajutor versiunea 4.0.

Publicat 01/07/2010 la 15:22
sursa de către utilizator

voturi
4

Încercați MapKit-Route-Direcții ( github ).

Publicat 05/01/2011 la 08:06
sursa de către utilizator

voturi
3

Obținerea și desenarea unui traseu pe hartă este foarte ușor cu iOS 7 API:

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];
    }
}];
Publicat 14/02/2015 la 16:46
sursa de către utilizator

voturi
3

Doar pentru a clarifica, se pare că există o serie de lucruri discutate. Una este o modalitate de a obține vârfurile unui traseu , iar celălalt este de a desena o suprapunere pe hartă folosind aceste noduri. Știu API - urile MapQuest, așa că am unele link - uri pentru cei de mai jos - Google și Bing au echivalente cred.

1) Obținerea de noduri ale unui traseu
Dacă sunteți în căutarea pentru noile coordonate ale unui traseu pentru a desena o suprapunere pe traseu, puteți utiliza fie un apel de serviciu web pentru un serviciu web de rutare - Sunt presupunând că utilizați JavaScript aici pentru a afișa harta. Dacă utilizați cod nativ, puteți lovi în continuare un serviciu web sau puteți utiliza un apel nativ (adică, MapQuest iPhone SDK - ul are un apel traseu nativ în ea).

Cele mai multe dintre serviciile direcții ar trebui să se întoarcă la „shapepoints“ ale traseului, astfel încât să puteți trage.

Iată câteva exemple folosind MapQuest- Serviciul de orientare web pentru a obține shapepoints ( a se vedea obiectul retur Shape) - http://www.mapquestapi.com/directions/

2) conturând o suprapunere
Odată ce aveți noduri, va trebui să le atragă. Cred că cele mai multe JavaScript harta API - uri vor avea o clasă de suprapunere de un anumit fel. Iată MapQuest unul: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Fac cu un singur apel
MapQuest au , de asemenea , unele funcții comoditate pentru a face apel ruta și trage linia pentru tine - nu pot posta mai mult de două link - uri! Deci , du - te la link - ul de mai sus și căutați „rutare“ în bara de navigare din partea stângă.

Publicat 12/03/2012 la 17:09
sursa de către utilizator

voturi
3

MapQuest are un SDK, care este un înlocuitor drop-in pentru MapKit. Este în prezent în versiune beta, dar în curs de dezvoltare activă.

Acesta permite suprapuneri, rutare, si geocodare.

MapQuest iOS API Hărți

Publicat 05/03/2012 la 00:45
sursa de către utilizator

voturi
2

Pentru a actualiza această întrebare, nu este necesar să apk externi, deoarece iOS7.

Aici o soluție foarte simplă și eficientă:

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

Știu că întrebarea a fost despre iOS 6, dar eu cred că această soluție va fi util pentru mulți oameni.

Singurul lucru care lipsește în această soluție implementează următoarea metodă delegat pentru a afișa început și se termină PIN-ul

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Publicat 25/02/2015 la 08:30
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more