From 8693ab8098ab68cd1be3a64fb9e9b4717aff0902 Mon Sep 17 00:00:00 2001 From: ferdiflash Date: Thu, 30 Apr 2026 12:46:28 +0200 Subject: [PATCH] Add functions that specify UTM zone for conversion --- README.md | 13 ++++++++++ .../CLLocation+UTMCoordinate.swift | 14 ++++++++++- ...CLLocationCoordinate2D+UTMCoordinate.swift | 14 +++++++++-- .../UTMConversionTests.swift | 24 +++++++++++++++++++ 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e90c082..55fe8c4 100644 --- a/README.md +++ b/README.md @@ -66,3 +66,16 @@ let utmCoordinate = UTMCoordinate(northing: 7034313, easting: 569612, zone: 32, let datum = UTMDatum(equitorialRadius: 6378137, polarRadius: 6356752.3142) let coordinate = utmCoordinate.coordinate(datum: datum) ``` + +### UTM Zone + +It is possible to specify the UTM zone for conversion, e.g. if you want consistent UTM coordinates at a border of two zones. + +```swift +import CoreLocation +import UTMConversion + +let location = CLLocation(latitude: 51.357402, longitude: 12.002263) +let utmCoordinateInZone33 = utmCoordinate.coordinate() // Coordinate is in 33, but at the border to 32. +let utmCoordinateInZone32 = utmCoordinate.coordinate(zone: 32) +``` diff --git a/Sources/UTMConversion/CLLocation+UTMCoordinate.swift b/Sources/UTMConversion/CLLocation+UTMCoordinate.swift index d0862b5..0220d86 100644 --- a/Sources/UTMConversion/CLLocation+UTMCoordinate.swift +++ b/Sources/UTMConversion/CLLocation+UTMCoordinate.swift @@ -14,5 +14,17 @@ public extension CLLocation { let zone = coordinate.zone return TMCoordinate(coordinate: coordinate, centralMeridian: zone.centralMeridian, datum: datum).utmCoordinate(zone: zone, hemisphere: coordinate.hemisphere) } - + + /** + Calculates the UTM coordinate of the receiver + + - Parameter zone: The UTM zone to use + - Parameter datum: The datum to use, defaults to WGS84 which should be fine for most applications + + */ + func utmCoordinate(zone: UTMGridZone, datum: UTMDatum = UTMDatum.wgs84) -> UTMCoordinate { + let coordinate = self.coordinate + return TMCoordinate(coordinate: coordinate, centralMeridian: zone.centralMeridian, datum: datum).utmCoordinate(zone: zone, hemisphere: coordinate.hemisphere) + } + } diff --git a/Sources/UTMConversion/CLLocationCoordinate2D+UTMCoordinate.swift b/Sources/UTMConversion/CLLocationCoordinate2D+UTMCoordinate.swift index d79dffd..fdc3458 100644 --- a/Sources/UTMConversion/CLLocationCoordinate2D+UTMCoordinate.swift +++ b/Sources/UTMConversion/CLLocationCoordinate2D+UTMCoordinate.swift @@ -14,8 +14,18 @@ public extension CLLocationCoordinate2D { let zone = self.zone return TMCoordinate(coordinate: self, centralMeridian: zone.centralMeridian, datum: datum).utmCoordinate(zone: zone, hemisphere: hemisphere) } - - + + /** + Calculates the UTM coordinate of the receiver + + - Parameter zone: The UTM zone to use + - Parameter datum: The datum to use, defaults to WGS84 which should be fine for most applications + + */ + func utmCoordinate(zone: UTMGridZone, datum: UTMDatum = UTMDatum.wgs84) -> UTMCoordinate { + TMCoordinate(coordinate: self, centralMeridian: zone.centralMeridian, datum: datum).utmCoordinate(zone: zone, hemisphere: hemisphere) + } + /** The UTM grid zone */ diff --git a/Tests/UTMConversionTests/UTMConversionTests.swift b/Tests/UTMConversionTests/UTMConversionTests.swift index dc18846..6a7e412 100644 --- a/Tests/UTMConversionTests/UTMConversionTests.swift +++ b/Tests/UTMConversionTests/UTMConversionTests.swift @@ -97,6 +97,30 @@ class UTMConversionTests: XCTestCase { let oslo = osloUTM.location(datum: UTMDatum(equitorialRadius: 6378137, polarRadius: 6356752.3142)) XCTAssertEqual(oslo.coordinate.latitude, 59.912814611065265) XCTAssertEqual(oslo.coordinate.longitude, 10.760192985178369) + + } + + func testCustomZone() { + // Coordinate located in UTM zone 33 + let lat = 51.357402 + let lon = 12.002263 + + // echo "12.002263 51.357402" | proj -f "%.5f" +proj=utm +zone=32 +datum=WGS84 +units=m +no_defs + let northing32 = 5693849.66049 + let easting32 = 709023.99157 + let zone: UTMGridZone = 32 + + let neumarkt2D = CLLocationCoordinate2D(latitude: lat, longitude: lon).utmCoordinate(zone: zone) + XCTAssertEqual(neumarkt2D.northing, northing32, accuracy: 0.0001) + XCTAssertEqual(neumarkt2D.easting, easting32, accuracy: 0.0001) + XCTAssertEqual(neumarkt2D.zone, zone) + XCTAssertEqual(neumarkt2D.hemisphere, .northern) + + let neumarkt = CLLocation(latitude: lat, longitude: lon).utmCoordinate(zone: zone) + XCTAssertEqual(neumarkt.northing, northing32, accuracy: 0.0001) + XCTAssertEqual(neumarkt.easting, easting32, accuracy: 0.0001) + XCTAssertEqual(neumarkt.zone, zone) + XCTAssertEqual(neumarkt.hemisphere, .northern) } }