2010-09-11 13 views
5

Ho il seguente:Disegno punti LAT/su un'immagine

  • Un'immagine - una mappa disegnata a mano - di un'area di circa 600x400 metri. L'immagine è disegnata sopra i riquadri di Google Maps.
  • La latitudine/longitudine (da Google Maps) degli angoli di questa immagine. In altre parole, ho la latitudine nord e sud e la longitudine est e ovest dell'immagine.
  • Una coordinata di latitudine/longitudine da CoreLocation di iPhone.

Come si disegna un punto su questa immagine (o nulla se è fuori dai limiti), che rappresenta le coordinate da CoreLocation?

Bonus aggiuntivo: disegnare una freccia sul bordo della mappa, che punta alla coordinata, se la coordinata è fuori limite dell'immagine.

Mi piacerebbe farlo senza utilizzare una libreria come proj, in modo da non dover raggruppare una grande libreria e capire cosa sto facendo e perché.

Come probabilmente avete intuito sapendo, sto scrivendo questo in Objective-C. La tua risposta non deve essere in Objective-C, però.

risposta

3

Dopo alcune ricerche, ho scritto la mia biblioteca: libPirateMap. Non è molto lucido, ma funziona.

Nel caso in cui il collegamento si interrompa, incollerò qui il codice sorgente pertinente.

Usage:

// .h 
PirateMap *pirateMap; 
PirateMapPoint *pirateMapPoint; 

// .m 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
    pirateMap = [[PirateMap alloc] initWithNorthLatitude:59.87822 
             andSouthLatitude:59.87428 
             andWestLongitude:10.79847 
             andEastLongitude:10.80375 
              andImageWidth:640 
              andImageHeight:960]; 

    pirateMapPoint = [[PirateMapPoint alloc] init]; 
    pirateMapPoint.pirateMap = pirateMap; 
} 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 
    pirateMapPoint.coordinate = PirateMapCoordinate2DMake(newLocation.coordinate.latitude, newLocation.coordinate.longitude)  
    PirateMapPoint2D point = [pirateMapPoint pointOnImage]; 
    // use point.x and point.y to place your view. 
} 

Rilevante .m-code.

#import "PirateMap.h" 

static const double RAD_TO_DEG = 180/M_PI; 
static const double DEG_TO_RAD = M_PI/180; 

PirateMapCoordinate2D PirateMapCoordinate2DMake(double latitude, double longitude) { 
    return (PirateMapCoordinate2D) {latitude, longitude}; 
} 

// atan2(y2-y1,x2-x1) 

@implementation PirateMap 
@synthesize northLatitude, southLatitude, westLongitude, eastLongitude, 
imageWidth, imageHeight, latitudeImageToWorldRatio, longitudeImageToWorldRatio; 

-(id)initWithNorthLatitude:(double)aNorthLatitude 
      andSouthLatitude:(double)aSouthLatitude 
      andWestLongitude:(double)aWestLongitude 
      andEastLongitude:(double)anEastLongitude 
      andImageWidth:(int)anImageWidth 
      andImageHeight:(int)anImageHeight{ 
    if (self = [super init]) { 
     self.northLatitude = aNorthLatitude; 
     self.southLatitude = aSouthLatitude; 
     self.westLongitude = aWestLongitude; 
     self.eastLongitude = anEastLongitude; 

     self.imageWidth = anImageWidth; 
     self.imageHeight = anImageHeight; 

     self.latitudeImageToWorldRatio = [self computeLatitudeImageToWorldRatio]; 
     self.longitudeImageToWorldRatio = [self computeLongitudeImageToWorldRatio]; 
    } 
    return self; 
} 

-(double)computeLatitudeImageToWorldRatio { 
    return fabs(self.northLatitude - self.southLatitude)/self.imageHeight; 
} 

-(double)computeLongitudeImageToWorldRatio { 
    return fabs(self.eastLongitude - self.westLongitude)/self.imageWidth; 
} 

+(double)latitudeToMercatorY:(double)latitude { 
    static const double M_PI_TO_4 = M_PI/4; 

    return RAD_TO_DEG * log(tan(M_PI_TO_4 + latitude * (DEG_TO_RAD/2))); 
} 
@end 

#import "PirateMapPoint.h" 

PirateMapPoint2D PirateMapPoint2DMake(int x, int y) { 
    return (PirateMapPoint2D) {x, y}; 
} 

