tile57

package module
v0.0.0-...-0bf4530 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 8 Imported by: 0

README

tile57 — Go binding

The canonical Go (cgo) binding to libtile57, the native Zig chart engine in this repo. It lives next to the engine (bindings/go, alongside bindings/wasm) so it tracks the C ABI in include/tile57.h as that ABI evolves — a host imports it and works in Go only, never touching cgo, the header, or the Zig build.

Requirements

  • CGO_ENABLED=1 and a C toolchain.

  • The static library built once from the repo root:

    zig build            # produces zig-out/lib/libtile57.a
    

    The cgo directives in tile57.go link ../../zig-out/lib/libtile57.a and include ../../include relative to this package, so the library must exist before you go build/go test here.

Use it from another module

Because the cgo paths are relative to this package's source, an importing module points at a local checkout with a replace directive (cgo can't link a path inside the module cache):

// go.mod
require github.com/beetlebugorg/tile57/bindings/go v0.0.0
replace github.com/beetlebugorg/tile57/bindings/go => /path/to/chartplotter-native/bindings/go
import tile57 "github.com/beetlebugorg/tile57/bindings/go"

// Bake an ENC_ROOT: each cell becomes its own PMTiles under <out>/tiles/, plus
// an ownership partition at <out>/partition.tpart.
n, err := tile57.BakeTree("/enc/ENC_ROOT", "/out", 4, nil)

// Open the compositor over the baked archives + partition, and serve tiles.
src, _ := tile57.OpenCompose([]string{"/out/tiles/US5MD1MC.pmtiles"}, "/out/partition.tpart")
defer src.Close()
body, owned, _ := src.Tile(13, 2359, 3139) // owned=false, body=nil => open ocean

// Or open one baked archive as a chart (bounds, scale, coverage, SCAMIN).
chart, _ := tile57.Open("/out/tiles/US5MD1MC.pmtiles")
defer chart.Close()
info := chart.Info()     // zoom range, bounds, embedded 1:N scale
scamin := chart.Scamin() // []uint32, ascending

// Raw S-57 reading is handle-free (cell inventory, feature extraction).
charts, _ := tile57.Charts("/enc/ENC_ROOT")
water, _ := tile57.Features("/enc/ENC_ROOT/US5MD1MC/US5MD1MC.000", "DEPARE", "DRGARE")

