Skip to content

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)
coord.precision              # => 10 (hash length)
coord.precision_in_meters    # => { lat: 0.31, lng: 0.62 }

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.

coord = GH36.new("bdrdC26BqH")
coord.to_s       # => "bdrdC26BqH"
coord.to_s(5)    # => "bdrdC"

to_a

Returns [lat, lng] of the cell midpoint.

coord.to_a    # => [40.689, -74.044]

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.

coord.valid?    # => true

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:

utm = seattle_lla.to_utm
gh36 = GH36.new(portland_lla)
utm.distance_to(gh36)    # => Distance