summaryrefslogtreecommitdiff
path: root/platform/darwin/src/MGLMapCamera.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/darwin/src/MGLMapCamera.mm')
-rw-r--r--platform/darwin/src/MGLMapCamera.mm125
1 files changed, 125 insertions, 0 deletions
diff --git a/platform/darwin/src/MGLMapCamera.mm b/platform/darwin/src/MGLMapCamera.mm
new file mode 100644
index 0000000000..93f3bd45e0
--- /dev/null
+++ b/platform/darwin/src/MGLMapCamera.mm
@@ -0,0 +1,125 @@
+#import "MGLMapCamera.h"
+
+#include <mbgl/util/projection.hpp>
+
+@implementation MGLMapCamera
+
++ (BOOL)supportsSecureCoding
+{
+ return YES;
+}
+
++ (instancetype)camera
+{
+ return [[self alloc] init];
+}
+
++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ fromEyeCoordinate:(CLLocationCoordinate2D)eyeCoordinate
+ eyeAltitude:(CLLocationDistance)eyeAltitude
+{
+ mbgl::LatLng centerLatLng = mbgl::LatLng(centerCoordinate.latitude, centerCoordinate.longitude);
+ mbgl::LatLng eyeLatLng = mbgl::LatLng(eyeCoordinate.latitude, eyeCoordinate.longitude);
+
+ mbgl::ProjectedMeters centerMeters = mbgl::Projection::projectedMetersForLatLng(centerLatLng);
+ mbgl::ProjectedMeters eyeMeters = mbgl::Projection::projectedMetersForLatLng(eyeLatLng);
+ CLLocationDirection heading = std::atan((centerMeters.northing - eyeMeters.northing) /
+ (centerMeters.easting - eyeMeters.easting));
+
+ double groundDistance = std::hypot(centerMeters.northing - eyeMeters.northing,
+ centerMeters.easting - eyeMeters.easting);
+ CGFloat pitch = std::atan(eyeAltitude / groundDistance);
+
+ return [[self alloc] initWithCenterCoordinate:centerCoordinate
+ altitude:eyeAltitude
+ pitch:pitch
+ heading:heading];
+}
+
++ (instancetype)cameraLookingAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ fromDistance:(CLLocationDistance)distance
+ pitch:(CGFloat)pitch
+ heading:(CLLocationDirection)heading
+{
+ return [[self alloc] initWithCenterCoordinate:centerCoordinate
+ altitude:distance
+ pitch:pitch
+ heading:heading];
+}
+
+- (instancetype)initWithCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
+ altitude:(CLLocationDistance)altitude
+ pitch:(CGFloat)pitch
+ heading:(CLLocationDirection)heading
+{
+ if (self = [super init])
+ {
+ _centerCoordinate = centerCoordinate;
+ _altitude = altitude;
+ _pitch = pitch;
+ _heading = heading;
+ }
+ return self;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)coder
+{
+ if (self = [super init])
+ {
+ _centerCoordinate = CLLocationCoordinate2DMake([coder decodeDoubleForKey:@"centerLatitude"],
+ [coder decodeDoubleForKey:@"centerLongitude"]);
+ _altitude = [coder decodeDoubleForKey:@"altitude"];
+ _pitch = [coder decodeDoubleForKey:@"pitch"];
+ _heading = [coder decodeDoubleForKey:@"heading"];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)coder
+{
+ [coder encodeDouble:_centerCoordinate.latitude forKey:@"centerLatitude"];
+ [coder encodeDouble:_centerCoordinate.longitude forKey:@"centerLongitude"];
+ [coder encodeDouble:_altitude forKey:@"altitude"];
+ [coder encodeDouble:_pitch forKey:@"pitch"];
+ [coder encodeDouble:_heading forKey:@"heading"];
+}
+
+- (id)copyWithZone:(nullable NSZone *)zone
+{
+ return [[[self class] allocWithZone:zone] initWithCenterCoordinate:_centerCoordinate
+ altitude:_altitude
+ pitch:_pitch
+ heading:_heading];
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@ %p centerCoordinate:%f, %f altitude:%.0fm heading:%.0f° pitch:%.0f°>",
+ NSStringFromClass([self class]), (void *)self, _centerCoordinate.latitude, _centerCoordinate.longitude, _altitude, _heading, _pitch];
+}
+
+- (BOOL)isEqual:(id)other
+{
+ if ( ! [other isKindOfClass:[self class]])
+ {
+ return NO;
+ }
+ if (other == self)
+ {
+ return YES;
+ }
+
+ MGLMapCamera *otherCamera = other;
+ return (_centerCoordinate.latitude == otherCamera.centerCoordinate.latitude
+ && _centerCoordinate.longitude == otherCamera.centerCoordinate.longitude
+ && _altitude == otherCamera.altitude
+ && _pitch == otherCamera.pitch && _heading == otherCamera.heading);
+}
+
+- (NSUInteger)hash
+{
+ return (@(_centerCoordinate.latitude).hash + @(_centerCoordinate.longitude).hash
+ + @(_altitude).hash + @(_pitch).hash + @(_heading).hash);
+}
+
+@end