Skip to content

Commit

Permalink
Add getNeighbors method (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
fummicc1 authored Nov 24, 2024
1 parent 8a3841f commit 56d8635
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
22 changes: 22 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"configurations": [
{
"type": "lldb",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:GeoHashSwift}",
"name": "Debug geohash",
"program": "${workspaceFolder:GeoHashSwift}/.build/debug/geohash",
"preLaunchTask": "swift: Build Debug geohash"
},
{
"type": "lldb",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:GeoHashSwift}",
"name": "Release geohash",
"program": "${workspaceFolder:GeoHashSwift}/.build/release/geohash",
"preLaunchTask": "swift: Build Release geohash"
}
]
}
10 changes: 10 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,14 @@
"editor.defaultFormatter": "vknabel.vscode-apple-swift-format",
"cSpell.words": [],
"makefile.configureOnOpen": false,
"swift.sourcekit-lsp.serverArguments": [
"-Xswiftc",
"-sdk",
"-Xswiftc",
"/Applications/Xcode-16.1.0.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneOS.sdk",
"-Xswiftc",
"-target",
"-Xswiftc",
"arm64-apple-ios18.1-simulator",
]
}
56 changes: 55 additions & 1 deletion Sources/GeoHashFramework/GeoHash.swift
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ extension GeoHash {
}
}

// MARK: Public getter
// MARK: Public properties and methods
extension GeoHash {
public var latitudeBits: String {
var lat: String = ""
Expand Down Expand Up @@ -209,6 +209,60 @@ extension GeoHash {
return hash
}

public func getNeighbors() -> [GeoHash] {
let latitudeBits = self.latitudeBits
let longitudeBits = self.longitudeBits

let north = add(bits: latitudeBits, by: 1)
let south = add(bits: latitudeBits, by: -1)
let east = add(bits: longitudeBits, by: 1)
let west = add(bits: longitudeBits, by: -1)

let northEast = combineBits(latitude: north, longitude: east)
let northWest = combineBits(latitude: north, longitude: west)
let southEast = combineBits(latitude: south, longitude: east)
let southWest = combineBits(latitude: south, longitude: west)

return [
GeoHash(binary: combineBits(latitude: north, longitude: longitudeBits), precision: precision),
GeoHash(binary: northEast, precision: precision),
GeoHash(binary: combineBits(latitude: latitudeBits, longitude: east), precision: precision),
GeoHash(binary: southEast, precision: precision),
GeoHash(binary: combineBits(latitude: south, longitude: longitudeBits), precision: precision),
GeoHash(binary: southWest, precision: precision),
GeoHash(binary: combineBits(latitude: latitudeBits, longitude: west), precision: precision),
GeoHash(binary: northWest, precision: precision)
]
}

/// Add `delta` to `bits`
private func add(bits: String, by delta: Int) -> String {
if let decimal = Int(bits, radix: 2) {
let moved = decimal + delta
// 11 -> 1110
return String(moved, radix: 2)
}
return bits
}

/// Combine `latitude` and `longitude` in bits.
private func combineBits(latitude: String, longitude: String) -> String {
var result = ""
let latArray = Array(latitude)
let lngArray = Array(longitude)
let maxLength = max(latArray.count, lngArray.count)

for i in 0..<maxLength {
if i < lngArray.count {
result.append(lngArray[i])
}
if i < latArray.count {
result.append(latArray[i])
}
}
return result
}

public static func getBound(with precision: GeoHashBitsPrecision) -> [GeoHashCoordinate2D] {
// Initial: BottomLeft in zoom-level 0
let baseGeoCoordinate = GeoHash(
Expand Down
22 changes: 22 additions & 0 deletions Tests/GeoHashFrameworkTests/GeoHashTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,26 @@ struct GeoHashTests {
}
print(count == 131072) // 2^15 * 4
}

@Test
func getNeighbors() async throws {
// Tokyo Station
let lat = 35.681382
let lng = 139.766084

let expected = [
"xn76urws",
"xn76urwu",
"xn76urwg",
"xn76urwf",
"xn76urwd",
"xn76urw6",
"xn76urw7",
"xn76urwk"
]

let geoHash = GeoHash(latitude: lat, longitude: lng)
let neighbors = geoHash.getNeighbors()
#expect(neighbors.map(\.geoHash) == expected)
}
}

0 comments on commit 56d8635

Please sign in to comment.