MKTileOverlay with gdal2tiles or other TMS tiles

Mon, 24. Aug 2015

Categories: en development Tags: gdal gdal2tiles iOS Map MKTileOverlay Overlay Tile

from iOS 7.0 onward there’s the neat MKTileOverlay::initWithURLTemplate: for tiled overlay maps.

Sadly it can’t display old-school Tile Map Service maps as e.g. produced by gdal2tiles.py1) because the y-values are flipped upside down. The OSM Wiki says about this fact: „This is really just an unfortunate historical misalignment.“

But with the drop-in MKTileOverlay replacement below, you can use flipped geometries and add {-y} in the URL template to indicate such:

 1#import <MapKit/MKTileOverlay.h>
 2// Copyright (c) 2015 Marcus Rohrmoser http://mro.name/me. All rights reserved.
 3//
 4// This program is free software: you can redistribute it and/or modify
 5// it under the terms of the GNU General Public License as published by
 6// the Free Software Foundation, either version 3 of the License, or
 7// (at your option) any later version.
 8//
 9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
17// interface unchanged
18@interface MKTileOverlayOSMorTMS : MKTileOverlay
19@end
20
21/**
22 * OSM: http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenames&oldid=1201902#X_and_Y
23 * TSM: http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification
24 *
25 * http://wiki.openstreetmap.org/w/index.php?title=Slippy_map_tilenames&oldid=1201902#Tile_numbers_to_lat..2Flon._.2F_Coordinates_to_tile_numbers_.2F_Sample_of_usage.2C_with_optional_tms-format_support
26 * const MKTileOverlayPath p0 = { x : 70406, y : 42987, z:17 };
27 * const MKTileOverlayPath p1 = convertYfromOSMtoTMS(p0);
28 * assert(88084 == p1.y && "");
29 */
30static inline MKTileOverlayPath convertYfromOSMtoTMS(MKTileOverlayPath path)
31{
32  assert( (1 << path.z) == (NSInteger)pow(2, path.z) && "oops, pow failed" );
33  path.y = (1 << path.z) - 1 - path.y;
34  return path;
35}
36
37@implementation MKTileOverlayOSMorTMS
38
39/** Detect `{-y}` in case and set `geometryFlipped` accordingly.
40 */
41-(instancetype)initWithURLTemplate:(NSString *)URLTemplate
42{
43  NSString *t = [URLTemplate stringByReplacingOccurrencesOfString:@"{-y}" withString:@"{y}"];
44  if( self = [super initWithURLTemplate:t] ) {
45    // NSParameterAssert(256.0f == self.tileSize.width);
46    NSParameterAssert(256.0f == self.tileSize.height);
47    NSParameterAssert(t.length == URLTemplate.length || t.length + 1 == URLTemplate.length);
48    self.geometryFlipped = t.length < URLTemplate.length;
49  }
50  return self;
51}
52
53-(NSURL *)URLForTilePath:(MKTileOverlayPath)path
54{
55  if( self.geometryFlipped ) {
56    // NSParameterAssert(256.0f == self.tileSize.width);
57    NSParameterAssert(256.0f == self.tileSize.height);
58    path = convertYfromOSMtoTMS(path);
59  }
60  MRLogD(@"%ld,%ld,%ld", (long)path.z, (long)path.x, (long)path.y, nil);
61  return [super URLForTilePath:path];
62}
63@end

1) see also the debian package python-gdal or the webpage of Petr Přidal, the author of gdal2tiles with a hint to it’s commercial successor.