Surface

  • Charts (a baked archive: metadata + query)Open (path, mmap'd), OpenBytes; Source.Info, Meta, Scamin, Coverage, Close.
  • S-57 source readers (handle-free)Charts (per-chart metadata of a .000 or ENC_ROOT), Features / FeaturesBytes (GeoJSON extraction), CatalogEntries (CATALOG.031 decode).
  • BakeBakeChart (one chart → PMTiles bytes), BakeTree (an ENC_ROOT → per-chart archives), BakeAssets (portrayal assets in memory).
  • ComposeOpenCompose (paths; owns its charts) / OpenComposeCharts (borrows yours); ComposeSource.Serve (a tile, with an ownership flag), Meta, SavePartition, Close.
  • StyleColortablesDefault, Style, BuildStyle, StyleDiff, MarinerDefaults.

libtile57 is not internally synchronized; every Source method is mutex-guarded, so a Source is safe for concurrent use.

Tests

zig build && go test ./...

The tests are self-contained: they use the S-101 PortrayalCatalogue vendored at ../../vendor/ and a small ENC cell in testdata/.

Documentation

Overview

Package tile57 is the canonical Go binding to libtile57 — the native Zig "tile57" chart engine (this repo, chartplotter-native). It ships WITH the engine (bindings/go) so it tracks the C ABI in <tile57.h> as the ABI evolves; a host imports it and works in Go only, never touching cgo, the header, or the Zig build.

Requirements: CGO (CGO_ENABLED=1) and the static library. Build it once from the repo root with `zig build`, producing zig-out/lib/libtile57.a — the cgo directives below link it by a path relative to this package, so an importing module needs a `replace` pointing at a local checkout (see this package's README).

The pipeline mirrors the C header: bake ENC charts to per-chart PMTiles (BakeChart / BakeTree), open each archive as a Source (Open / OpenBytes) for metadata, and compose the open charts into one seamless tile pyramid with OpenCompose / OpenComposeCharts for serving. Raw S-57 reading (chart inventory, feature extraction, catalogue decode) is handle-free — see Charts, Features, FeaturesBytes, CatalogEntries.

libtile57 is NOT internally synchronized, so every call into a handle is guarded by a mutex.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoCoverage is returned by BakePmtiles / BakeBundle when the bake completed
	// successfully but produced no tiles — the inputs covered nothing in range. This
	// is a routine, recoverable outcome (skip this region), NOT a failure: a host
	// should distinguish it from a hard error and continue.
	ErrNoCoverage = errors.New("tile57: bake covered nothing")

	// ErrSourceClosed is returned by Source methods invoked after Close.
	ErrSourceClosed = errors.New("tile57: source closed")

	// ErrEmptyInput is returned when a call is handed no usable input — no charts,
	// empty bytes, an empty style template, or empty asset inputs.
	ErrEmptyInput = errors.New("tile57: empty input")

	// Category sentinels matching the C tile57_status codes. A call that fails
	// wraps the matching sentinel with %w (the message stays specific — often
	// "path: reason"), so a host can branch with errors.Is(err, ErrParse) etc.
	ErrBadArg      = errors.New("tile57: invalid argument")
	ErrIO          = errors.New("tile57: I/O error")
	ErrParse       = errors.New("tile57: malformed input")
	ErrNoMem       = errors.New("tile57: out of memory")
	ErrUnsupported = errors.New("tile57: unsupported input")
	ErrRender      = errors.New("tile57: render failed")
	ErrInternal    = errors.New("tile57: internal error")
)

Sentinel errors hosts can branch on with errors.Is. The package wraps these with %w, so the human-readable message stays specific while the category is testable.

Functions

func BakeChart

func BakeChart(path string) ([]byte, error)

BakeChart bakes ONE on-disk chart (a .000 path + its .001.. updates) to a PMTiles archive over its NATIVE band zoom range and returns the bytes — the per-chart tile store the compositor consumes (it handles any cross-band zoom expansion). The archive metadata embeds that chart's own coverage (M_COVR + cscl + date/name); read it back with PMTilesMetadata, or open the archive with OpenBytes. A chart that produces no tiles returns ErrNoCoverage.

func BakePartitionDebug

func BakePartitionDebug(encRoot, outPath string, minZoom, maxZoom uint8, band PartitionBand) (chartCount int, err error)

BakePartitionDebug bakes the ownership-partition DEBUG tiles from an on-disk ENC_ROOT into a single PMTiles at outPath — the composited faces (which chart renders which ground at each band), one polygon per owning chart in a layer named "partition" with the properties cell/cscl/band/tier/oi/color, and NO portrayed chart content. It is the raw material for a partition-debug UI: point a MapLibre style (using the vector_layers metadata) at it and fill by the "color" property.

band = BandGoverning emits the band governing each zoom (the natural view); BandBerthingBandOverview emit that one band's own map at every zoom. minZoom and maxZoom bound the tiles — the coarse bands are cheap, but harbor-level detail (maxZoom >= 13) multiplies the tile count ~4× per zoom, so raise it deliberately. Returns the chart count; nothing covered returns ErrNoCoverage (no file written).

func BakeTree

func BakeTree(inDir, outDir string, workers int, onProgress func(done, total int)) (int, error)

BakeTree walks inDir for S-57 base charts (*.000) and bakes each IN PARALLEL to the SAME relative path under outDir with a .pmtiles extension (+ an <out>.sha content-hash sidecar), creating subdirs. INCREMENTAL: a chart whose archive is already up to date (newer than its .000 and its update chain) is skipped, so a re-run over an unchanged tree bakes nothing — 0 over a warm cache is success. The engine writes and frees each archive as it goes, so this never holds N archives in memory (peak ~ workers). outDir is the caller's OWN cache — it owns the location + layout, so distinct consumers don't clash. onProgress(done, total) fires per baked chart (may be called concurrently from workers, so it must be safe for concurrent use). Returns the number baked THIS run.

func BuildStyle

func BuildStyle(template []byte, m Mariner, colortables []byte, enabledBands []int32, scamin []int32, scaminLat float64) ([]byte, error)

BuildStyle patches a style template with the mariner settings + S-52 colortables into a concrete MapLibre style JSON. enabledBands (nil = show all) restricts the output to features whose band rank is listed. scamin is the SCAMIN manifest (the distinct denominators present, e.g. from Source.Scamin / the TileJSON): when non-empty the `_scamin` layers are split into per-value bucket layers with native minzoom = scaminDisplayZoom(value, scaminLat) — the same gating the offline bundle emits; nil/empty leaves them ungated. scaminLat is the source's center latitude.

func ColortablesDefault

func ColortablesDefault() ([]byte, error)

ColortablesDefault returns colortables.json (S-52 colour token -> hex per day/dusk/night) from the colour profile baked into libtile57 — no on-disk catalogue needed.

func PMTilesMetadata

func PMTilesMetadata(pmtiles []byte) ([]byte, error)

PMTilesMetadata returns a PMTiles archive's metadata JSON blob (decompressed), or nil if the archive carries none. A BakeChart archive embeds the chart's coverage under a "coverage" key. The pmtiles bytes are read but not retained.

func Style

func Style(scheme Scheme, sourceTiles, sprite, glyphs string, minZoom, maxZoom uint32, encoding TileFormat, m Mariner, enabledBands []int32, scamin []int32, scaminLat float64) ([]byte, error)

Style is a convenience that runs the whole pipeline — default colortables + template (scheme, tiles/sprite/glyph URLs) patched by mariner + band filter — to produce a complete MapLibre style JSON from libtile57's baked-in catalogue. minZoom is the chart source's tile floor, emitted verbatim (pass the archive's real minzoom; 0 = tiles from z0). maxZoom of 0 = the engine default, i.e. z16 max; a host that overzooms past z16 must pass its own maxZoom. encoding is the chart source's tile encoding (FormatMLT hints maplibre-gl's native MLT decoder; see StyleTemplate). scamin/scaminLat (typically Source.Scamin() + the source center latitude) gate the `_scamin` layers by value; pass nil/0 to leave them ungated.

func StyleDiff

func StyleDiff(template []byte, from, to Mariner, colortables []byte, enabledBands []int32, scamin []int32, scaminLat float64) ([]byte, error)

StyleDiff returns the MapLibre mutation ops (a raw JSON array) to turn the style for `from` into the style for `to`, sharing the template/colortables/bands/scamin inputs of BuildStyle so the two styles are comparable. The result is "[]" when nothing changed, one op per differing filter/paint/layout key, or [{"op":"rebuild"}] when the host should fall back to a full setStyle. The host applies each op with map.setFilter / setPaintProperty / setLayoutProperty; the raw JSON is returned so a server can forward it to the browser untouched.

func StyleTemplate

func StyleTemplate(scheme Scheme, sourceTiles, sprite, glyphs string, minZoom, maxZoom uint32, encoding TileFormat) ([]byte, error)

StyleTemplate returns the base MapLibre style template (layers + chart sources + sprite/glyph URLs) for a scheme, from the catalogue baked into libtile57. sourceTiles is the chart {z}/{x}/{y} URL; sprite/glyphs are base URLs ("" omits the symbol/text layers). minZoom is the chart source's tile floor, emitted verbatim — pass the archive's real minzoom (0 = tiles from z0; MapLibre never requests tiles below a source's minzoom). maxZoom of 0 uses the engine default. encoding is the chart source's tile encoding (FormatMLT emits "encoding":"mlt" on the source so maplibre-gl >=5.12 decodes MLT natively; FormatDefault/ FormatMVT emit nothing — the MapLibre default). Pass the set's real tile type (e.g. from Meta.TileType / the archive header); the hint survives BuildStyle and StyleDiff.

func Version

func Version() string

Version returns the libtile57 version string (e.g. "0.3.0").

Types

type Assets

type Assets struct {
	Colortables, Linestyles, SpriteJSON, SpritePNG, PatternJSON, PatternPNG []byte
}

Assets bundles the six in-memory portrayal-asset buffers BakeAssets returns — the same files BakeBundle writes under a bundle's assets/ directory.

func BakeAssets

func BakeAssets(catalogDir string) (Assets, error)

BakeAssets generates all portrayal assets in memory (colortables + linestyles + sprite/pattern atlases) from the library's embedded S-101 catalogue (catalogDir == "") or an on-disk PortrayalCatalog directory. Pairs with BakePmtiles + BuildStyle for a full in-memory bundle.

type BoundaryStyle

type BoundaryStyle int32

BoundaryStyle selects symbolized vs plain area boundaries.

const (
	BoundarySymbolized BoundaryStyle = C.TILE57_BOUNDARY_SYMBOLIZED
	BoundaryPlain      BoundaryStyle = C.TILE57_BOUNDARY_PLAIN
)

type CatalogEntry

type CatalogEntry struct {
	File     string     `json:"file"`     // recorded path, '/'-normalised
	LongName string     `json:"longName"` // LFIL — the human chart title ("" when absent)
	Impl     string     `json:"impl"`     // "BIN" (a chart), "ASC", "TXT"
	BBox     [4]float64 `json:"bbox"`     // [west, south, east, north]
	HasBBox  bool       `json:"-"`
}

CatalogEntry is one CATD record of an exchange-set catalogue (CATALOG.031).

func CatalogEntries

func CatalogEntries(catalog []byte) ([]CatalogEntry, error)

CatalogEntries decodes a CATALOG.031 exchange-set catalogue. Not chart-scoped: the catalogue describes an exchange set, not an open chart.

type ChartInfo

type ChartInfo struct {
	MinZoom, MaxZoom                 uint8
	Bands                            uint32
	HasBounds                        bool
	West, South, East, North         float64
	HasAnchor                        bool
	AnchorLat, AnchorLon, AnchorZoom float64
	// TileType is the archive's stored encoding (FormatMVT or FormatMLT).
	TileType TileFormat
	// NativeScale is the compilation scale (1:N) embedded by the per-chart bake;
	// 0 = unknown (a composed/foreign archive — derive from the zoom band).
	NativeScale int32
}

ChartInfo is a chart's fixed metadata — zoom range, bands, bounds, a good initial camera, the archive's tile encoding, and the compilation scale the bake embedded. HasBounds/HasAnchor guard the respective fields.

type ChartRecord

type ChartRecord struct {
	Name      string     `json:"name"`      // chart stem, e.g. "US5MD1MC"
	Scale     int        `json:"scale"`     // DSPM CSCL (1:N)
	Edition   string     `json:"edition"`   // DSID EDTN
	Update    string     `json:"update"`    // DSID UPDN (last applied update)
	IssueDate string     `json:"issueDate"` // DSID ISDT, YYYYMMDD
	Agency    int        `json:"agency"`    // DSID AGEN (550 = NOAA)
	BBox      [4]float64 `json:"bbox"`      // [west, south, east, north]
	HasBBox   bool       `json:"-"`
}

ChartRecord is one chart's identity + coverage, as recorded in its DSID/DSPM after the applied update chain.

func Charts

func Charts(path string) ([]ChartRecord, error)

Charts returns the per-chart metadata of the S-57 data at path — one .000 file (with its update chain applied) or a whole ENC_ROOT directory — for a host's chart-database scan.

type ComposeMeta

type ComposeMeta struct {
	MinZoom, MaxZoom         uint8
	Charts                   uint32
	West, South, East, North float64
}

ComposeMeta is a ComposeSource's served zoom range, coverage-carrying chart count, and union coverage bounds (degrees).

type ComposeSource

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

ComposeSource is a resident runtime compositor over open charts: the ownership partition loaded once, so Tile composes any tile on demand. It BORROWS its charts — they must outlive it — except charts opened for it by OpenCompose, which it owns and closes. Tile is serialised by an internal mutex (the compositor reads through the charts, which are not thread-safe).

func OpenCompose

func OpenCompose(paths []string) (*ComposeSource, error)

OpenCompose opens a resident compositor over the per-chart PMTiles at paths (each written by BakeChart / BakeTree): every path is opened as a chart (mmap'd, so the chart set is never fully resident) and the compositor OWNS those charts — Close releases them too. See OpenComposeCharts to compose over charts you keep.

func OpenComposeCharts

func OpenComposeCharts(charts []*Source) (*ComposeSource, error)

OpenComposeCharts opens a resident compositor over already-open charts, BORROWING them: every chart must outlive the compositor (Close the compositor first), and while it serves, don't call those charts' own methods from other goroutines. Charts whose archives embed no coverage are skipped; if none carries coverage the open fails with ErrNoCoverage. The ownership partition is handled by the engine — found beside the archives, reused when it matches, and rebuilt when it does not.

func OpenComposeTree

func OpenComposeTree(dir string) (*ComposeSource, error)

OpenComposeTree opens a WHOLE baked tree in one call: the engine recursively walks dir for the *.pmtiles archives a bake produced, mmaps and opens each (the cell set is never fully resident), and composes them. Unlike OpenCompose — which round-trips tile57_chart_open across cgo once per archive, each standing up per-chart machinery — the walk, open and compose all happen inside the one engine call on its batch path; on a ~1700-cell library that is the difference between a ~60 s and a ~5 s open. The compositor OWNS the archives it opened; Close alone releases the whole set. The ownership partition is the engine's: found beside the archives, reused when it matches, rebuilt when it does not.

func (*ComposeSource) Close

func (c *ComposeSource) Close() error

Close releases the compositor, then any charts OpenCompose opened for it. Borrowed charts (from OpenComposeCharts) stay open. Idempotent.

func (*ComposeSource) Meta

func (c *ComposeSource) Meta() ComposeMeta

Meta returns the compositor's served zoom range + union coverage bounds.

func (*ComposeSource) PNG

func (c *ComposeSource) PNG(lon, lat, zoom float64, width, height uint32, m Mariner) ([]byte, error)

PNG renders the composed view centred on (lon, lat) at web-mercator zoom into a width×height PNG, through the engine's native S-52 pixel path — portrayal, symbols, patterns, and text identical to the baked-tile web render. m controls the mariner settings (scheme, contours, viewing groups…); use MarinerDefaults() for the standard chart.

func (*ComposeSource) Query

func (c *ComposeSource) Query(lon, lat, zoom float64) ([]PickedFeature, error)

Query runs the composed cursor pick at (lon, lat) for a view at `zoom`: every feature under the point (areas by point-in-polygon, lines/points within an on-screen tolerance) as displayed at that zoom (SCAMIN-gated).

func (*ComposeSource) Surface

func (c *ComposeSource) Surface(lon, lat, zoom float64, width, height uint32, m Mariner, cb *SurfaceFuncs) error

Surface emits the composed view centred on (lon, lat) at zoom for a width×height viewport as a vector draw stream — the primitive for a host that renders on the GPU and re-portrays nothing on pan/zoom. The portrayal is north-up (view rotation 0); a rotating host rotates the world geometry itself and applies the per-call RotAlign flags to its marks.

func (*ComposeSource) Tile

func (c *ComposeSource) Tile(z uint8, x, y uint32) (body []byte, owned bool, err error)

Tile composes the tile (z,x,y) on demand, returning raw (decompressed) MLT bytes plus `owned` — whether the ownership partition says a chart SHOULD render here. body!=nil → composed (owned). body==nil && owned → a chart owns this ground but produced nothing (transient while its per-chart bake runs; an error state once bakes are done). body==nil && !owned → true empty ocean (safe to cache). Thread-safe (serialised).

type DepthUnit

type DepthUnit int32

DepthUnit selects the contour-label unit.

const (
	DepthMeters DepthUnit = C.TILE57_DEPTH_METERS
	DepthFeet   DepthUnit = C.TILE57_DEPTH_FEET
)

type DisplayCategory

type DisplayCategory uint8
const (
	DisplayBase     DisplayCategory = 0
	DisplayStandard DisplayCategory = 1
	DisplayOther    DisplayCategory = 2
)

type DisplayPlane

type DisplayPlane uint8

DisplayCategory is the S-52 display category a feature arrived on. A host applying SCAMIN itself must skip it for DisplayBase (the never-hide safety minimum). DisplayPlane is the S-101 DisplayPlane. It outranks DisplayPriority in paint order (S-52 PresLib §10.3.4.2).

const (
	PlaneUnderRadar DisplayPlane = 0
	PlaneOverRadar  DisplayPlane = 1
)

type Feature

type Feature struct {
	Class    string            // e.g. "DEPARE"
	Attrs    map[string]string // full S-57 attribute set, e.g. {"DRVAL1":"3.6"}
	Type     string            // GeoJSON type: Point/MultiPoint/LineString/MultiLineString/Polygon
	Geometry json.RawMessage   // the GeoJSON geometry object (lon/lat; soundings carry depth as a 3rd coord)
}

Feature is one S-57 feature from Features: its class acronym, the full attribute map (acronym → raw string value), and GeoJSON geometry.

func Features

func Features(path string, classes ...string) ([]Feature, error)

Features returns the features of the S-57 data at path (one chart, updates applied, or a whole ENC_ROOT) for the given object-class acronyms (e.g. "DEPARE", "DRGARE"), parsed without portrayal. A whole-ENC_ROOT extraction walks every chart — the caller owns that cost.

func FeaturesBytes

func FeaturesBytes(base []byte, classes ...string) ([]Feature, error)

FeaturesBytes is Features over in-memory base .000 bytes (read from a zip member, say). No update chain is applied.

type LocalPoint

type LocalPoint struct{ X, Y float32 }

LocalPoint is an anchor-relative offset in reference pixels.

type LocalRings

type LocalRings struct {
	Pts        []LocalPoint
	RingStarts []uint32
}

LocalRings is a multi-ring outline in reference px around an anchor.

type Mariner

type Mariner struct {
	Scheme                                                  Scheme
	ShallowContour, SafetyContour, DeepContour, SafetyDepth float64
	FourShadeWater                                          bool
	DepthUnit                                               DepthUnit
	DisplayBase, DisplayStandard, DisplayOther              bool
	DataQuality, ShowInformCallouts                         bool
	ShowMetaBounds, ShowIsolatedDangersShallow              bool
	BoundaryStyle                                           BoundaryStyle
	SimplifiedPoints, ShowFullSectorLines                   bool
	TextNames, ShowLightDescriptions, TextOther             bool
	DateDependent, HighlightDateDependent                   bool
	DateView                                                string  // "YYYYMMDD" or "" (today)
	IgnoreScamin                                            bool    // ?ignoreScamin: drop SCAMIN gating, show all in-band
	ScaminFilterGate                                        bool    // one live-filtered *_scamin layer per render-type instead of per-value buckets
	ShowOverscale                                           bool    // S-52 §10.1.10 AP(OVERSC01) overscale indication (default true)
	SizeScale                                               float64 // physical-scale multiplier for icon/line/text sizes (1.0 = verbatim)
	TextSizeScale                                           float64 // extra multiplier for TEXT labels on top of SizeScale (0 reads as 1.0)
	SoundingSizeScale                                       float64 // extra multiplier for SOUNDINGS on top of SizeScale (0 reads as 1.0)
	DeviceScale                                             float64 // device px per reference px: the HiDPI density the SURFACE paths are drawn at (0 reads as 1.0)
	Soundings                                               SoundingsMode
	ViewingGroupsOff                                        []int32 // S-52 §14.5 DENY-LIST: vg ids turned OFF (nil/empty = show all)
}

Mariner is the S-52 mariner display selection that drives the style patch — the Go mirror of tile57_mariner. Get a sensible default with MarinerDefaults.

func MarinerDefaults

func MarinerDefaults() Mariner

MarinerDefaults returns the canonical default mariner settings from libtile57.

type Meta

type Meta struct {
	MinZoom, MaxZoom uint8
	W, S, E, N       float64  // lon/lat bounds (degrees)
	Gzipped          bool     // tile bodies gzip-compressed (always false for tile57)
	Scamin           []uint32 // distinct SCAMIN denominators present (ascending)
	TileType         string   // "mvt" | "mlt" — the archive's stored encoding
}

Meta is a chart source's display metadata — the shape a host tile server needs to publish a TileJSON: zoom range, geographic bounds (degrees), whether tile bodies are gzip-compressed (always false here — tile57 serves decompressed tiles), the distinct SCAMIN denominators present (see Source.Scamin), and the tile encoding ("mvt" or "mlt" — the TileJSON/style `encoding` hint). A host with its own metadata type copies these fields across.

type PartitionBand

type PartitionBand int8

PartitionBand selects which ownership-partition map BakePartitionDebug emits.

const (
	// BandGoverning emits, at each zoom, the partition of the band that governs it —
	// the natural view (coarse bands zoomed out, finer bands zoomed in).
	BandGoverning PartitionBand = -1
	// The six navigational-purpose bands, finest→coarsest: each emits ITS OWN
	// partition map at every zoom (e.g. BandHarbor is the finest quilt).
	BandBerthing PartitionBand = 0
	BandHarbor   PartitionBand = 1
	BandApproach PartitionBand = 2
	BandCoastal  PartitionBand = 3
	BandGeneral  PartitionBand = 4
	BandOverview PartitionBand = 5
)

type PickedFeature

type PickedFeature struct {
	Class string // S-57 object-class acronym (e.g. "BOYLAT")
	S57   string // attribute JSON (acronym → value)
	Chart string // source chart name
}

PickedFeature is one feature under the cursor from Query — the S-52 §10.8 object pick, composed across chart boundaries.

type RGBA

type RGBA struct{ R, G, B, A uint8 }

RGBA is a resolved straight-alpha colour from the active palette.

type RotAlign

type RotAlign uint8

RotAlign says what a mark's rotation is referenced to. Geometry arrives ALREADY rotated to its own angle; the flag tells a host with a rotated view (course-up/head-up) whether to ADD the view rotation.

const (
	// AlignViewport: screen-relative — the mark stays upright on screen; a
	// rotated view must NOT add its rotation (buoys, ordinary labels).
	AlignViewport RotAlign = 0
	// AlignMap: chart-relative — a rotated view ADDS its rotation so the mark
	// turns with the chart (ORIENT symbols, depth-contour values).
	AlignMap RotAlign = 1
)

type Scheme

type Scheme int32

Scheme selects the S-52 colour palette (day/dusk/night).

const (
	SchemeDay   Scheme = C.TILE57_SCHEME_DAY
	SchemeDusk  Scheme = C.TILE57_SCHEME_DUSK
	SchemeNight Scheme = C.TILE57_SCHEME_NIGHT
)

func SchemeFromString

func SchemeFromString(s string) Scheme

SchemeFromString maps "day"/"dusk"/"night" to a Scheme (default day).

type SoundingsMode

type SoundingsMode uint8

SoundingsMode gives spot soundings their own switch, independent of the display category (S-52 files SOUNDG under OTHER, but the everyday ECDIS setting is STANDARD + soundings ON).

const (
	SoundingsFollowCategory SoundingsMode = 0 // the old behaviour: OTHER controls them
	SoundingsShow           SoundingsMode = 1 // show whatever the category says
	SoundingsHide           SoundingsMode = 2 // hide whatever the category says
)

type Source

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

Source is an open libtile57 chart: ONE baked PMTiles archive. Construct it with Open (mmap'd path) or OpenBytes (copied); release it with Source.Close. It is safe for concurrent use: the underlying handle is not thread-safe, so calls are serialized internally.

func Open

func Open(path string) (*Source, error)

Open opens a baked PMTiles archive from a file path, mmap'd — a whole chart library can be open without being resident. The file must stay in place while the Source is open.

func OpenBytes

func OpenBytes(pmtiles []byte) (*Source, error)

OpenBytes opens a baked PMTiles archive from in-memory bytes (e.g. straight from BakeChart, before any file exists). Bytes are copied.

func (*Source) Close

func (s *Source) Close() error

Close releases the source and all cached tiles. It is idempotent. Per the ABI's lifetime rule, callers must not Close while any borrower (a compositor built over this Source, a goroutine mid-call) can still read from it.

func (*Source) Coverage

func (s *Source) Coverage() ([][][2]float64, error)

Coverage returns the chart's M_COVR data-coverage polygons (one exterior ring per polygon, lon/lat points) from the coverage the bake embedded in the archive metadata — the real coverage a host reports so a quilt fills gaps to coarser charts. Nil when the archive embeds none (a composed/foreign archive).

func (*Source) Info

func (s *Source) Info() ChartInfo

Info returns the chart's fixed metadata in one call.

func (*Source) Meta

func (s *Source) Meta() Meta

Meta reports the source's display metadata (zoom range, bounds, SCAMIN manifest). tile57 serves decompressed tiles, so Gzipped is always false. Bounds fall back to the world extent when the archive reports none.

func (*Source) PNG

func (s *Source) PNG(lon, lat, zoom float64, width, height uint32, m Mariner) ([]byte, error)

PNG renders this chart's view centred on (lon, lat) at web-mercator zoom into a width×height PNG through the engine's native S-52 pixel path. See ComposeSource.PNG for the composed form.

func (*Source) Query

func (s *Source) Query(lon, lat, zoom float64) ([]PickedFeature, error)

Query runs this chart's cursor pick at (lon, lat) for a view at `zoom`. See ComposeSource.Query for the composed form.

func (*Source) Scamin

func (s *Source) Scamin() []uint32

Scamin returns the distinct SCAMIN denominators present in the source (the live SCAMIN manifest, ascending, from the archive metadata), so the client builds one native fractional-minzoom bucket layer per value. Cached after the first call.

func (*Source) Surface

func (s *Source) Surface(lon, lat, zoom float64, width, height uint32, m Mariner, cb *SurfaceFuncs) error

Surface is the single-chart form of ComposeSource.Surface.

func (*Source) TileSurface

func (s *Source) TileSurface(z uint8, x, y uint32, m Mariner, cb *SurfaceFuncs) error

TileSurface portrays ONE tile (z, x, y) through the same S-52 portrayal and callbacks — the unit a host tessellates once and caches keyed by (chart, z, x, y), composing views from cached tiles. Decluttering is per-tile.

type SurfaceFeature

type SurfaceFeature struct {
	Class           string          // object-class acronym ("" if none)
	Scamin          int64           // SCAMIN 1:N denominator (<= 0 → always visible)
	DisplayPriority int32           // S-52 draw priority (S-101 DrawingPriority, 0..30)
	DisplayPlane    DisplayPlane    // S-101 DisplayPlane; outranks DisplayPriority in paint order
	DisplayCategory DisplayCategory // the display category the feature came in on
}

SurfaceFeature tags the draw calls that belong to one S-57 feature.

type SurfaceFuncs

type SurfaceFuncs struct {
	// FillArea fills world rings; evenOdd selects the even-odd rule.
	FillArea func(f SurfaceFeature, rings WorldRings, color RGBA, evenOdd bool)
	// StrokeLine strokes world polylines widthPx wide; dashes in px (0,0 solid).
	StrokeLine func(f SurfaceFeature, lines WorldRings, widthPx, dashOn, dashOff float32, color RGBA)
	// DrawSymbol draws a point symbol: world anchor + local outline. strokeW > 0
	// means the rings are a polyline stroked that wide (px), else filled. The
	// outline arrives already rotated; align says whether that angle is
	// chart-relative (a rotated view additionally rotates AlignMap outlines).
	DrawSymbol func(f SurfaceFeature, anchor WorldPoint, rings LocalRings, color RGBA, evenOdd bool, strokeW float32, align RotAlign)
	// DrawText draws shaped label glyphs as local outline rings (even-odd), with
	// an optional halo (halo.A == 0 → none). align as in DrawSymbol. textGroup is
	// the label's S-52 text group (§14.5) — a property of the LABEL, not the
	// feature, since one feature can carry several. Group 11 is important text
	// (it ignores the mariner's text switches); 21/26/29 names, 23 light
	// descriptions, 0 none.
	DrawText func(f SurfaceFeature, anchor WorldPoint, glyphs LocalRings, color, halo RGBA, haloPx float32, align RotAlign, textGroup int)
}

SurfaceFuncs receives the draw stream. Nil members skip those calls. Slices are copies owned by the callee; retain freely.

type TileFormat

type TileFormat uint8

TileFormat is a tile encoding (tile57_tile_type). The zero value means "the engine default" (MLT).

const (
	FormatDefault TileFormat = 0                      // engine default (MLT)
	FormatMVT     TileFormat = C.TILE57_TILE_TYPE_MVT // Mapbox Vector Tile
	FormatMLT     TileFormat = C.TILE57_TILE_TYPE_MLT // MapLibre Tile (the default bake format)
)

func EncodingFormat

func EncodingFormat(encoding string) TileFormat

EncodingFormat maps a TileJSON/style `encoding` string ("mlt"/"mvt"/"") to the TileFormat StyleTemplate takes ("" and "mvt" both mean MVT — no hint emitted).

func (TileFormat) Encoding

func (f TileFormat) Encoding() string

Encoding returns the MapLibre vector-source `encoding` value for the format ("mlt" or "mvt") — the hint a host puts on its style sources / TileJSON so maplibre-gl (>=5.12) picks the matching decoder.

type WorldPoint

type WorldPoint struct{ X, Y float64 }

WorldPoint is a web-mercator [0,1] position (y down).

type WorldRings

type WorldRings struct {
	Pts        []WorldPoint
	RingStarts []uint32
}

WorldRings is a multi-ring path in world space: ring k spans [RingStarts[k], RingStarts[k+1]) (the last runs to len(Pts)). Rings close implicitly.

Jump to

Keyboard shortcuts

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