Рисование точек широты и долготы на изображении - PullRequest
5 голосов
/ 11 сентября 2010

У меня есть следующее:

  • Изображение - нарисованная от руки карта - площадью примерно 600х400 метров. Изображение нарисовано поверх плиток Google Maps.
  • Широта / долгота (из Google Maps) углов этого изображения. Или, иначе говоря, у меня есть северная и южная широта и восточная и западная долгота изображения.
  • Координата широты / долготы из CoreLocation на iPhone.

Как нарисовать точку на этом изображении (или ничего, если оно выходит за границы), представляя координату из CoreLocation?

Дополнительный бонус: нарисуйте стрелку на краю карты, указывающую на координату, если координата выходит за границы изображения.

Я хотел бы сделать это без использования библиотеки, такой как proj, чтобы не приходилось связывать большую библиотеку и понимать, что я делаю и почему.

Как вы, наверное, догадались, знаете, я пишу это в Objective-C. Ваш ответ не обязательно должен быть в Objective-C.

Ответы [ 3 ]

3 голосов
/ 18 сентября 2010

Если я правильно понимаю, вам нужно сделать две вещи. Во-первых, поместите ваше пользовательское изображение в вид карты, и ваши плитки будут отображаться с правильными координатами, затем панорамирование, масштабирование и т.д. Второе, что вам нужно сделать, это нарисовать точку на этом изображении на определенной широте и долготе.

Вам нужно пользовательских оверлеев , доступных в iOS 4 и более поздних версиях. Лучшее место, чтобы узнать о пользовательских оверлеях - видео WWDC 2010 под названием «Сессия 127 - Настройка карт с помощью оверлеев». Для видео также доступен специальный код. В видео докладчик создает пользовательскую карту и встраивает ее в MKMapView. Он также описывает инструмент, который вы можете использовать для создания своих плиток (чтобы разрезать их, получить их формы в проекции Меркатора и правильно назвать их). Его карта сканируется с морской карты, а затем помещается поверх обычного вида карты.

Вы сможете использовать boundingMapRect для создания прямоугольника границ путем преобразования границ вашей пользовательской карты в точки. Вы можете конвертировать между точками и координатами, используя MKMapPointForCoordinate и MKCoordinateForMapPoint.

Что касается рисования точки на карте, вы можете сделать это несколькими способами. Самое простое - просто использовать пользовательский MKAnnotationView с точкой в ​​качестве изображения. Таким образом, изображение не увеличивается и не сжимается при увеличении. Если вы хотите, чтобы точка росла и сужалась, вы должны использовать для этого и собственное наложение. Вы можете легко использовать MKCircleView, который является подклассом MKOverlayView

Для стрелки вы можете использовать обычный вид и поворачивать ее (и размещать на одной стороне экрана) в соответствии с направлением вашей точки за пределами допустимых границ. Используйте MKMapPointForCoordinate, а затем рассчитайте направление от центра вашего взгляда.

Но вашим лучшим источником будет это видео. Он углубляется во весь процесс и дает источник для рабочего приложения, что на 90% больше, чем нужно для вашей собственной карты.

3 голосов
/ 22 сентября 2010

После некоторых исследований я написал свою собственную библиотеку: libPirateMap .Это не очень хорошо, но это работает.

В случае, если ссылка не работает, я вставлю соответствующий исходный код сюда.

Использование:

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

Соответствует.m-код.

#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 голос
/ 12 сентября 2010

Вы изучали использование MapKit?У него есть методы для преобразования координат карты для просмотра координат.Посмотрите на семейство методов convert.

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

Если вы используете только 4.0, вы также можете воспользоваться классом наложения.*http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKOverlayView_class/Reference/Reference.html

Ура!

...