Jer*_*oen 15 iphone cocoa-touch core-graphics objective-c mapkit
更新:
使用MKOverlayView投影在MKMapView上的图像使用墨卡托投影,而我用作输入数据的图像使用WGS84投影.有没有办法将输入图像转换为正确的投影WGS84 - >墨卡托,没有平铺图像,可以在运行中完成吗?
通常,您可以使用程序gdal2tiles将图像转换为右投影.然而,输入数据每十五分钟改变一次,因此图像必须每十五分钟转换一次.所以转换必须在飞行中完成.我也想平铺由Mapkit完成,而不是通过使用gdal2tiles或GDAL框架自己.
更新结束
我目前正在开展一个项目,在世界某些地方展示降雨雷达.雷达图像是由欧洲气象卫星应用组织提供的,他们提供可以被加载到谷歌地球或谷歌地图KML文件.如果我加载在谷歌地图的KML文件,它显示完美,但如果我画上的MKMapView使用MKOverlayView的图像时,图像略微的.
例如,在左侧,Google地图和右侧,相同的图像显示在MKMapView上.


该图像覆盖可以被看作表面谷歌地图,即用于图像的卫星是"气象卫星0度"卫星.
这两个图像覆盖面大小是一样的,这是从KML文件LatLonBox,它指定了顶部,底部,右侧和左侧地面叠加的边界框的两侧对齐.
<LatLonBox id="GE_MET0D_VP-MPE-latlonbox">
<north>57.4922</north>
<south>-57.4922</south>
<east>57.4922</east>
<west>-57.4922</west>
<rotation>0</rotation>
</LatLonBox>
Run Code Online (Sandbox Code Playgroud)
我用这些参数创建了一个名为RadarOverlay的新自定义MKOverlay对象,
[[RadarOverlay alloc] initWithImageData:[[self.currentRadarData objectAtIndex:0] valueForKey:@"Image"] withLowerLeftCoordinate:CLLocationCoordinate2DMake(-57.4922, -57.4922) withUpperRightCoordinate:CLLocationCoordinate2DMake(57.4922, 57.4922)];
Run Code Online (Sandbox Code Playgroud)
自定义MKOverlay对象的实现; RadarOverlay
- (id) initWithImageData:(NSData*) imageData withLowerLeftCoordinate:(CLLocationCoordinate2D)lowerLeftCoordinate withUpperRightCoordinate:(CLLocationCoordinate2D)upperRightCoordinate
{
self.radarData = imageData;
MKMapPoint lowerLeft = MKMapPointForCoordinate(lowerLeftCoordinate);
MKMapPoint upperRight = MKMapPointForCoordinate(upperRightCoordinate);
mapRect = MKMapRectMake(lowerLeft.x, upperRight.y, upperRight.x - lowerLeft.x, lowerLeft.y - upperRight.y);
return self;
}
- (CLLocationCoordinate2D)coordinate
{
return MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMidX(mapRect), MKMapRectGetMidY(mapRect)));
}
- (MKMapRect)boundingMapRect
{
return mapRect;
}
Run Code Online (Sandbox Code Playgroud)
自定义MKOverlayView,RadarOverlayView的实现
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
RadarOverlay* radarOverlay = (RadarOverlay*) self.overlay;
UIImage *image = [[UIImage alloc] initWithData:radarOverlay.radarData];
CGImageRef imageReference = image.CGImage;
MKMapRect theMapRect = [self.overlay boundingMapRect];
CGRect theRect = [self rectForMapRect:theMapRect];
CGRect clipRect = [self rectForMapRect:mapRect];
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
CGContextSetAlpha(context, [preferences floatForKey:@"RadarTransparency"]);
CGContextAddRect(context, clipRect);
CGContextClip(context);
CGContextDrawImage(context, theRect, imageReference);
[image release];
}
Run Code Online (Sandbox Code Playgroud)
当我下载图像时,我翻转图像,以便可以在MKOverlayView中轻松绘制
size_t width = (CGImageGetWidth(imageReference) / self.scaleFactor);
size_t height = (CGImageGetHeight(imageReference) / self.scaleFactor);
// Calculate colorspace for the specified image
CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageReference);
// Allocate and clear memory for the data of the image
unsigned char *imageData = (unsigned char*) malloc(height * width * 4);
memset(imageData, 0, height * width * 4);
// Define the rect for the image
CGRect imageRect;
if(image.imageOrientation==UIImageOrientationUp || image.imageOrientation==UIImageOrientationDown)
imageRect = CGRectMake(0, 0, width, height);
else
imageRect = CGRectMake(0, 0, height, width);
// Create the imagecontext by defining the colorspace and the address of the location to store the data
CGContextRef imageContext = CGBitmapContextCreate(imageData, width, height, 8, width * 4, imageColorSpace, kCGImageAlphaPremultipliedLast);
CGContextSaveGState(imageContext);
// Scale the image to the opposite orientation so it can be easylier drawn with CGContectDrawImage
CGContextTranslateCTM(imageContext, 0, height);
CGContextScaleCTM(imageContext, 1.0, -1.0);
if(image.imageOrientation==UIImageOrientationLeft)
{
CGContextRotateCTM(imageContext, M_PI / 2);
CGContextTranslateCTM(imageContext, 0, -width);
}
else if(image.imageOrientation==UIImageOrientationRight)
{
CGContextRotateCTM(imageContext, - M_PI / 2);
CGContextTranslateCTM(imageContext, -height, 0);
}
else if(image.imageOrientation==UIImageOrientationDown)
{
CGContextTranslateCTM(imageContext, width, height);
CGContextRotateCTM(imageContext, M_PI);
}
// Draw the image in the context
CGContextDrawImage(imageContext, imageRect, imageReference);
CGContextRestoreGState(imageContext);
Run Code Online (Sandbox Code Playgroud)
在我翻转图像后,我操纵它然后将其作为NSData对象存储在内存中.
它看起来像图像被拉伸,但它看起来在图像的中心,这是在赤道.
您是否已经在WWDC 2010视频中看到过"会话127 - 使用叠加层自定义地图"?其中一个例子是地震数据,它给出0.5到0.5度区域的地震风险并对它们进行映射.基于正方形,您的雷达数据看起来很相似.示例代码有一个名为HazardMaps的完整应用程序,它使用MKMapPoints获取此数据并创建叠加层.如果你还没有看过这个视频,我想它会给你很多有用的信息.他还谈到转换为墨卡托投影.
要检查的另一件事是来自EUMETSAT的数据的坐标系(数据).Google Maps使用一个名为WGS-84的系统,这是一个通用标准.但是还有许多其他标准可以在世界不同地区提供更准确的位置.如果您使用谷歌地图中不同标准的纬度和经度,您的所有积分将会减少一定数量.偏移量不一致,当您在地图上移动时,它会发生变化.Google地图可能会对数据进行智能处理,并在运行中转换为WGS-84.
您可以通过查看KML找到更多详细信息.我看了,但找不到最终的KML,矩形.也许它提供了有关它在元数据中使用的坐标系的信息.
您的图像/叠加层很可能不再成比例(即它已被拉伸)。我在自己的应用程序中看到过这种情况,其中视图的中心是正确的,但是当您远离赤道向任一极(屏幕的顶部和底部)移动时,地图/叠加层变得越来越扭曲。
显然,您正在通过scaleFactor缩放图像。首先我会看一下。
size_t width = (CGImageGetWidth(imageReference) / self.scaleFactor);
size_t height = (CGImageGetHeight(imageReference) / self.scaleFactor);
Run Code Online (Sandbox Code Playgroud)
测试代码以查看缩放是否是罪魁祸首的另一个好方法是将 MKMapView 缩小到覆盖图像的大小。不要管覆盖图像,如果它不再扭曲,那么您就知道问题所在了。
| 归档时间: |
|
| 查看次数: |
11736 次 |
| 最近记录: |