Created
May 18, 2011 06:02
-
-
Save zssz/978056 to your computer and use it in GitHub Desktop.
IZOSMShortLink
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// IZOSMShortLink.h | |
// OpenMaps | |
// | |
// Created by Zsombor Szabó on 2/2/10. | |
// Copyright 2010 IZE. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
@interface IZOSMShortLink : NSObject { | |
NSNumber *_latitude; | |
NSNumber *_longitude; | |
NSNumber *_zoomlevel; | |
NSString *_string; | |
} | |
- (id)initWithLatitude:(NSNumber *)latitude longitude:(NSNumber *)longitude zoomlevel:(NSNumber *)zoomlevel; | |
- (id)initWithString:(NSString *)string; | |
@property (nonatomic, retain) NSNumber *latitude; | |
@property (nonatomic, retain) NSNumber *longitude; | |
@property (nonatomic, retain) NSNumber *zoomlevel; | |
@property (nonatomic, retain) NSString *string; | |
+ (BOOL)isValidShortLinkString:(NSString *)string; | |
- (NSString *)osmShortURLString; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// IZOSMShortLink.m | |
// OpenMaps | |
// | |
// Created by Zsombor Szabó on 2/2/10. | |
// Copyright 2010 IZE. All rights reserved. | |
// | |
#import "IZOSMShortLink.h" | |
#import "RegexKitLite.h" | |
@implementation IZOSMShortLink | |
@synthesize latitude=_latitude; | |
@synthesize longitude=_longitude; | |
@synthesize zoomlevel=_zoomlevel; | |
@synthesize string=_string; | |
static NSString *shortLinkCharArray = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; | |
- (id)initWithLatitude:(NSNumber *)latitude longitude:(NSNumber *)longitude zoomlevel:(NSNumber *)zoomlevel | |
{ | |
if (self = [super init]) | |
{ | |
self.latitude = latitude; | |
self.longitude = longitude; | |
self.zoomlevel = zoomlevel; | |
// Calculate string | |
long long x = round(([longitude doubleValue] + 180.0) * ((1 << 30) / 90.0)); | |
long long y = round(([latitude doubleValue] + 90.0) * ((1 << 30) / 45.0)); | |
long long c1 = 0, c2 = 0; | |
for (int i = 31; i > 16; --i) | |
{ | |
c1 = (c1 << 1) | ((x >> i) & 1); | |
c1 = (c1 << 1) | ((y >> i) & 1); | |
} | |
for (int i = 16; i > 1; --i) | |
{ | |
c2 = (c2 << 1) | ((x >> i) & 1); | |
c2 = (c2 << 1) | ((y >> i) & 1); | |
} | |
NSMutableString *str = [[NSMutableString alloc] init]; | |
int zoom = [self.zoomlevel intValue]; | |
int digit; | |
for (int i = 0; i < ceil((zoom + 8) / 3.0) && i < 5; ++i) | |
{ | |
digit = (c1 >> (24 - 6 * i)) & 0x3f; | |
[str appendFormat:@"%c", [shortLinkCharArray characterAtIndex:digit]]; | |
} | |
for (int i = 5; i < ceil((zoom + 8) / 3.0); ++i) | |
{ | |
digit = (c2 >> (24 - 6 * (i - 5))) & 0x3f; | |
[str appendFormat:@"%c", [shortLinkCharArray characterAtIndex:digit]]; | |
} | |
for (int i = 0; i < ((zoom + 8) % 3); ++i) | |
{ | |
[str appendString:@"-"]; | |
} | |
self.string = str; | |
[str release]; | |
} | |
return self; | |
} | |
+ (BOOL)isValidShortLinkString:(NSString *)string | |
{ | |
return [string isMatchedByRegex:@"[A-Za-z0-9_@]+"]; | |
} | |
- (id)initWithString:(NSString *)string | |
{ | |
if (self = [super init]) | |
{ | |
self.string = string; | |
// Calculate latitude, longitude, zoomlevel | |
if ([IZOSMShortLink isValidShortLinkString:self.string] == NO) | |
return nil; | |
NSString *m = [self.string stringByMatching:@"[A-Za-z0-9_@]+"]; | |
int zoom = [m length]*2+[string length]-11; | |
long long c1 = 0; | |
long long c2 = 0; | |
for (int i = 0, j = 54; i < [m length]; i++, j-= 6) | |
{ | |
//int bits = [shortLinkCharArray rangeOfString: | |
unsigned int bits = [shortLinkCharArray rangeOfString: | |
[NSString stringWithFormat:@"%c", [m characterAtIndex:i]]].location; | |
if (j <= 30) | |
//c1 |= bits >>> (30-j); | |
c1 |= bits >> (30-j); | |
else if (j > 30) | |
c1 |= bits << (j-30); | |
if (j < 30) | |
//c2 |= (bits & (0x3fffffff >>> j)) << j; | |
c2 |= (bits & (0x3fffffff >> j)) << j; | |
} | |
long long x = 0; | |
long long y = 0; | |
for (int j=29; j>0;) | |
{ | |
x = (x << 1) | ((c1 >> j--) & 1); | |
y = (y << 1) | ((c1 >> j--) & 1); | |
} | |
for (int j=29; j>0;) | |
{ | |
x = (x << 1) | ((c2 >> j--) & 1); | |
y = (y << 1) | ((c2 >> j--) & 1); | |
} | |
x *= 4; // We can’t do <<= 2 here as x and y may be greater than 2³¹ and then the value would become negative | |
y *= 4; | |
double lon = x*90.0/(1<<30)-180.0; | |
double lat = y*45.0/(1<<30)-90.0; | |
self.latitude = [NSNumber numberWithDouble:lat]; | |
self.longitude = [NSNumber numberWithDouble:lon]; | |
self.zoomlevel = [NSNumber numberWithInt:zoom]; | |
} | |
return self; | |
} | |
- (NSString *)osmShortURLString | |
{ | |
return [NSString stringWithFormat:@"http://osm.org/go/%@", self.string]; | |
} | |
- (void)dealloc | |
{ | |
self.latitude = nil; | |
self.longitude = nil; | |
self.zoomlevel = nil; | |
self.string = nil; | |
[super dealloc]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment