1
0
mirror of https://github.com/danog/Telegram.git synced 2025-01-22 05:52:06 +01:00
Telegram/Telegraph/TGLocationUtils.m

301 lines
10 KiB
Mathematica
Raw Normal View History

2015-10-01 19:19:52 +03:00
#import "TGLocationUtils.h"
#import <MapKit/MapKit.h>
@implementation TGLocationUtils
+ (MKMapRect)MKMapRectForCoordinateRegion:(MKCoordinateRegion)region
{
MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta / 2,
region.center.longitude - region.span.longitudeDelta / 2));
MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta / 2,
region.center.longitude + region.span.longitudeDelta / 2));
return MKMapRectMake(MIN(a.x,b.x), MIN(a.y,b.y), ABS(a.x-b.x), ABS(a.y-b.y));
}
+ (bool)requestWhenInUserLocationAuthorizationWithLocationManager:(CLLocationManager *)locationManager
{
CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus];
if (authorizationStatus == kCLAuthorizationStatusDenied || authorizationStatus == kCLAuthorizationStatusRestricted)
return false;
if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])
{
[locationManager requestWhenInUseAuthorization];
return true;
}
return false;
}
+ (NSString *)stringFromDistance:(CLLocationDistance)distance
{
if (iosMajorVersion() >= 7)
return [[self sharedDistanceFormatter] stringFromDistance:distance];
else
return [self _customStringFromDistance:distance];
}
+ (NSString *)stringFromAccuracy:(CLLocationAccuracy)accuracy
{
if (iosMajorVersion() >= 7)
return [[self sharedAccuracyFormatter] stringFromDistance:accuracy];
else
return [self _customStringFromDistance:accuracy];
}
+ (NSString *)_customStringFromDistance:(CLLocationDistance)distance
{
static bool metricUnits = true;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
NSLocale *locale = [NSLocale currentLocale];
metricUnits = [[locale objectForKey:NSLocaleUsesMetricSystem] boolValue];
});
NSString *distanceString = nil;
if (metricUnits)
{
if (distance >= 1000 * 1000)
distanceString = [[NSString alloc] initWithFormat:@"%.1fK km", distance / (1000.0 * 1000.0)];
else if (distance > 1000)
distanceString = [[NSString alloc] initWithFormat:@"%.1f km", distance / 1000.0];
else
distanceString = [[NSString alloc] initWithFormat:@"%d m", (int)distance];
}
else
{
double feetDistance = distance / 0.3048;
if (feetDistance >= 5280)
{
char buf[32];
snprintf(buf, 32, "%.1f", feetDistance / 5280.0);
bool dot = false;
for (int i = 0; i < 32; i++)
{
char c = buf[i];
if (c == '\0')
break;
else if (c < '0' || c > '9')
{
dot = true;
break;
}
}
distanceString = [[NSString alloc] initWithFormat:@"%s mile%s", buf, dot || feetDistance / 5280.0 > 1.0 ? "s" : ""];
}
else
{
distanceString = [[NSString alloc] initWithFormat:@"%d %s", (int)feetDistance, (int)feetDistance != 1 ? "feet" : "foot"];
}
}
return distanceString;
}
+ (MKDistanceFormatter *)sharedDistanceFormatter
{
static dispatch_once_t once;
static MKDistanceFormatter *distanceFormatter;
dispatch_once(&once, ^
{
distanceFormatter = [[MKDistanceFormatter alloc] init];
NSLocale *locale = [NSLocale currentLocale];
if ([[locale objectForKey:NSLocaleUsesMetricSystem] boolValue])
distanceFormatter.unitStyle = MKDistanceFormatterUnitStyleAbbreviated;
else
distanceFormatter.unitStyle = MKDistanceFormatterUnitStyleDefault;
});
return distanceFormatter;
}
+ (MKDistanceFormatter *)sharedAccuracyFormatter
{
static dispatch_once_t once;
static MKDistanceFormatter *accuracyFormatter;
dispatch_once(&once, ^
{
accuracyFormatter = [[MKDistanceFormatter alloc] init];
accuracyFormatter.unitStyle = MKDistanceFormatterUnitStyleFull;
});
return accuracyFormatter;
}
@end
const NSInteger TGGoogleMapsOffset = 268435456;
const CGFloat TGGoogleMapsRadius = TGGoogleMapsOffset / (CGFloat)M_PI;
@implementation TGLocationUtils (GoogleMaps)
+ (CLLocationCoordinate2D)adjustGMapCoordinate:(CLLocationCoordinate2D)coordinate withPixelOffset:(CGPoint)offset zoom:(NSInteger)zoom
{
return CLLocationCoordinate2DMake([self adjustGMapLatitude:coordinate.latitude withPixelOffset:(NSInteger)offset.y zoom:zoom], [self adjustGMapLongitude:coordinate.longitude withPixelOffset:(NSInteger)offset.x zoom:zoom]);
}
+ (CLLocationDegrees)adjustGMapLatitude:(CLLocationDegrees)latitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom
{
return [self _yToLatitude:([self _latitudeToY:latitude] + (offset << (21 - zoom)))];
}
+ (CLLocationDegrees)adjustGMapLongitude:(CLLocationDegrees)longitude withPixelOffset:(NSInteger)offset zoom:(NSInteger)zoom
{
return [self _xToLongitude:([self _longitudeToX:longitude] + (offset << (21 - zoom)))];
}
+ (NSInteger)_latitudeToY:(CLLocationDegrees)latitude
{
return (NSInteger)round(TGGoogleMapsOffset - TGGoogleMapsRadius * log((1 + sin(latitude * M_PI / 180.0)) / (1 - sin(latitude * M_PI / 180.0))) / 2);
}
+ (CLLocationDegrees)_yToLatitude:(NSInteger)y
{
return (M_PI_2 - 2 * atan(exp((y - TGGoogleMapsOffset) / TGGoogleMapsRadius))) * 180.0 / M_PI;
}
+ (NSInteger)_longitudeToX:(CLLocationDegrees)longitude
{
return (NSInteger)round(TGGoogleMapsOffset + TGGoogleMapsRadius * longitude * M_PI / 180);
}
+ (CLLocationDegrees)_xToLongitude:(NSInteger)x
{
return (x - TGGoogleMapsOffset) / TGGoogleMapsRadius * 180.0 / M_PI;
}
@end
@implementation TGLocationUtils (ThirdPartyAppLauncher)
#pragma mark Apple Maps
+ (void)openMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections locationName:(NSString *)locationName
{
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate
addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
[mapItem setName:locationName];
if (withDirections)
{
NSDictionary *options = @{ MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving };
MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
[MKMapItem openMapsWithItems:@[ currentLocationMapItem, mapItem ]
launchOptions:options];
}
else
{
[mapItem openInMapsWithLaunchOptions:nil];
}
}
#pragma mark Google Maps
+ (void)openGoogleMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections
{
NSURL *url = nil;
NSString *coordinatePair = [NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude];
if (withDirections)
{
url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"comgooglemaps-x-callback://?daddr=%@&directionsmode=driving&x-success=telegram://?resume=true&&x-source=Telegram", coordinatePair]];
}
else
{
url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"comgooglemaps-x-callback://?center=%@&q=%@&x-success=telegram://?resume=true&&x-source=Telegram", coordinatePair, coordinatePair]];
}
[[UIApplication sharedApplication] openURL:url];
}
+ (bool)isGoogleMapsInstalled
{
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps-x-callback://"]];
}
+ (void)openGoogleWithPlaceId:(NSString *)placeId
{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://maps.google.com/maps/place?cid=%@", placeId]];
[[UIApplication sharedApplication] openURL:url];
}
#pragma mark Foursquare
+ (void)openFoursquareWithVenueId:(NSString *)venueId
{
NSURL *url = nil;
if ([self isFoursquareInstalled])
url = [NSURL URLWithString:[NSString stringWithFormat:@"foursquare://venues/%@", venueId]];
else
url = [NSURL URLWithString:[NSString stringWithFormat:@"https://foursquare.com/venue/%@", venueId]];
[[UIApplication sharedApplication] openURL:url];
}
+ (bool)isFoursquareInstalled
{
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"foursquare://"]];
}
#pragma mark Here Maps
+ (void)openHereMapsWithCoordinate:(CLLocationCoordinate2D)coordinate
{
NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"here-location://%f,%f", coordinate.latitude, coordinate.longitude]];
[[UIApplication sharedApplication] openURL:url];
}
+ (bool)isHereMapsInstalled
{
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"here-location://"]];
}
#pragma mark Yandex Maps
+ (void)openYandexMapsWithCoordinate:(CLLocationCoordinate2D)coordinate withDirections:(bool)withDirections
{
NSURL *url = nil;
if (withDirections)
{
url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexmaps://build_route_on_map?lat_to=%f&lon_to=%f", coordinate.latitude, coordinate.longitude]];
}
else
{
url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexmaps://maps.yandex.ru/?pt=%f,%f&z=16", coordinate.longitude, coordinate.latitude]];
}
[[UIApplication sharedApplication] openURL:url];
}
+ (bool)isYandexMapsInstalled
{
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"yandexmaps://"]];
}
#pragma mark Yandex Navigator
+ (void)openDirectionsInYandexNavigatorWithCoordinate:(CLLocationCoordinate2D)coordinate
{
NSURL *url = [NSURL URLWithString:[[NSString alloc] initWithFormat:@"yandexnavi://build_route_on_map?lat_to=%f&lon_to=%f", coordinate.latitude, coordinate.longitude]];
[[UIApplication sharedApplication] openURL:url];
}
+ (bool)isYandexNavigatorInstalled
{
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"yandexnavi://"]];
}
@end