/
WMOverlayView (MacBookAir3,1 上の問題のあるコピー 2012-09-27).m
158 lines (129 loc) · 6.91 KB
/
WMOverlayView (MacBookAir3,1 上の問題のあるコピー 2012-09-27).m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
//
// WMOverlayView.m
// WorldMap
//
// Created by kishikawa katsumi on 2012/09/26.
// Copyright (c) 2012 kishikawa katsumi. All rights reserved.
//
#import "WMOverlayView.h"
#import "WMOverlay.h"
@implementation WMOverlayView
/**
* Given a MKMapRect, this reprojects the center of the mapRect
* into the Mercator projection and calculates the rect's top-left point
* (so that we can later figure out the tile coordinate).
*
* See http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Derivation_of_tile_names
*/
- (CGPoint)mercatorTileOriginForMapRect:(MKMapRect)mapRect {
MKCoordinateRegion region = MKCoordinateRegionForMapRect(mapRect);
// Convert lat/lon to radians
CGFloat x = (region.center.longitude) * (M_PI / 180.0f); // Convert lon to radians
CGFloat y = (region.center.latitude) * (M_PI / 180.0f); // Convert lat to radians
y = log(tan(y) + 1.0f / cos(y));
// X and Y should actually be the top-left of the rect (the values above represent
// the center of the rect)
x = (1.0f + (x / M_PI)) / 2.0f;
y = (1.0f - (y / M_PI)) / 2.0f;
return CGPointMake(x, y);
}
- (NSUInteger)zoomLevelForZoomScale:(MKZoomScale)zoomScale
{
CGFloat realScale = zoomScale / [[UIScreen mainScreen] scale];
NSUInteger zoomLevel = (NSUInteger)(log(realScale) / log(2.0) + 20.0);
return zoomLevel;
}
- (NSUInteger)worldTileWidthForZoomLevel:(NSUInteger)zoomLevel
{
return (NSUInteger)(pow(2, zoomLevel));
}
- (CGFloat)tileWidthForZoomLevel:(NSUInteger)zoomLevel
{
CGFloat scale = [[UIScreen mainScreen] scale];
return 1.0f / (pow(2, zoomLevel) * scale);
}
- (CGRect)contentsRectForMercatorPoint:(CGPoint)mercatorPoint tileX:(NSInteger)tilex tileY:(NSInteger)tiley zoomLevel:(NSUInteger)zoomLevel
{
NSInteger scale = [[UIScreen mainScreen] scale];
CGFloat tileWidth = [self tileWidthForZoomLevel:zoomLevel];
for (NSInteger x = 0; x < scale; x++) {
for (NSInteger y = 0; y < scale; y++) {
CGRect rect = CGRectMake(tileWidth * (tilex * scale) + tileWidth * x,
tileWidth * (tiley * scale) + tileWidth * y,
tileWidth,
tileWidth);
if (CGRectContainsPoint(rect, mercatorPoint)) {
return CGRectMake(tileWidth * x, tileWidth * y, tileWidth, tileWidth);
}
}
}
return CGRectZero;
}
- (BOOL)canDrawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale {
WMOverlay *overlay = self.overlay;
NSUInteger zoomLevel = [self zoomLevelForZoomScale:zoomScale];
CGPoint mercatorPoint = [self mercatorTileOriginForMapRect:mapRect];
NSUInteger tilex = floor(mercatorPoint.x * [self worldTileWidthForZoomLevel:zoomLevel]);
NSUInteger tiley = floor(mercatorPoint.y * [self worldTileWidthForZoomLevel:zoomLevel]);
NSInteger scale = [[UIScreen mainScreen] scale];
NSString *path = [NSString stringWithFormat:@"x=%d&y=%d&z=%d&scale=%d", tilex, tiley, zoomLevel, scale];
NSURL *URL = [overlay imageURLWithTilePath:path];
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%d%d%d+%d", tilex, tiley, zoomLevel, overlay.mapType]];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
return YES;
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:10.0];
// NSLog(@"%@", URL.absoluteString);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(queue, ^{
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[data writeToFile:filePath atomically:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplayInMapRect:mapRect zoomScale:zoomScale];
});
});
return YES;
}
}
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context {
WMOverlay *overlay = self.overlay;
NSUInteger zoomLevel = [self zoomLevelForZoomScale:zoomScale];
CGPoint mercatorPoint = [self mercatorTileOriginForMapRect:mapRect];
NSUInteger tilex = floor(mercatorPoint.x * [self worldTileWidthForZoomLevel:zoomLevel]);
NSUInteger tiley = floor(mercatorPoint.y * [self worldTileWidthForZoomLevel:zoomLevel]);
NSInteger scale = [[UIScreen mainScreen] scale];
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%d%d%d+%d", tilex, tiley, zoomLevel, overlay.mapType]];
NSData *imageData = [NSData dataWithContentsOfFile:path];
if (imageData) {
UIImage *image = [UIImage imageWithData:imageData];
CGFloat tileWidth = [self tileWidthForZoomLevel:zoomLevel];
CGRect nwRect = CGRectMake(tileWidth * (tilex * scale), tileWidth * (tiley * scale), tileWidth, tileWidth);
CGRect neRect = CGRectMake(nwRect.origin.x + tileWidth, nwRect.origin.y, tileWidth, tileWidth);
CGRect swRect = CGRectMake(nwRect.origin.x, nwRect.origin.y + tileWidth, tileWidth, tileWidth);
CGRect seRect = CGRectMake(nwRect.origin.x + tileWidth, nwRect.origin.y + tileWidth, tileWidth, tileWidth);
CGRect contentsRect = CGRectZero;
CGSize imageSize = image.size;
if (CGRectContainsPoint(nwRect, mercatorPoint)) {
contentsRect = CGRectMake(0.0f, 0.0f, imageSize.width / scale, imageSize.height / scale);
} else if (CGRectContainsPoint(neRect, mercatorPoint)) {
contentsRect = CGRectMake(imageSize.width / scale, 0.0f, imageSize.width / scale, imageSize.height / scale);
} else if (CGRectContainsPoint(swRect, mercatorPoint)) {
contentsRect = CGRectMake(0.0f, imageSize.height / scale, imageSize.width / scale, imageSize.height / scale);
} else if (CGRectContainsPoint(seRect, mercatorPoint)) {
contentsRect = CGRectMake(imageSize.width / scale, imageSize.height / scale, imageSize.width / scale, imageSize.height / scale);
}
CGImageRef croppedImage = CGImageCreateWithImageInRect(image.CGImage, contentsRect);
CGRect rect = [self rectForMapRect:mapRect];
CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM(context, 1.0f / zoomScale, 1.0f / zoomScale);
CGContextTranslateCTM(context, 0.0f, image.size.height/2);
CGContextScaleCTM(context, 1.0f, -1.0f);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, image.size.width /2, image.size.height/2), croppedImage);
}/* else {
UIGraphicsPushContext(context);
UIImage *image = [UIImage imageNamed:@"LoadingTile"];
[image drawInRect:[self rectForMapRect:mapRect]];
UIGraphicsPopContext();
}*/
}
@end