diff --git a/Sources/GeoHashFramework/GeoHash.swift b/Sources/GeoHashFramework/GeoHash.swift index 447e4fd..c31140a 100644 --- a/Sources/GeoHashFramework/GeoHash.swift +++ b/Sources/GeoHashFramework/GeoHash.swift @@ -4,7 +4,7 @@ import Foundation public struct GeoHash: Sendable, Hashable { - public private(set) var precision: GeoHashPrecision + public private(set) var precision: GeoHashBitsPrecision public private(set) var binary: String /// Base32 characters used to hash @@ -19,7 +19,7 @@ public struct GeoHash: Sendable, Hashable { /// - Parameter value: A string that contains only "0" or "1". public init( binary: String, - precision: GeoHashPrecision = .mid + precision: GeoHashBitsPrecision = .mid ) { precondition( binary.allSatisfy({ @@ -39,7 +39,7 @@ public struct GeoHash: Sendable, Hashable { public init( latitude: Double, longitude: Double, - precision: GeoHashPrecision = .mid + precision: GeoHashBitsPrecision = .mid ) { precondition( latitude >= -90 && latitude <= 90, @@ -62,7 +62,7 @@ public struct GeoHash: Sendable, Hashable { ) } - public init(geoHash: String, precision: GeoHashPrecision = .mid) { + public init(geoHash: String, precision: GeoHashBitsPrecision = .mid) { self.init( binary: Self.makeBinary( from: geoHash, @@ -77,7 +77,7 @@ public struct GeoHash: Sendable, Hashable { extension GeoHash { static func makeBinary( from geoHash: String, - precision: GeoHashPrecision + precision: GeoHashBitsPrecision ) -> String { var binary = "" @@ -98,7 +98,7 @@ extension GeoHash { return binary } - static func makeBinary(from coordinate: GeoHashCoordinate2D, precision: GeoHashPrecision) + static func makeBinary(from coordinate: GeoHashCoordinate2D, precision: GeoHashBitsPrecision) -> String { let latitude = coordinate.latitude diff --git a/Sources/GeoHashFramework/GeoHashBitsPrecision.swift b/Sources/GeoHashFramework/GeoHashBitsPrecision.swift new file mode 100644 index 0000000..651e871 --- /dev/null +++ b/Sources/GeoHashFramework/GeoHashBitsPrecision.swift @@ -0,0 +1,33 @@ +/// A GeoHashPrecision enum represents the bits precision of the GeoHash in binary unit. +/// +/// - low: 30 bits precision. This corresponds to 6 characters of GeoHash. +/// - mid: 40 bits precision. This corresponds to 8 characters of GeoHash. +/// - high: 50 bits precision. This corresponds to 10 characters of GeoHash. +public enum GeoHashBitsPrecision: Sendable, Hashable { + /// 6 digits GeoHash + case low + /// 8 digits GeoHash + case mid + /// 10 digits GeoHash + case high + + /// `digits` **bits** precision. + /// - Note: `digits` must be a multiple of 4 because each GeoHash character is 5 bits. + case exact(digits: Int) + + public var rawValue: Int { + switch self { + case .low: return 6 * 5 + case .mid: return 8 * 5 + case .high: return 10 * 5 + case .exact(let digits): + precondition(digits % 5 == 0) + return digits + } + } + + var format: String { + let rawValue = self.rawValue + return "%0\(rawValue / 5)d" + } +} diff --git a/Sources/GeoHashFramework/GeoHashCluster.swift b/Sources/GeoHashFramework/GeoHashCluster.swift index 7ba2425..ed5fe2f 100644 --- a/Sources/GeoHashFramework/GeoHashCluster.swift +++ b/Sources/GeoHashFramework/GeoHashCluster.swift @@ -9,17 +9,17 @@ /// /// This data structure is used to store GeoHashes and their relations. public struct GeoHashCluster: Sendable, Hashable { - private var clusters: [GeoHashPrecision: [GeoHash]] = [:] + private var clusters: [GeoHashBitsPrecision: [GeoHash]] = [:] public init() { clusters = [:] } - public func isSame(geoHash1: GeoHash, geoHash2: GeoHash, precision: GeoHashPrecision) -> Bool { + public func isSame(geoHash1: GeoHash, geoHash2: GeoHash, precision: GeoHashBitsPrecision) -> Bool { fatalError("Not implemented") } - public func mergeIfPossible(geoHash1: GeoHash, geoHash2: GeoHash, precision: GeoHashPrecision) { + public func mergeIfPossible(geoHash1: GeoHash, geoHash2: GeoHash, precision: GeoHashBitsPrecision) { fatalError("Not implemented") } } diff --git a/Sources/GeoHashFramework/GeoHashPrecision.swift b/Sources/GeoHashFramework/GeoHashPrecision.swift deleted file mode 100644 index 24c3760..0000000 --- a/Sources/GeoHashFramework/GeoHashPrecision.swift +++ /dev/null @@ -1,33 +0,0 @@ -/// A GeoHashPrecision enum represents the precision of the GeoHash in binary unit. -/// -/// - low: 24 digits precision. This corresponds to 6 characters of GeoHash. -/// - mid: 32 digits precision. This corresponds to 8 characters of GeoHash. -/// - high: 40 digits precision. This corresponds to 10 characters of GeoHash. -public enum GeoHashPrecision: Sendable, Hashable { - /// 6 digits GeoHash - case low - /// 8 digits GeoHash - case mid - /// 10 digits GeoHash - case high - - /// `digits` **bits** precision. - /// - Note: `digits` must be a multiple of 4 because each GeoHash character is 4 bits. - case exact(digits: Int) - - public var rawValue: Int { - switch self { - case .low: return 6 * 4 - case .mid: return 8 * 4 - case .high: return 10 * 4 - case .exact(let digits): - precondition(digits % 4 == 0) - return digits - } - } - - var format: String { - let rawValue = self.rawValue - return "%0\(rawValue / 4)d" - } -} diff --git a/Tests/GeoHashFrameworkTests/GeoHashTests.swift b/Tests/GeoHashFrameworkTests/GeoHashTests.swift index 29f350a..84f7366 100644 --- a/Tests/GeoHashFrameworkTests/GeoHashTests.swift +++ b/Tests/GeoHashFrameworkTests/GeoHashTests.swift @@ -12,26 +12,26 @@ import Testing struct GeoHashTests { @Test func makeGeoHashFromBinary() async throws { - let input = "0110101001101010" + let input = "01101010011010100110" let geoHash = GeoHash( binary: input, - precision: .exact(digits: 16) + precision: .exact(digits: 20) ) - #expect(geoHash.geoHash == "e9p0") - #expect(geoHash.geoHash.count == input.count / 4) + #expect(geoHash.geoHash == "e9p6") + #expect(geoHash.geoHash.count == input.count / 5) } @Test func makeFromBinary() async throws { - let input = "0110101001101010" + let input = "01101010011010100110" - let expectedLat = "10001000" - let expectedLng = "01110111" + let expectedLat = "1000100010" + let expectedLng = "0111011101" let geoHash = GeoHash( binary: input, precision: .exact( - digits: 16 + digits: 20 ) ) #expect(geoHash.latitudeBits == expectedLat) @@ -45,10 +45,10 @@ struct GeoHashTests { let geoHash = GeoHash(latitude: lat, longitude: lng) #expect( - geoHash.binary == "11101101000011100110110101011111" + geoHash.binary == "1110110100001110011011010101111110001101" ) #expect( - geoHash.geoHash == "xn76urs" + geoHash.geoHash == "xn76urwe" ) } }