@implementation PirateMapPoint 
@synthesize pirateMap, coordinate; 

-(id)initWithPirateMap:(PirateMap *)aPirateMap andCoordinate:(PirateMapCoordinate2D)aCoordinate { 
    if (self = [super init]) { 
     self.pirateMap = aPirateMap; 
     self.coordinate = aCoordinate; 
    } 

    return self; 
} 

-(PirateMapPoint2D)pointOnImage { 
    double xDelta = self.coordinate.longitude - self.pirateMap.westLongitude; 
    double yDelta = self.pirateMap.northLatitude - self.coordinate.latitude; 
    return PirateMapPoint2DMake(round(xDelta/self.pirateMap.longitudeImageToWorldRatio), round(yDelta/self.pirateMap.latitudeImageToWorldRatio)); 
} 
@end 
1

Hai esaminato l'utilizzo di MapKit? Ha metodi per convertire le coordinate della mappa per visualizzare le coordinate. Dai un'occhiata alla famiglia di metodi convert.

http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKMapView_Class/MKMapView/MKMapView.html

Se siete in solo 4.0, si potrebbe trarre vantaggio dalla classe sovrapposizione pure.

http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKOverlayView_class/Reference/Reference.html

Cheers!

3

Se ho capito bene, è necessario fare due cose. Il primo è quello di mettere la tua immagine personalizzata in una vista mappa e avere le tue tessere personalizzate apparire con le coordinate corrette, quindi pan, zoom e così via. La seconda cosa che devi fare è disegnare un punto su quell'immagine ad una certa latitudine e longitudine.

Quello che ti serve è custom overlays, disponibile in iOS 4 e versioni successive. Il posto migliore per scoprire gli overlay personalizzati è lo WWDC 2010 video chiamato "Sessione 127 - Personalizzazione di mappe con sovrapposizioni". C'è anche un codice personalizzato disponibile per il video. Nel video, il relatore crea una mappa personalizzata e la incorpora in un MKMapView. Descrive anche uno strumento che puoi usare per creare le tue tessere (per tagliarle, ottenere le loro forme nella proiezione di Mercator e nominarle correttamente). La sua mappa viene scansionata da una mappa marina, quindi posizionata in cima alla normale visualizzazione della mappa.

È possibile utilizzare boundingMapRect per creare un rettangolo di limiti convertendo i limiti della mappa personalizzata in punti. Puoi convertire tra punti e coordinate usando MKMapPointForCoordinate e MKCoordinateForMapPoint.

Come per ottenere un punto disegnato sulla mappa, è possibile farlo in due modi. Il modo più semplice è usare semplicemente un oggetto personalizzato MKAnnotationView con un punto come immagine. In questo modo l'immagine non cresce e si riduce man mano che si ingrandisce. Se si desidera che il punto cresca e si riduca, è consigliabile utilizzare una sovrapposizione personalizzata anche per questo.È possibile utilizzare facilmente una sottoclasse di MKOverlayView

Per una freccia, è possibile utilizzare una vista normale e ruotarla (e posizionarla su un lato dello schermo) in base alla direzione di uscita. - punto di svolta. Utilizzare MKMapPointForCoordinate e quindi calcolare la direzione dal centro della vista.

Ma la tua migliore fonte sarà quel video. Approfondisce l'intero processo e fornisce una fonte per un'app di lavoro che è il 90% di ciò che ti serve per la tua mappa.

+0

Poiché ho solo un'immagine memorizzata nel pacchetto di app, sarebbe un po 'sciocco scaricare le tessere mappa da google in aggiunta alla mia immagine. Come posso impedire a MapKit di scaricare le tessere di Google? Non riesci a trovare nulla nei documenti e il video WWDC mostra una mappa opaca sopra i riquadri di Google. –

+0

In realtà finirai con più di un'immagine. Devi eseguire uno strumento chiamato GDAL (http://www.gdal.org/) per tagliare la tua grande immagine in tessere a vari livelli di zoom. Gli zoom più alti avranno più tessere. Non sono sicuro che tu possa impedire a MapKit di scaricare le tessere, ma suppongo che se la tua mappa fosse opaca al 100%, non le scaricherà. Nel video la sua mappa è in realtà leggermente trasparente. Parla di poter vedere una nave sul satellite. Guarda Google Maps vicino a San Francisco e potrai vedere le stesse navi. –