2010-09-11 25 views
5

que tienen la siguiente:Dibujo puntos LAT/LNG en una imagen

  • Una imagen - un mapa dibujado a mano - de un área de aproximadamente 600x400 metros. La imagen se dibuja sobre los mosaicos de Google Maps.
  • La latitud/longitud (desde Google Maps) de las esquinas de esta imagen. O dicho de otra manera, tengo la latitud norte y sur y la longitud este y oeste de la imagen.
  • Una coordenada de latitud/longitud desde CoreLocation de iPhone.

¿Cómo se dibuja un punto en esta imagen (o nada si está fuera de los límites), que representa la coordenada de CoreLocation?

Bonificación adicional: dibuja una flecha en el borde del mapa, apuntando a la coordenada, si la coordenada está fuera de los límites de la imagen.

Me gustaría hacer esto sin usar una biblioteca como proj, para no tener que agrupar una gran biblioteca, y entender lo que estoy haciendo y por qué.

Como probablemente haya adivinado por saber, estoy escribiendo esto en Objective-C. Sin embargo, su respuesta no tiene que ser en Objective-C.

Respuesta

3

Después de algunas investigaciones, escribí mi propia biblioteca: libPirateMap. No está muy pulido, pero funciona.

En caso de que el enlace se caiga, pegaré aquí el código fuente correspondiente.

Uso:

// .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. 
} 

Relevante .m-código.

#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

¿Has investigado el uso de MapKit? Tiene métodos para convertir las coordenadas del mapa para ver las coordenadas. Eche un vistazo a la familia de métodos convertida.

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

Si se encuentra en sólo el 4,0, que podría beneficiarse de la clase de superposición también.

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

Saludos!

3

Si lo entiendo correctamente, debe hacer dos cosas. El primero es poner su imagen personalizada en una vista de mapa y hacer que sus azulejos personalizados aparezcan en las coordenadas correctas, luego hacer panorámicas, acercar y más. Lo segundo que debe hacer es dibujar un punto en esa imagen en cierta latitud y longitud.

Lo que necesita es custom overlays, disponible en iOS 4 en adelante. El mejor lugar para averiguar sobre superposiciones personalizadas es el WWDC 2010 video llamado "Sesión 127 - Personalización de mapas con superposiciones". También hay un código personalizado disponible para el video. En el video, el presentador crea un mapa personalizado y lo incorpora en un MKMapView. También describe una herramienta que puedes utilizar para hacer tus mosaicos (para cortarlos, poner sus formas en la proyección de Mercator y ponerles un nombre apropiado). Su mapa se escanea desde un mapa marino, luego se coloca en la parte superior de la vista del mapa normal.

Puede usar boundingMapRect para crear un rectángulo de límites convirtiendo los límites de su mapa personalizado en puntos. Puede convertir puntos y coordenadas usando MKMapPointForCoordinate y MKCoordinateForMapPoint.

En cuanto a un punto dibujado en el mapa, puede hacerlo de varias maneras. Lo más fácil es usar un MKAnnotationView personalizado con un punto como imagen. De esta forma, la imagen no crece y se reduce a medida que acercas la imagen. Si quieres que el punto crezca y se encoja, debes usar una superposición personalizada para eso también.Desde aquí se puede utilizar un MKCircleView, que es una subclase de MKOverlayView

Para una flecha, se puede utilizar una vista normal y girarlo (y lo coloca en un lado de la pantalla) de acuerdo con la dirección de su fuera de -bordos punto. Use MKMapPointForCoordinate y luego calcule la dirección desde el centro de su vista.

Pero su mejor fuente será ese video. Él profundiza en todo el proceso y da origen a una aplicación que funciona, que es el 90% de lo que necesita para su propio mapa.

+0

Como solo tengo una imagen almacenada en el paquete de la aplicación, sería una tontería descargar mosaicos de Google Maps además de mi propia imagen. ¿Cómo puedo evitar que MapKit descargue fichas de Google? No se puede encontrar nada en los documentos, y el video de WWDC muestra un mapa opaco sobre los mosaicos de Google. –

+0

De hecho, terminará con más de una imagen. Necesita ejecutar una herramienta llamada GDAL (http://www.gdal.org/) para cortar su imagen grande en mosaicos en varios niveles de zoom. Los zooms más altos tendrán más fichas. No estoy seguro de si puedes evitar que MapKit descargue mosaicos, pero supongo que si tu propio mapa es 100% opaco, no los descargaría. En el video, su mapa es en realidad un poco transparente. Habla sobre poder ver un barco en el satélite. Mira Google Maps cerca de San Francisco y podrás ver los mismos barcos. –

Cuestiones relacionadas