Geodetic::Coordinate::GH36¶
Geohash-36¶
Geohash-36 is a hierarchical spatial hashing algorithm that encodes latitude/longitude into a compact, URL-friendly string using a case-sensitive 36-character alphabet. It uses a 6x6 grid subdivision (radix-36) providing higher precision per character than standard Geohash (radix-32).
Character set: 23456789bBCdDFgGhHjJKlLMnNPqQrRtTVWX
(avoids vowels, vowel-like numbers, and ambiguous characters like 0/O, 1/I/l)
GH36 is a 2D coordinate system (no altitude). Conversions to/from other systems go through LLA as the intermediary. Each geohash string represents a rectangular cell; the coordinate's point value is the cell's midpoint.
Constructor¶
# From a geohash string
coord = Geodetic::Coordinate::GH36.new("bdrdC26BqH")
# From any coordinate (converts via LLA)
coord = Geodetic::Coordinate::GH36.new(lla_coord)
coord = Geodetic::Coordinate::GH36.new(utm_coord, precision: 8)
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
String or Coord | — | A geohash string or any coordinate object |
precision |
Integer | 10 | Hash length (ignored when source is a String) |
Raises ArgumentError if the source is an empty string, contains invalid characters, or is not a recognized coordinate type.
Attributes¶
| Attribute | Type | Access | Description |
|---|---|---|---|
geohash |
String | read-only | The geohash-36 encoded string |
GH36 is immutable — there are no setter methods.
Precision¶
The precision (hash length) determines the size of the cell:
| Length | Approximate Resolution |
|---|---|
| 5 | ~1.4 km |
| 8 | ~6.5 m |
| 10 | ~0.3 m (default) |
Longer hashes yield finer precision. Longitude precision is always coarser than latitude (cells are wider than tall).
Conversions¶
All conversions chain through LLA. The datum parameter defaults to Geodetic::WGS84.
Instance Methods¶
coord.to_lla # => LLA (midpoint of the cell)
coord.to_ecef
coord.to_utm
coord.to_enu(reference_lla)
coord.to_ned(reference_lla)
coord.to_mgrs
coord.to_usng
coord.to_web_mercator
coord.to_ups
coord.to_state_plane(zone_code)
coord.to_bng
coord.to_gh36 # identity (via mixin)
Class Methods¶
GH36.from_lla(lla_coord)
GH36.from_ecef(ecef_coord)
GH36.from_utm(utm_coord)
GH36.from_web_mercator(wm_coord)
# ... and all other coordinate systems
LLA Convenience Methods¶
lla = Geodetic::Coordinate::LLA.new(lat: 40.689167, lng: -74.044444)
gh36 = lla.to_gh36 # default precision 10
gh36 = lla.to_gh36(precision: 5) # custom precision
lla = Geodetic::Coordinate::LLA.from_gh36(gh36)
Serialization¶
to_s(truncate_to = nil)¶
Returns the geohash string. An optional integer truncates to that length.
to_a¶
Returns [lat, lng] of the cell midpoint.
from_string / from_array¶
GH36.from_string("bdrdC26BqH") # from geohash string
GH36.from_array([40.689, -74.044]) # from [lat, lng]
Neighbors¶
Returns all 8 adjacent geohash cells as GH36 instances.
coord = GH36.new(LLA.new(lat: 40.0, lng: -74.0))
neighbors = coord.neighbors
# => { N: GH36, S: GH36, E: GH36, W: GH36, NE: GH36, NW: GH36, SE: GH36, SW: GH36 }
neighbors[:N].to_lla.lat > coord.to_lla.lat # => true
neighbors[:E].to_lla.lng > coord.to_lla.lng # => true
Neighbor computation propagates carries when the adjustment wraps beyond the matrix edge, recursing on the parent prefix.
Area¶
The to_area method returns the geohash cell as a Geodetic::Areas::BoundingBox.
area = coord.to_area
# => Geodetic::Areas::BoundingBox
area.includes?(coord.to_lla) # => true (midpoint is inside the cell)
area.nw # => LLA (northwest corner)
area.se # => LLA (southeast corner)
Equality¶
Two GH36 instances are equal if their geohash strings match exactly.
GH36.new("bdrdC26BqH") == GH36.new("bdrdC26BqH") # => true
GH36.new("bdrdC26BqH") == GH36.new("bdrdC26Bq2") # => false
valid?¶
Returns true if all characters are in the valid Geohash-36 alphabet.
Universal Distance and Bearing Methods¶
GH36 supports all universal distance and bearing methods via the DistanceMethods and BearingMethods mixins:
a = GH36.new(LLA.new(lat: 40.689167, lng: -74.044444))
b = GH36.new(LLA.new(lat: 51.504444, lng: -0.086666))
a.distance_to(b) # => Distance (~5,570 km)
a.straight_line_distance_to(b) # => Distance
a.bearing_to(b) # => Bearing (~51°)
a.elevation_to(b) # => Float (degrees)
Cross-system distances work too: