elevation

package
v0.22.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package elevation looks up altitude (meters above sea level) for arbitrary lat/lon coordinates against the Mapzen Terrarium DEM (https://github.com/tilezen/joerd/blob/master/docs/formats.md#terrarium).

Terrarium tiles are 256x256 PNGs hosted on AWS Open Data:

https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png

Each pixel encodes elevation in meters with the formula:

height = (R * 256 + G + B / 256) - 32768

We use zoom 12 (~9.5 m/pixel at the equator), which is well over the resolution we need for cabin-altitude charts and keeps tile counts small enough to LRU-cache in process memory.

Hot-path semantics: Lookup is wired into the per-frame recorder path. Cache hits are O(microseconds). Cache misses kick off an asynchronous fetch and return ok=false; the next sample on the same tile (~9 km later, typically the very next frame) hits the warm cache. We never block the recorder on a network round trip.

Index

Constants

View Source
const (
	// DefaultZoom strikes the right balance between resolution
	// (~9.5 m/pixel at equator, sub-meter altitude error after
	// bilinear interp) and tile size (a single tile covers a 9-10 km
	// box, so a typical commute fits in 2-4 tiles).
	DefaultZoom = 12

	// DefaultTileURL is Mapzen's public Terrarium endpoint hosted on
	// AWS Open Data. Free, no key, no rate-limit (within reason).
	// NOTE: this leaks per-tile coordinates off-LAN; the recorder is
	// opt-in (ELEVATION_ENABLED=1) and operators are expected to
	// either point ELEVATION_TILES_URL at an in-cluster mirror or
	// run with a pre-warmed disk cache so tiles only fetch once.
	DefaultTileURL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png"

	// DefaultCacheSize bounds in-memory tile retention. Each tile is
	// 256*256*2 = 128 KB of decoded int16 elevation grid, so 256
	// tiles ~= 32 MB heap. 256 tiles at z=12 covers ~2,400 km of
	// route history -- a personal-scale recorder rarely evicts.
	DefaultCacheSize = 256
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// TileURL is the Terrarium tile template. Empty -> DefaultTileURL
	// (Mapzen on AWS Open Data, off-LAN).
	TileURL string
	// CacheDir, if non-empty, persists fetched PNGs to disk under
	// {dir}/{z}/{x}/{y}.png. Used both as a read-through cache (avoids
	// re-fetching after a pod restart) and as a self-hosted offline
	// store: an operator can rsync a pre-built Terrarium tile dump
	// here and leave TileURL empty/blackholed for fully-offline runs.
	CacheDir string
	// Zoom: 0 -> DefaultZoom (12).
	Zoom int
	// MaxTiles bounds the in-memory LRU. 0 -> DefaultCacheSize.
	MaxTiles int
	// HTTPClient: nil -> http.Client with 10s timeout.
	HTTPClient *http.Client
	// Logger: nil -> slog.Default().
	Logger *slog.Logger
}

Config bundles all Resolver knobs. Zero values fall back to package defaults; the empty CacheDir disables disk persistence.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver answers (lat, lon) -> altitude lookups against a tile server, with a bounded LRU of decoded tile grids in front to keep the hot path lock-free on warm tiles. An optional disk cache (cacheDir) survives pod restarts and can be pre-warmed by the operator (rsync from a Terrarium dump) for fully-offline operation.

func New

func New(cfg Config) *Resolver

New constructs a Resolver from a Config. See Config field docs for per-field defaults.

func (*Resolver) Lookup

func (r *Resolver) Lookup(lat, lon float64) (float64, bool)

Lookup returns the bilinearly-interpolated elevation at (lat, lon) in meters, or ok=false when the tile is not yet cached. On miss we asynchronously fetch the tile so subsequent lookups warm up; the caller (the recorder) must NOT block waiting -- elevation is best-effort and the column is nullable.

Returns ok=false (without scheduling a fetch) for invalid lat/lon (NaN, out-of-range) or for the (0, 0) "no fix" sentinel the recorder uses when GPS is unavailable.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL