Added sources
This commit is contained in:
parent
a453ded16f
commit
0ed858c769
|
@ -14,6 +14,10 @@
|
|||
454361D81E7BECE300656472 /* UTMConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 454361761E7BE75800656472 /* UTMConversion.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
454361D91E7BECE700656472 /* UTMConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 454361761E7BE75800656472 /* UTMConversion.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
454361DA1E7BECE900656472 /* UTMConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 454361761E7BE75800656472 /* UTMConversion.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
454361EE1E7C077E00656472 /* RadianDegrees.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454361EB1E7C077E00656472 /* RadianDegrees.swift */; };
|
||||
454361EF1E7C077E00656472 /* TMCoordinate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454361EC1E7C077E00656472 /* TMCoordinate.swift */; };
|
||||
454361F01E7C077E00656472 /* UTMConversion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454361ED1E7C077E00656472 /* UTMConversion.swift */; };
|
||||
454361F21E7C078D00656472 /* UTMConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 454361F11E7C078D00656472 /* UTMConversionTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -53,6 +57,10 @@
|
|||
454361CA1E7BE7B000656472 /* UTMConversion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UTMConversion.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
454361DB1E7BECFA00656472 /* Info-tvOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = "<group>"; };
|
||||
454361DE1E7BED1500656472 /* Info-tvOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = "<group>"; };
|
||||
454361EB1E7C077E00656472 /* RadianDegrees.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadianDegrees.swift; sourceTree = "<group>"; };
|
||||
454361EC1E7C077E00656472 /* TMCoordinate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TMCoordinate.swift; sourceTree = "<group>"; };
|
||||
454361ED1E7C077E00656472 /* UTMConversion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UTMConversion.swift; sourceTree = "<group>"; };
|
||||
454361F11E7C078D00656472 /* UTMConversionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UTMConversionTests.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -140,6 +148,9 @@
|
|||
454361761E7BE75800656472 /* UTMConversion.h */,
|
||||
454361DB1E7BECFA00656472 /* Info-tvOS.plist */,
|
||||
454361771E7BE75800656472 /* Info.plist */,
|
||||
454361EB1E7C077E00656472 /* RadianDegrees.swift */,
|
||||
454361EC1E7C077E00656472 /* TMCoordinate.swift */,
|
||||
454361ED1E7C077E00656472 /* UTMConversion.swift */,
|
||||
);
|
||||
path = UTMConversion;
|
||||
sourceTree = "<group>";
|
||||
|
@ -149,6 +160,7 @@
|
|||
children = (
|
||||
454361DE1E7BED1500656472 /* Info-tvOS.plist */,
|
||||
454361831E7BE75800656472 /* Info.plist */,
|
||||
454361F11E7C078D00656472 /* UTMConversionTests.swift */,
|
||||
);
|
||||
path = UTMConversionTests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -445,6 +457,10 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
454361EF1E7C077E00656472 /* TMCoordinate.swift in Sources */,
|
||||
454361F01E7C077E00656472 /* UTMConversion.swift in Sources */,
|
||||
454361F21E7C078D00656472 /* UTMConversionTests.swift in Sources */,
|
||||
454361EE1E7C077E00656472 /* RadianDegrees.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -654,6 +670,7 @@
|
|||
4543618B1E7BE75800656472 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
DEVELOPMENT_TEAM = 7L5H8T8QE3;
|
||||
INFOPLIST_FILE = UTMConversionTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
|
@ -666,6 +683,7 @@
|
|||
4543618C1E7BE75800656472 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
DEVELOPMENT_TEAM = 7L5H8T8QE3;
|
||||
INFOPLIST_FILE = UTMConversionTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// RadianDegrees.swift
|
||||
// UTMConversion
|
||||
//
|
||||
// Created by Peter Ringset on 16/03/2017.
|
||||
// Copyright © 2017 WTW. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
func toDegrees(radians: Double) -> Double {
|
||||
return radians * 180 / M_PI
|
||||
}
|
||||
|
||||
func toRadians(degrees: Double) -> Double {
|
||||
return degrees / 180 * M_PI
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
//
|
||||
// TMCoordinate.swift
|
||||
// UTMConversion
|
||||
//
|
||||
// Created by Peter Ringset on 16/03/2017.
|
||||
// Copyright © 2017 WTW. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreLocation
|
||||
import Foundation
|
||||
|
||||
private let utmScaleFactor = 0.9996
|
||||
|
||||
struct TMCoordinate {
|
||||
let northing: Double
|
||||
let easting: Double
|
||||
|
||||
init(northing: Double, easting: Double) {
|
||||
self.northing = northing
|
||||
self.easting = easting
|
||||
}
|
||||
|
||||
init(utmCoordinate: UTMCoordinate) {
|
||||
easting = (utmCoordinate.easting - 500000.0) / utmScaleFactor;
|
||||
northing = {
|
||||
/* If in southern hemisphere, adjust y accordingly. */
|
||||
if case .southern = utmCoordinate.hemisphere {
|
||||
return (utmCoordinate.northing - 10000000.0) / utmScaleFactor
|
||||
} else {
|
||||
return utmCoordinate.northing / utmScaleFactor
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
init(coordinate: CLLocationCoordinate2D, centralMeridian lambda0: Double, datum: UTMDatum) {
|
||||
let phi = toRadians(degrees: coordinate.latitude) // Latitude in radians
|
||||
let lambda = toRadians(degrees: coordinate.longitude) // Longitude in radians
|
||||
|
||||
let equitorialRadus = datum.equitorialRadius
|
||||
let polarRadius = datum.polarRadius
|
||||
|
||||
/* Precalculate ep2 */
|
||||
let ep2 = (pow(equitorialRadus, 2.0) - pow(polarRadius, 2.0)) / pow(polarRadius, 2.0)
|
||||
|
||||
/* Precalculate nu2 */
|
||||
let nu2 = ep2 * pow(cos(phi), 2.0)
|
||||
|
||||
/* Precalculate N */
|
||||
let N = pow(equitorialRadus, 2.0) / (polarRadius * sqrt(1 + nu2))
|
||||
|
||||
/* Precalculate t */
|
||||
let t = tan(phi)
|
||||
let t2 = t * t
|
||||
|
||||
/* Precalculate l */
|
||||
let l = lambda - lambda0
|
||||
|
||||
/* Precalculate coefficients for l**n in the equations below
|
||||
so a normal human being can read the expressions for easting
|
||||
and northing
|
||||
-- l**1 and l**2 have coefficients of 1.0 */
|
||||
let l3coef = 1.0 - t2 + nu2
|
||||
let l4coef = 5.0 - t2 + 9 * nu2 + 4.0 * (nu2 * nu2)
|
||||
let l5coef = 5.0 - 18.0 * t2 + (t2 * t2) + 14.0 * nu2 - 58.0 * t2 * nu2
|
||||
let l6coef = 61.0 - 58.0 * t2 + (t2 * t2) + 270.0 * nu2 - 330.0 * t2 * nu2
|
||||
let l7coef = 61.0 - 479.0 * t2 + 179.0 * (t2 * t2) - (t2 * t2 * t2)
|
||||
let l8coef = 1385.0 - 3111.0 * t2 + 543.0 * (t2 * t2) - (t2 * t2 * t2)
|
||||
|
||||
let arcLengthOfMeridian: (Double, UTMDatum) -> Double = { latitudeInRadians, datum in
|
||||
let equitorialRadus = datum.equitorialRadius
|
||||
let polarRadius = datum.polarRadius
|
||||
|
||||
/* Precalculate n */
|
||||
let n = (equitorialRadus - polarRadius) / (equitorialRadus + polarRadius)
|
||||
|
||||
/* Precalculate alpha */
|
||||
let alpha = ((equitorialRadus + polarRadius) / 2.0) * (1.0 + (pow(n, 2.0) / 4.0) + (pow(n, 4.0) / 64.0))
|
||||
|
||||
/* Precalculate beta */
|
||||
let beta = (-3.0 * n / 2.0) + (9.0 * pow(n, 3.0) / 16.0) + (-3.0 * pow(n, 5.0) / 32.0)
|
||||
|
||||
/* Precalculate gamma */
|
||||
let gamma = (15.0 * pow(n, 2.0) / 16.0) + (-15.0 * pow(n, 4.0) / 32.0)
|
||||
|
||||
/* Precalculate delta */
|
||||
let delta = (-35.0 * pow(n, 3.0) / 48.0) + (105.0 * pow(n, 5.0) / 256.0)
|
||||
|
||||
/* Precalculate epsilon */
|
||||
let epsilon = (315.0 * pow(n, 4.0) / 512.0)
|
||||
|
||||
/* Now calculate the sum of the series and return */
|
||||
let result = alpha * (latitudeInRadians + (beta * sin(2.0 * latitudeInRadians)) + (gamma * sin(4.0 * latitudeInRadians)) + (delta * sin(6.0 * latitudeInRadians)) + (epsilon * sin(8.0 * latitudeInRadians)))
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/* Calculate easting (x) */
|
||||
easting = N * cos(phi) * l + (N / 6.0 * pow(cos(phi), 3.0) * l3coef * pow(l, 3.0)) + (N / 120.0 * pow(cos(phi), 5.0) * l5coef * pow(l, 5.0)) + (N / 5040.0 * pow(cos(phi), 7.0) * l7coef * pow(l, 7.0))
|
||||
|
||||
/* Calculate northing (y) */
|
||||
northing = arcLengthOfMeridian(phi, datum) + (t / 2.0 * N * pow(cos(phi), 2.0) * pow(l, 2.0)) + (t / 24.0 * N * pow(cos(phi), 4.0) * l4coef * pow(l, 4.0)) + (t / 720.0 * N * pow(cos(phi), 6.0) * l6coef * pow(l, 6.0)) + (t / 40320.0 * N * pow(cos(phi), 8.0) * l8coef * pow(l, 8.0))
|
||||
}
|
||||
|
||||
func utmCoordinate(zone: UTMGridZone, hemisphere: UTMHemisphere) -> UTMCoordinate {
|
||||
let x = easting * utmScaleFactor + 500000.0;
|
||||
let y: Double = {
|
||||
let scaled = northing * utmScaleFactor
|
||||
if scaled < 0.0 {
|
||||
return scaled + 10000000.0
|
||||
}
|
||||
return scaled
|
||||
}()
|
||||
|
||||
return UTMCoordinate(northing: y, easting: x, zone: zone, hemisphere: hemisphere)
|
||||
}
|
||||
|
||||
//
|
||||
// Converts x and y coordinates in the Transverse Mercator projection to a latitude/longitude pair. Note that Transverse Mercator is not the same as UTM a scale factor is required to convert between them.
|
||||
// Remarks:
|
||||
// The local variables Nf, nuf2, tf, and tf2 serve the same purpose as N, nu2, t, and t2 in MapLatLonToXY, but they are computed with respect to the footpoint latitude phif.
|
||||
// x1frac, x2frac, x2poly, x3poly, etc. are to enhance readability and to optimize computations.
|
||||
func coordinate(centralMeridian lambda0: Double, datum: UTMDatum) -> CLLocationCoordinate2D {
|
||||
let x = easting
|
||||
let y = northing
|
||||
|
||||
let equitorialRadus = datum.equitorialRadius
|
||||
let polarRadius = datum.polarRadius
|
||||
|
||||
/* Get the value of phif, the footpoint latitude. */
|
||||
let phif = footpointLatitude(northingInMeters: y, datum: datum)
|
||||
|
||||
/* Precalculate ep2 */
|
||||
let ep2 = (pow(equitorialRadus, 2.0) - pow(polarRadius, 2.0)) / pow(polarRadius, 2.0)
|
||||
|
||||
/* Precalculate cos (phif) */
|
||||
let cf = cos(phif)
|
||||
|
||||
/* Precalculate nuf2 */
|
||||
let nuf2 = ep2 * pow(cf, 2.0)
|
||||
|
||||
/* Precalculate Nf and initialize Nfpow */
|
||||
let Nf = pow(equitorialRadus, 2.0) / (polarRadius * sqrt(1 + nuf2))
|
||||
var Nfpow = Nf
|
||||
|
||||
/* Precalculate tf */
|
||||
let tf = tan(phif)
|
||||
let tf2 = tf * tf
|
||||
let tf4 = tf2 * tf2
|
||||
|
||||
/* Precalculate fractional coefficients for x**n in the equations
|
||||
below to simplify the expressions for latitude and longitude. */
|
||||
let x1frac = 1.0 / (Nfpow * cf)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**2) */
|
||||
let x2frac = tf / (2.0 * Nfpow)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**3) */
|
||||
let x3frac = 1.0 / (6.0 * Nfpow * cf)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**4) */
|
||||
let x4frac = tf / (24.0 * Nfpow)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**5) */
|
||||
let x5frac = 1.0 / (120.0 * Nfpow * cf)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**6) */
|
||||
let x6frac = tf / (720.0 * Nfpow)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**7) */
|
||||
let x7frac = 1.0 / (5040.0 * Nfpow * cf)
|
||||
|
||||
Nfpow *= Nf /* now equals Nf**8) */
|
||||
let x8frac = tf / (40320.0 * Nfpow)
|
||||
|
||||
/* Precalculate polynomial coefficients for x**n.
|
||||
-- x**1 does not have a polynomial coefficient. */
|
||||
let x2poly = -1.0 - nuf2
|
||||
let x3poly = -1.0 - 2 * tf2 - nuf2
|
||||
let x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 * nuf2) - 9.0 * tf2 * (nuf2 * nuf2)
|
||||
let x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2
|
||||
let x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2
|
||||
let x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2)
|
||||
let x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2)
|
||||
|
||||
/* Calculate latitude */
|
||||
let latitudeRadians = phif + x2frac * x2poly * (x * x) + x4frac * x4poly * pow(x, 4.0) + x6frac * x6poly * pow(x, 6.0) + x8frac * x8poly * pow(x, 8.0)
|
||||
|
||||
/* Calculate longitude */
|
||||
let longitudeRadians = lambda0 + x1frac * x + x3frac * x3poly * pow(x, 3.0) + x5frac * x5poly * pow(x, 5.0) + x7frac * x7poly * pow(x, 7.0)
|
||||
|
||||
return CLLocationCoordinate2D(latitude: toDegrees(radians: latitudeRadians), longitude: toDegrees(radians: longitudeRadians))
|
||||
}
|
||||
|
||||
//
|
||||
// Computes the footpoint latitude for use in converting transverse Mercator coordinates to ellipsoidal coordinates.
|
||||
private func footpointLatitude(northingInMeters: Double, datum: UTMDatum) -> Double {
|
||||
let equitorialRadus = datum.equitorialRadius
|
||||
let polarRadius = datum.polarRadius
|
||||
|
||||
/* Precalculate n (Eq. 10.18) */
|
||||
let n = (equitorialRadus - polarRadius) / (equitorialRadus + polarRadius)
|
||||
|
||||
/* Precalculate alpha_ (Eq. 10.22) */
|
||||
/* (Same as alpha in Eq. 10.17) */
|
||||
let alpha = ((equitorialRadus + polarRadius) / 2.0) * (1 + (pow(n, 2.0) / 4) + (pow(n, 4.0) / 64))
|
||||
|
||||
/* Precalculate y (Eq. 10.23) */
|
||||
let y = northingInMeters / alpha
|
||||
|
||||
/* Precalculate beta (Eq. 10.22) */
|
||||
let beta = (3.0 * n / 2.0) + (-27.0 * pow(n, 3.0) / 32.0) + (269.0 * pow(n, 5.0) / 512.0)
|
||||
|
||||
/* Precalculate gamma (Eq. 10.22) */
|
||||
let gamma = (21.0 * pow(n, 2.0) / 16.0) + (-55.0 * pow(n, 4.0) / 32.0)
|
||||
|
||||
/* Precalculate delta (Eq. 10.22) */
|
||||
let delta = (151.0 * pow(n, 3.0) / 96.0) + (-417.0 * pow(n, 5.0) / 128.0)
|
||||
|
||||
/* Precalculate epsilon (Eq. 10.22) */
|
||||
let epsilon = (1097.0 * pow(n, 4.0) / 512.0)
|
||||
|
||||
/* Now calculate the sum of the series (Eq. 10.21) */
|
||||
let footprintLatitudeInRadians = y + (beta * sin(2.0 * y)) + (gamma * sin(4.0 * y)) + (delta * sin(6.0 * y)) + (epsilon * sin(8.0 * y))
|
||||
|
||||
return footprintLatitudeInRadians
|
||||
}
|
||||
|
||||
//
|
||||
// Computes the ellipsoidal distance from the equator to a point at a given latitude in meters
|
||||
private func arcLengthOfMeridian(latitudeInRadians: Double, datum: UTMDatum) -> Double {
|
||||
let equitorialRadus = datum.equitorialRadius
|
||||
let polarRadius = datum.polarRadius
|
||||
|
||||
/* Precalculate n */
|
||||
let n = (equitorialRadus - polarRadius) / (equitorialRadus + polarRadius)
|
||||
|
||||
/* Precalculate alpha */
|
||||
let alpha = ((equitorialRadus + polarRadius) / 2.0) * (1.0 + (pow(n, 2.0) / 4.0) + (pow(n, 4.0) / 64.0))
|
||||
|
||||
/* Precalculate beta */
|
||||
let beta = (-3.0 * n / 2.0) + (9.0 * pow(n, 3.0) / 16.0) + (-3.0 * pow(n, 5.0) / 32.0)
|
||||
|
||||
/* Precalculate gamma */
|
||||
let gamma = (15.0 * pow(n, 2.0) / 16.0) + (-15.0 * pow(n, 4.0) / 32.0)
|
||||
|
||||
/* Precalculate delta */
|
||||
let delta = (-35.0 * pow(n, 3.0) / 48.0) + (105.0 * pow(n, 5.0) / 256.0)
|
||||
|
||||
/* Precalculate epsilon */
|
||||
let epsilon = (315.0 * pow(n, 4.0) / 512.0)
|
||||
|
||||
/* Now calculate the sum of the series and return */
|
||||
let result = alpha * (latitudeInRadians + (beta * sin(2.0 * latitudeInRadians)) + (gamma * sin(4.0 * latitudeInRadians)) + (delta * sin(6.0 * latitudeInRadians)) + (epsilon * sin(8.0 * latitudeInRadians)))
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// UTMConversion.swift
|
||||
// UTMConversion
|
||||
//
|
||||
// Created by Peter Ringset on 16/03/2017.
|
||||
// Copyright © 2017 WTW. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreLocation
|
||||
|
||||
public typealias UTMGridZone = UInt
|
||||
|
||||
extension UTMGridZone {
|
||||
var centralMeridian: Double {
|
||||
return toRadians(degrees: -183.0 + (Double(self) * 6.0));
|
||||
}
|
||||
}
|
||||
|
||||
public enum UTMHemisphere {
|
||||
case northern
|
||||
case southern
|
||||
}
|
||||
|
||||
public struct UTMDatum {
|
||||
public let equitorialRadius: Double
|
||||
public let polarRadius: Double
|
||||
|
||||
public static let wgs84 = UTMDatum(equitorialRadius: 6378137, polarRadius: 6356752.3142) // WGS84
|
||||
}
|
||||
|
||||
public struct UTMCoordinate {
|
||||
|
||||
public let northing: Double
|
||||
public let easting: Double
|
||||
public let zone: UTMGridZone
|
||||
public let hemisphere: UTMHemisphere
|
||||
|
||||
public init(northing: Double, easting: Double, zone: UTMGridZone, hemisphere: UTMHemisphere) {
|
||||
self.northing = northing
|
||||
self.easting = easting
|
||||
self.zone = zone
|
||||
self.hemisphere = hemisphere
|
||||
}
|
||||
|
||||
public func coordinate(datum: UTMDatum = UTMDatum.wgs84) -> CLLocationCoordinate2D {
|
||||
return TMCoordinate(utmCoordinate: self).coordinate(centralMeridian: zone.centralMeridian, datum: datum)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public extension CLLocationCoordinate2D {
|
||||
|
||||
public func utmCoordinate(datum: UTMDatum = UTMDatum.wgs84) -> UTMCoordinate {
|
||||
let zone = self.zone
|
||||
return TMCoordinate(coordinate: self, centralMeridian: zone.centralMeridian, datum: datum).utmCoordinate(zone: zone, hemisphere: hemisphere)
|
||||
}
|
||||
|
||||
var zone: UTMGridZone {
|
||||
return UTMGridZone(floor((longitude + 180.0) / 6)) + 1;
|
||||
}
|
||||
|
||||
var hemisphere: UTMHemisphere {
|
||||
return latitude < 0 ? .southern : .northern
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
//
|
||||
// UTMConversionTests.swift
|
||||
// UTMConversionTests
|
||||
//
|
||||
// Created by Peter Ringset on 17/03/2017.
|
||||
// Copyright © 2017 Peter Ringset. All rights reserved.
|
||||
//
|
||||
|
||||
import CoreLocation
|
||||
import UTMConversion
|
||||
import XCTest
|
||||
|
||||
class UTMConversionTests: XCTestCase {
|
||||
|
||||
func testCLLocationCoordinate2DConvertToUTMCoordinate() {
|
||||
let oslo = CLLocationCoordinate2D(latitude: 59.912814611065265, longitude: 10.760192985178369)
|
||||
let utmOslo = oslo.utmCoordinate()
|
||||
XCTAssertEqualWithAccuracy(utmOslo.northing, 6643010.0, accuracy: 0.00001);
|
||||
XCTAssertEqualWithAccuracy(utmOslo.easting, 598430.0, accuracy: 0.00001);
|
||||
XCTAssertEqual(utmOslo.zone, 32)
|
||||
XCTAssertEqual(utmOslo.hemisphere, .northern)
|
||||
|
||||
let trondheim = CLLocationCoordinate2D(latitude: 63.430493678423012, longitude: 10.394966844991798)
|
||||
let utmTrondheim = trondheim.utmCoordinate()
|
||||
XCTAssertEqualWithAccuracy(utmTrondheim.northing, 7034313, accuracy: 0.00001)
|
||||
XCTAssertEqualWithAccuracy(utmTrondheim.easting, 569612, accuracy: 0.00001)
|
||||
XCTAssertEqual(utmTrondheim.zone, 32)
|
||||
XCTAssertEqual(utmTrondheim.hemisphere, .northern)
|
||||
|
||||
let johannesburg = CLLocationCoordinate2D(latitude: -26.214767103043133, longitude: 28.040197220939884)
|
||||
let utmJohannesburg = johannesburg.utmCoordinate()
|
||||
XCTAssertEqualWithAccuracy(utmJohannesburg.northing, 7100115, accuracy: 0.00001)
|
||||
XCTAssertEqualWithAccuracy(utmJohannesburg.easting, 603914, accuracy: 0.00001)
|
||||
XCTAssertEqual(utmJohannesburg.zone, 35)
|
||||
XCTAssertEqual(utmJohannesburg.hemisphere, .southern)
|
||||
}
|
||||
|
||||
func testUTMCoordinateConvertToCLLocationCoordinate2D() {
|
||||
let utmOslo = UTMCoordinate(northing: 6643010, easting: 598430, zone: 32, hemisphere: .northern)
|
||||
let oslo = utmOslo.coordinate()
|
||||
XCTAssertEqual(oslo.latitude, 59.912814611065265)
|
||||
XCTAssertEqual(oslo.longitude, 10.760192985178369)
|
||||
|
||||
let utmTrondheim = UTMCoordinate(northing: 7034313, easting: 569612, zone: 32, hemisphere: .northern)
|
||||
let trondheim = utmTrondheim.coordinate()
|
||||
XCTAssertEqual(trondheim.latitude, 63.430493678423012)
|
||||
XCTAssertEqual(trondheim.longitude, 10.394966844991798)
|
||||
|
||||
let utmJohannesburg = UTMCoordinate(northing: 7100115, easting: 603914, zone: 35, hemisphere: .southern)
|
||||
let johannesburg = utmJohannesburg.coordinate()
|
||||
XCTAssertEqual(johannesburg.latitude, -26.214767103043133)
|
||||
XCTAssertEqual(johannesburg.longitude, 28.040197220939884)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue