在图像上绘制lat / lng点

时间:2010-09-11 17:45:45

标签: objective-c math map gis trigonometry

我有以下内容:

  • 图像 - 手绘地图 - 面积约600x400米。图像绘制在Google地图图块上。
  • 此图片角落的纬度/经度(来自Google地图)。或者换句话说,我有北纬和南纬以及图像的东西经度。
  • iPhone CoreLocation的纬度/经度坐标。

如何在此图像上绘制一个点(如果超出边界,则不显示任何内容),表示CoreLocation的坐标?

添加奖励:如果坐标超出图像范围,则在地图边缘绘制一个箭头,指向坐标。

我想在不使用类似proj的库的情况下这样做,以便不必捆绑大型库,并了解我在做什么以及为什么。

正如你可能猜到的那样,我是用Objective-C写的。不过,你的答案不一定是在Objective-C中。

3 个答案:

答案 0 :(得分:3)

如果我理解正确,你需要做两件事。第一种方法是将自定义图像放入地图视图中,让自定义图块显示在正确的坐标上,然后平移,缩放等。您需要做的第二件事是在某个纬度和经度上绘制一个点到该图像上。

您需要的是custom overlays,可在iOS 4及更高版本中使用。查找自定义叠加层的最佳位置是WWDC 2010 video,称为“会话127 - 使用叠加层自定义地图”。还有可用于视频的自定义代码。在视频中,演示者创建自定义地图并将其嵌入MKMapView中。他还描述了一个工具,您可以使用它来制作您的瓷砖(将它们剪切,将其形状放入墨卡托投影并正确命名)。他的地图从海洋地图扫描,然后放在法线地图视图的顶部。

您可以使用boundingMapRect通过将自定义地图的边界转换为点来创建边界矩形。您可以使用MKMapPointForCoordinateMKCoordinateForMapPoint在点和坐标之间进行转换。

至于在地图上绘制一个点,你可以用两种方法做到这一点。最简单的方法是使用带有点的自定义MKAnnotationView作为其图像。这样,在放大时图像不会增大和缩小。如果您希望点增长和缩小,您也应该使用自定义叠加。您可以轻松使用MKCircleView,它是MKOverlayView

的子类

对于箭头,您可以使用普通视图并根据您的越界点的方向旋转它(并将其放置在屏幕的一侧)。使用MKMapPointForCoordinate,然后根据视图中心计算直接输入。

但你最好的消息来源就是那个视频。他对整个过程进行了深入研究,并为工作应用程序提供了源代码,该应用程序占您自己地图所需内容的90%。

答案 1 :(得分:3)

经过一番研究,我编写了自己的图书馆: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-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

答案 2 :(得分:1)

您是否考虑过使用MapKit?它具有将地图坐标转换为视图坐标的方法。看看转换族方法。

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

干杯!