Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add getNeighbors method #4

Merged
merged 1 commit into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
}
}