Documentation
¶
Overview ¶
Package ndslivemath provides NDS.Live mathematical utilities for geographic tiling: WGS84 coordinate handling, Morton (Z-order) codes, packed tile IDs and NDS-coordinate bounding boxes.
This is the Go port of the reference Python and C++ implementations. The public surface mirrors the Python package ndslive.math, adapted to idiomatic Go (errors instead of exceptions, multiple return values instead of tuples).
Index ¶
- Constants
- Variables
- func BoundingBoxFromTileIds(tiles []PackedTileId) (int64, int64, int64, int64, error)
- func DegreesToMeters(lonDegrees, latDegrees, atLatitude float64) (float64, float64)
- func NdsDistanceToMeters(ndsXDistance, ndsYDistance, atLatitude float64) (float64, float64)
- type MortonCode
- type NdsBoundingBox
- type Orientation
- type PackedTileId
- func GetTileIdsForBoundingBox(swX, swY, neX, neY int32, level int) []PackedTileId
- func NewPackedTileId(value int32) (PackedTileId, error)
- func NewPackedTileIdFromUnsigned(value uint64) (PackedTileId, error)
- func PackedTileIdFromMortonAndLevel(mortonCode MortonCode, level int) (PackedTileId, error)
- func PackedTileIdFromTileIndex(mortonNumber uint32, level int) (PackedTileId, error)
- func (t PackedTileId) Center() (int64, int64)
- func (t PackedTileId) DimensionsInMeters() (float64, float64)
- func (t PackedTileId) EastNeighbour() PackedTileId
- func (t PackedTileId) Level() int
- func (t PackedTileId) MortonNumber() uint32
- func (t PackedTileId) NorthEastCorner() (int64, int64)
- func (t PackedTileId) NorthNeighbour() PackedTileId
- func (t PackedTileId) Size() uint32
- func (t PackedTileId) SouthNeighbour() PackedTileId
- func (t PackedTileId) SouthWestCorner() (int64, int64)
- func (t PackedTileId) String() string
- func (t PackedTileId) Value() int32
- func (t PackedTileId) WestNeighbour() PackedTileId
- type Polygon
- func (p *Polygon) AddVertex(position Wgs84)
- func (p *Polygon) AddVertices(vertices []Wgs84)
- func (p Polygon) At(i int) Wgs84
- func (p Polygon) IsValid() bool
- func (p Polygon) Len() int
- func (p Polygon) Orientation() Orientation
- func (p *Polygon) Set(i int, value Wgs84)
- func (p *Polygon) SetType(polygonType PolygonType)
- func (p Polygon) Type() PolygonType
- func (p Polygon) Vertices() []Wgs84
- type PolygonTriangulation
- type PolygonType
- type Vec2
- type Wgs84
- func (w Wgs84) BearingFrom(other Wgs84) float64
- func (w Wgs84) DistanceTo(other Wgs84) float64
- func (w Wgs84) Dx() float64
- func (w Wgs84) Dy() float64
- func (w Wgs84) Equals(other Wgs84) bool
- func (w Wgs84) Latitude() float64
- func (w Wgs84) Longitude() float64
- func (w *Wgs84) Normalize()
- func (w Wgs84) Sub(other Wgs84) Wgs84
- func (w Wgs84) ToDegreeMinutesSeconds() (string, string)
- func (w Wgs84) ToNdsCoordinates() (int32, int32)
- type Wgs84AABB
- func (b Wgs84AABB) AvgMercatorStretch() float64
- func (b Wgs84AABB) Center() Wgs84
- func (b Wgs84AABB) Contains(point Wgs84) bool
- func (b Wgs84AABB) ContainsAntiMeridian() bool
- func (b Wgs84AABB) Intersects(other Wgs84AABB) bool
- func (b Wgs84AABB) NE() Wgs84
- func (b Wgs84AABB) NW() Wgs84
- func (b Wgs84AABB) NumTileIds(lv int) int
- func (b Wgs84AABB) SE() Wgs84
- func (b Wgs84AABB) SW() Wgs84
- func (b Wgs84AABB) Size() Vec2
- func (b Wgs84AABB) SplitOverAntiMeridian() (left, right Wgs84AABB, ok bool)
- func (b Wgs84AABB) TileLevel(minNumTiles int) int
- func (b Wgs84AABB) Valid() bool
- func (b Wgs84AABB) Vertices() []Wgs84
- type Wgs84Polygon
Constants ¶
const ( // EarthRadiusInMeters is the approximate radius of Earth used for // great-circle (haversine) distance calculations. EarthRadiusInMeters = 6371000.8 // MetersPerDegree is the approximate number of meters per degree of // latitude (and of longitude at the equator). MetersPerDegree = 111320.0 )
WGS84 / NDS conversion constants. These mirror the Python reference exactly.
Variables ¶
var ( // LonNdsDelta is 360 / (2^32 - 1). LonNdsDelta = 360.0 / float64((uint64(1)<<32)-1) // LatNdsDelta is 180 / (2^31 - 1). LatNdsDelta = 180.0 / float64((uint64(1)<<31)-1) )
LonNdsDelta and LatNdsDelta are the smallest representable angular steps in the NDS coordinate system. They are defined as package-level variables (not const) because they involve floating-point division.
var ( // LonNdsDeltaPow2 is 360 / 2^32 (== 8.381903171539307e-08). LonNdsDeltaPow2 = 360.0 / math.Exp2(32) // LatNdsDeltaPow2 is 180 / 2^31 (== 8.381903171539307e-08, numerically // equal to LonNdsDeltaPow2). LatNdsDeltaPow2 = 180.0 / math.Exp2(31) // LonMin is the minimum longitude (-180). LonMin = -180.0 // LonMax is the maximum longitude (180 - LonNdsDeltaPow2 == 179.99999991618097). LonMax = 180.0 - LonNdsDeltaPow2 // LatMin is the minimum latitude (-90). LatMin = -90.0 // LatMax is the maximum latitude (90 - LatNdsDeltaPow2). LatMax = 90.0 - LatNdsDeltaPow2 )
Geometry-layer constants mirroring the C++ Wgs84<double> static members (cpp/include/ndsmath/wgs84.h). These intentionally use a power-of-two denominator (2^32 / 2^31) rather than LonNdsDelta / LatNdsDelta above (which use 2^32 - 1 / 2^31 - 1). The difference shows up in the 13th significant digit, but it is load-bearing for the geometry layer: Wgs84AABB antimeridian handling and tile-from-index construction must match the C++ reference bit-for-bit. Do NOT reuse LonNdsDelta / LatNdsDelta in the geometry layer.
Functions ¶
func BoundingBoxFromTileIds ¶
BoundingBoxFromTileIds computes the minimal NDS bounding box covering all the given tiles. It returns (minX, minY, maxX, maxY) where the NE corner has been decremented by 1 so that the box is inclusive (the NorthEastCorner of a tile is exclusive). It returns an error if tiles is empty.
Values are int64 because the intermediate (exclusive) maxima may exceed int32; the decremented results returned here are always within int32 range for valid tiles. A single-tile box round-trips: passing the result back through GetTileIdsForBoundingBox at the same level yields exactly that tile.
func DegreesToMeters ¶
DegreesToMeters converts degree distances to meters at a given latitude.
Longitude distance shrinks toward the poles (scaled by cos(latitude)); latitude distance is constant. Returns (widthMeters, heightMeters).
func NdsDistanceToMeters ¶
NdsDistanceToMeters converts NDS coordinate distances to meters at a given latitude. Returns (widthMeters, heightMeters).
Types ¶
type MortonCode ¶
type MortonCode struct {
// contains filtered or unexported fields
}
MortonCode implements Morton encoding (Z-order curve) for 2D NDS coordinates. It wraps a 64-bit unsigned value and provides conversion to and from NDS integer coordinates.
func MortonFromNdsCoordinates ¶
func MortonFromNdsCoordinates(xIn, yIn int32) MortonCode
MortonFromNdsCoordinates encodes NDS integer coordinates into a Morton (Z-order) code. It is the inverse of MortonCode.ToNdsCoordinates.
x is NDS longitude (signed 32-bit), y is NDS latitude (signed 31-bit); both are wrapped into range before encoding. Bit 63 is masked off, matching the Python/C++ reference (morton_code &= ~(1 << 63)).
The interleave loop is ported verbatim from morton.py. Note that the arithmetic is performed on signed 64-bit values (mirroring Python's arbitrary-precision ints and C++'s int64_t), then OR-ed into the unsigned accumulator. Using int64 here is essential: the X high bit is extracted at bit position 62 during the 32nd X step, and y is shifted left by 1 up front, so values can exceed the int32 range during the loop.
func NewMortonCode ¶
func NewMortonCode(value uint64) MortonCode
NewMortonCode constructs a MortonCode from a raw 64-bit code value.
Most callers use MortonFromNdsCoordinates instead; this constructor is for round-tripping a previously computed code. The value is stored as-is (it is already 64-bit unsigned in Go, so no masking is needed for the full width).
func (MortonCode) ToNdsCoordinates ¶
func (m MortonCode) ToNdsCoordinates() (int32, int32)
ToNdsCoordinates decodes this Morton code back into NDS integer coordinates. It is the inverse of MortonFromNdsCoordinates and returns (x, y) as signed NDS longitude (32-bit) and latitude (31-bit).
The deinterleave loop is ported verbatim from morton.py. The accumulators x and y are computed as int64 (the same width the encoder used) and then sign-adjusted against XBASE / YBASE before being narrowed to int32.
func (MortonCode) Value ¶
func (m MortonCode) Value() uint64
Value returns the raw 64-bit Morton code value (matches the C++/Python API).
type NdsBoundingBox ¶
type NdsBoundingBox struct {
MinX int32 // SW corner longitude (NDS coords)
MinY int32 // SW corner latitude (NDS coords)
MaxX int32 // NE corner longitude (NDS coords)
MaxY int32 // NE corner latitude (NDS coords)
}
NdsBoundingBox is an axis-aligned bounding box in NDS coordinates.
NDS coordinates use integers for fast comparisons:
- X (longitude): 32-bit signed integer
- Y (latitude): 31-bit signed integer
MinX/MinY are the SW corner; MaxX/MaxY are the NE corner.
func NdsBoundingBoxFromTile ¶
func NdsBoundingBoxFromTile(tile PackedTileId) NdsBoundingBox
NdsBoundingBoxFromTile creates a bounding box covering the given tile's area.
The NE corner is the tile's exclusive corner (SW + size); for low-level tiles this can exceed the int32 range, so the corner is narrowed via reinterpreting conversion exactly as the C++ reference does with int32_t.
func NdsBoundingBoxFromWgs84Corners ¶
func NdsBoundingBoxFromWgs84Corners(sw, ne Wgs84) NdsBoundingBox
NdsBoundingBoxFromWgs84Corners creates a bounding box from WGS84 corner coordinates (sw = min lon/lat, ne = max lon/lat), converting each corner to NDS coordinates.
func (NdsBoundingBox) Contains ¶
func (b NdsBoundingBox) Contains(other NdsBoundingBox) bool
Contains reports whether other is completely inside this bounding box.
func (NdsBoundingBox) Intersects ¶
func (b NdsBoundingBox) Intersects(other NdsBoundingBox) bool
Intersects reports whether this bounding box overlaps (shares any area with) other.
type Orientation ¶
type Orientation int
Orientation is the winding order of a polygon. The integer values match the C++ enum (cpp/include/ndsmath/polygon.h) and are part of the parity output.
const ( // Clockwise winding (negative signed area). Clockwise Orientation = -1 // InvalidOrientation: not a simple polygon / single triangle, or zero area. InvalidOrientation Orientation = 0 // CounterClockwise winding (positive signed area). CounterClockwise Orientation = 1 )
type PackedTileId ¶
type PackedTileId struct {
// contains filtered or unexported fields
}
PackedTileId represents a tile in the hierarchical NDS.Live tiling system.
Per the NDS.Live standard, tile IDs are signed 32-bit integers. For levels 0-14 the values are positive; for level 15 the values are negative (-2147483648 to -1) because the level bit (bit 31) coincides with the sign bit of a signed int32.
Internally the value is stored as an unsigned 32-bit integer so that all bit operations are free of sign-bit complications. Conversion between signed and unsigned happens only at the API boundary: constructors accept either representation, and Value returns the signed int32 mandated by the standard.
func GetTileIdsForBoundingBox ¶
func GetTileIdsForBoundingBox(swX, swY, neX, neY int32, level int) []PackedTileId
GetTileIdsForBoundingBox returns all tile IDs that intersect the bounding box defined by the south-west and north-east corners in NDS coordinates, at the given level.
Floor division is used for the corner-to-tile-index mapping (matching Python's // operator), which matters for negative coordinates.
func NewPackedTileId ¶
func NewPackedTileId(value int32) (PackedTileId, error)
NewPackedTileId constructs a PackedTileId from a signed int32 tile ID value.
Per the NDS.Live standard, level 15 tiles have negative values (-2147483648 to -1) while levels 0-14 have positive values. This accepts the signed representation directly; for unsigned input use NewPackedTileIdFromUnsigned.
It returns an error if the resulting tile ID is invalid.
func NewPackedTileIdFromUnsigned ¶
func NewPackedTileIdFromUnsigned(value uint64) (PackedTileId, error)
NewPackedTileIdFromUnsigned constructs a PackedTileId from an unsigned tile ID value. Values outside the 32-bit range are masked to 32 bits, mirroring the Python constructor. It returns an error if the tile ID is invalid.
func PackedTileIdFromMortonAndLevel ¶
func PackedTileIdFromMortonAndLevel(mortonCode MortonCode, level int) (PackedTileId, error)
PackedTileIdFromMortonAndLevel creates the PackedTileId of the tile at the given level that contains the full-precision NDS point encoded by mortonCode.
The resulting tile's MortonNumber will NOT generally equal mortonCode.Value(); use PackedTileIdFromTileIndex if you need a specific morton number. level must be in [0, 15].
func PackedTileIdFromTileIndex ¶
func PackedTileIdFromTileIndex(mortonNumber uint32, level int) (PackedTileId, error)
PackedTileIdFromTileIndex creates a PackedTileId directly from a tile morton number and level, without any coordinate conversion.
mortonNumber must be in [0, 2^(2*level+1) - 1] and level in [0, 15]; otherwise an error is returned.
func (PackedTileId) Center ¶
func (t PackedTileId) Center() (int64, int64)
Center returns the center of the tile in NDS coordinates.
Returned as int64 because, although the center always fits in int32 for valid tiles, the corner arithmetic it derives from can exceed int32.
func (PackedTileId) DimensionsInMeters ¶
func (t PackedTileId) DimensionsInMeters() (float64, float64)
DimensionsInMeters returns the tile's (width, height) in meters, computed at the tile's center latitude. Width varies with cos(latitude); height is constant.
func (PackedTileId) EastNeighbour ¶
func (t PackedTileId) EastNeighbour() PackedTileId
EastNeighbour returns the tile to the east at the same level, wrapping at the antimeridian.
func (PackedTileId) Level ¶
func (t PackedTileId) Level() int
Level returns the level of the tile (0..15).
func (PackedTileId) MortonNumber ¶
func (t PackedTileId) MortonNumber() uint32
MortonNumber returns the tile's Morton number (the value with the level-specific offset removed).
func (PackedTileId) NorthEastCorner ¶
func (t PackedTileId) NorthEastCorner() (int64, int64)
NorthEastCorner returns the north-east (EXCLUSIVE) corner of the tile in NDS coordinates: the first coordinate outside the tile, i.e. SW + size.
Returned as int64 because for low levels (e.g. level 0) the exclusive corner is 2^31, which exceeds the signed int32 range.
func (PackedTileId) NorthNeighbour ¶
func (t PackedTileId) NorthNeighbour() PackedTileId
NorthNeighbour returns the tile to the north at the same level, wrapping at the north pole.
func (PackedTileId) Size ¶
func (t PackedTileId) Size() uint32
Size returns the tile's edge length in NDS coordinate units.
func (PackedTileId) SouthNeighbour ¶
func (t PackedTileId) SouthNeighbour() PackedTileId
SouthNeighbour returns the tile to the south at the same level, wrapping at the south pole.
func (PackedTileId) SouthWestCorner ¶
func (t PackedTileId) SouthWestCorner() (int64, int64)
SouthWestCorner returns the south-west (inclusive) corner of the tile in NDS coordinates. Returned as int64 for a uniform corner API; SW values always fit in int32.
func (PackedTileId) Value ¶
func (t PackedTileId) Value() int32
Value returns the tile ID as a signed int32 per the NDS.Live standard. Level 15 tiles return negative values; levels 0-14 return positive values.
func (PackedTileId) WestNeighbour ¶
func (t PackedTileId) WestNeighbour() PackedTileId
WestNeighbour returns the tile to the west at the same level, wrapping at the antimeridian.
type Polygon ¶
type Polygon struct {
// contains filtered or unexported fields
}
Polygon is a set of WGS84 vertices with a topology type and an orientation query. It mirrors the C++ Polygon<Vector> template, specialized directly to a slice of Wgs84 vertices. Orientation is computed on the raw (lon, lat) plane (no WGS84 normalization, no antimeridian handling).
Wgs84Polygon embeds Polygon and overrides validity semantics via its own IsValid method.
func NewPolygon ¶
func NewPolygon(polygonType PolygonType) Polygon
NewPolygon constructs an empty polygon of the given type.
func NewPolygonWithVertices ¶
func NewPolygonWithVertices(polygonType PolygonType, vertices []Wgs84) Polygon
NewPolygonWithVertices constructs a polygon of the given type with the supplied vertices (copied).
func (*Polygon) AddVertices ¶
AddVertices appends a list of vertices, in order.
func (Polygon) At ¶
At returns the vertex at index i (no bounds check beyond Go's own, mirroring the C++ operator[]).
func (Polygon) IsValid ¶
IsValid reports whether this is a valid polygon. The base implementation requires at least one vertex; Wgs84Polygon overrides it to require >= 3.
func (Polygon) Orientation ¶
func (p Polygon) Orientation() Orientation
Orientation computes the winding order via the signed shoelace formula.
Only works for SimplePolygon and a single-triangle TriangleList (exactly 3 vertices). All other types return InvalidOrientation without computing area. Collinear vertices (zero area) also return InvalidOrientation. Uses raw (lon, lat) doubles; no normalization.
func (*Polygon) SetType ¶
func (p *Polygon) SetType(polygonType PolygonType)
SetType sets the polygon type.
type PolygonTriangulation ¶
type PolygonTriangulation struct{}
PolygonTriangulation triangulates simple polygons by ear clipping (O(n^2)).
Port of the C++ PolygonTriangulation (cpp/include/ndsmath/ polygontriangulation.{h,cpp}). The C++ implementation uses a pointer-linked ring of partition vertices; this port uses an index-linked slice of partitionVertex (prev / next integer indices) to avoid manual memory management while reproducing the same traversal.
The set of output triangles is deterministic, but the ordering of triangles and the rotation of each triangle's three vertices are implementation- specific (driven by the "most extruded ear" tie-break and floating-point angle comparisons). Triangulation output is therefore NOT part of the cross-language parity vectors; tests assert structure (type and vertex count) only.
func (PolygonTriangulation) TriangulateByEarClipping ¶
func (PolygonTriangulation) TriangulateByEarClipping(polygon Wgs84Polygon) Wgs84Polygon
TriangulateByEarClipping triangulates a CCW simple polygon into a TriangleList.
The input must be a SimplePolygon with at least 3 vertices, in counter-clockwise order. It returns a Wgs84Polygon of type TriangleList on success (3 * (n - 2) vertices), or a polygon of type PolygonUnknown on failure (wrong type, too few vertices, or no ear found).
type PolygonType ¶
type PolygonType int
PolygonType is the topology of a polygon. The integer values match the C++ enum and are part of the parity output.
const ( // SimplePolygon is a shape with an arbitrary number of vertices and no // holes; the last vertex connects back to the first. SimplePolygon PolygonType = 0 // TriangleStrip is a triangle strip. TriangleStrip PolygonType = 1 // TriangleFan is a triangle fan. TriangleFan PolygonType = 2 // TriangleList is a set of independent triangles; three consecutive // vertices form one. TriangleList PolygonType = 3 // PolygonUnknown is an illegal polygon type, used to signal failure. PolygonUnknown PolygonType = 4 )
type Vec2 ¶
Vec2 is a plain, un-normalized 2D vector (X, Y).
The geometry layer (Wgs84AABB in particular) needs a raw (dx, dy) extent that can legitimately exceed 360 / 180 degrees or be negative — unlike Wgs84, whose constructor wraps longitude and clamps latitude. Reusing Wgs84 for a size/extent would silently corrupt those values via normalization, so this small struct is used instead.
It mirrors the role of glm::dvec2 (used as Wgs84<T>::vec2_t) in the C++ reference (cpp/include/ndsmath/wgs84aabb.h). X is the longitude/horizontal component, Y the latitude/vertical component.
type Wgs84 ¶
type Wgs84 struct {
Lon float64 // longitude in degrees, normalized into [-180, 180)
Lat float64 // latitude in degrees, clamped into [-90, 90 - LatNdsDelta]
Alt float64 // altitude in meters above the WGS84 ellipsoid
}
Wgs84 represents a point on the Earth's surface using the WGS84 coordinate system. Lon (X) and Lat (Y) are in degrees; Alt (Z) is meters above the WGS84 ellipsoid.
func NewWgs84 ¶
NewWgs84 constructs a WGS84 point in degrees and normalizes it: longitude is wrapped into [-180, 180) and latitude is clamped into [-90, 90 - LatNdsDelta].
func Wgs84FromMortonCode ¶
func Wgs84FromMortonCode(mortonCode MortonCode) Wgs84
Wgs84FromMortonCode constructs a Wgs84 point (with Alt=0) from a Morton code.
This mirrors the C++ Wgs84<double>::fromMortonCode (cpp/include/ndsmath/wgs84.h). Note that it scales BOTH the NDS x (longitude) and the NDS y (latitude) by the same factor 360 / 2^32 — unlike Wgs84FromNdsCoordinates, which scales latitude by 180 / 2^31. This difference is intentional in the reference and is relied upon by the geometry layer (e.g. the Wgs84AABB tile-from-index constructor); do not "fix" it.
func Wgs84FromNdsCoordinates ¶
Wgs84FromNdsCoordinates constructs a Wgs84 point (with Alt=0) from NDS integer coordinates. It is the inverse of ToNdsCoordinates.
func (Wgs84) BearingFrom ¶
BearingFrom returns the initial bearing (forward azimuth) in radians from other toward this point, measured clockwise from true north.
func (Wgs84) DistanceTo ¶
DistanceTo returns the great-circle distance in meters to another point, computed via the haversine formula using EarthRadiusInMeters.
func (Wgs84) Equals ¶
Equals reports whether two points have approximately equal longitude and latitude (relative tolerance 1e-12), mirroring Python's math.isclose.
func (*Wgs84) Normalize ¶
func (w *Wgs84) Normalize()
Normalize wraps longitude into [-180, 180) and clamps latitude into [-90, 90 - LatNdsDelta]. It is called automatically by NewWgs84; call it explicitly after mutating Lon or Lat directly.
This mirrors the Python Wgs84.normalize() logic precisely, including the math.Mod (fmod) sign-preserving wrap and the boundary snapping for values very close to the positive limit.
func (Wgs84) Sub ¶
Sub returns the component-wise difference of this point and other, then re-normalizes the result (longitude wrap, latitude clamp). It mirrors the re-normalizing Wgs84 operator- of the C++/Python reference, which the ear-clipping triangulation relies on.
func (Wgs84) ToDegreeMinutesSeconds ¶
ToDegreeMinutesSeconds formats this point as degrees-minutes-seconds strings. It returns (latStr, lonStr) in the form "DD° MM' SS.ss\" N|S" and "DDD° MM' SS.ss\" E|W".
func (Wgs84) ToNdsCoordinates ¶
ToNdsCoordinates converts this WGS84 point to NDS integer coordinates.
NDS allows floor, truncate, or round for this conversion. Floor is used here (as recommended by NDS and matching the reference implementations). This is significant for negative coordinates, which floor toward negative infinity rather than truncating toward zero.
type Wgs84AABB ¶
type Wgs84AABB struct {
// contains filtered or unexported fields
}
Wgs84AABB is a WGS84 axis-aligned bounding box.
Port of the C++ Wgs84AABB<T> (cpp/include/ndsmath/wgs84aabb.h), specialized to float64. The box is stored as a south-west corner (a Wgs84) plus a raw Vec2 size (a (dx, dy) extent that is NOT normalized).
The geometry layer deliberately uses the power-of-two NDS deltas (LonNdsDeltaPow2 etc.) so antimeridian handling and tile-from-index construction match the C++ reference bit-for-bit.
func NewWgs84AABB ¶
NewWgs84AABB constructs an AABB from a south-west corner and a size.
After storing, if the box is valid, the height is clamped so the top never exceeds +90 degrees (the excessHeight correction). An invalid box stores size unmodified.
func Wgs84AABBFromCenterAndTileLimit ¶
Wgs84AABBFromCenterAndTileLimit constructs an AABB from a center, a soft tile-count limit, and a level.
func Wgs84AABBFromTile ¶
func Wgs84AABBFromTile(tileID PackedTileId) Wgs84AABB
Wgs84AABBFromTile constructs an AABB covering a tile (Path A: via Wgs84FromMortonCode).
Mirrors the C++ Wgs84AABB(PackedTileId) constructor: the SW/NE NDS corners are wrapped into a MortonCode and converted via Wgs84FromMortonCode, so both axes are scaled by 360 / 2^32 (NOT Wgs84FromNdsCoordinates, which scales latitude by 180 / 2^31 and would diverge from C++).
func (Wgs84AABB) AvgMercatorStretch ¶
AvgMercatorStretch returns the Mercator-projection vertical stretch factor.
Transcendental; not part of the cross-language parity vectors (asserted only for finiteness in unit tests).
func (Wgs84AABB) Contains ¶
Contains reports whether point lies within the box (inclusive on all edges).
func (Wgs84AABB) ContainsAntiMeridian ¶
ContainsAntiMeridian reports whether the horizontal extent crosses the anti-meridian (+/-180).
func (Wgs84AABB) Intersects ¶
Intersects is the axis-aligned interval-overlap test against another box.
This is the fixed test: a pure interval overlap on longitude and latitude. Edge-touching counts as intersecting; it correctly detects cross-shaped overlaps and never recurses on disjoint boxes.
func (Wgs84AABB) NumTileIds ¶
NumTileIds returns the approximate number of tiles at level lv contained in this box.
Mirrors the C++ numTileIds: tileWidth = 180 / float32(2^lv) and a component-wise ceil of size / tileWidth. The C++ code casts 1u<<lv to a 32-bit float; for lv <= 31 that cast is exact for powers of two. The product is truncated toward zero to an integer (matching the reference int() cast), so it can be negative for invalid (negative-size) boxes; that is preserved.
func (Wgs84AABB) SplitOverAntiMeridian ¶
SplitOverAntiMeridian splits a box crossing the anti-meridian into a left and a right half.
Only meaningful when ContainsAntiMeridian is true. Returns the two normalized boxes and ok=true, or two zero boxes and ok=false if the box does not actually extend past LonMax.
func (Wgs84AABB) TileLevel ¶
TileLevel returns the first level (0..15) whose tile count is at least minNumTiles. Returns 15 if no level in 0..15 reaches the threshold.
type Wgs84Polygon ¶
type Wgs84Polygon struct {
Polygon
}
Wgs84Polygon is a simple polygon of WGS84 vertices with bounding box, median, and Separating-Axis-Theorem collision helpers.
Port of the C++ HighPrecWgs84Polygon (cpp/include/ndsmath/wgs84polygon.h). It embeds Polygon, defaults to SimplePolygon, and overrides validity to require at least three vertices. The collision math runs on raw (lon, lat) doubles: no normalization, no antimeridian handling.
func EarthWrappingPoly ¶
func EarthWrappingPoly() Wgs84Polygon
EarthWrappingPoly returns the 4-vertex sentinel polygon wrapping the whole Earth.
Constructed from (-180,-90), (-180,90), (180,-90), (180,90). These coordinates pass through Wgs84 normalization, so the stored values are not exactly those literals. This polygon is only used as an identity sentinel in CollidesWith via Equals; its exact normalized coordinates are not part of cross-language parity.
func NewWgs84Polygon ¶
func NewWgs84Polygon() Wgs84Polygon
NewWgs84Polygon constructs an empty simple WGS84 polygon.
func NewWgs84PolygonOfType ¶
func NewWgs84PolygonOfType(polygonType PolygonType) Wgs84Polygon
NewWgs84PolygonOfType constructs an empty WGS84 polygon of the given type.
func NewWgs84PolygonOfTypeWithVertices ¶
func NewWgs84PolygonOfTypeWithVertices(polygonType PolygonType, vertices []Wgs84) Wgs84Polygon
NewWgs84PolygonOfTypeWithVertices constructs a WGS84 polygon of the given type with the given vertices.
func NewWgs84PolygonWithVertices ¶
func NewWgs84PolygonWithVertices(vertices []Wgs84) Wgs84Polygon
NewWgs84PolygonWithVertices constructs a simple WGS84 polygon with the given vertices.
func (Wgs84Polygon) AaBb ¶
func (p Wgs84Polygon) AaBb() Wgs84AABB
AaBb returns the axis-aligned bounding box of this polygon.
Returns a default (empty) Wgs84AABB if the polygon is invalid (fewer than 3 vertices). The size is computed as raw coordinate differences (not normalized), then handed to the Wgs84AABB constructor, which still applies the excess-height clamp.
func (Wgs84Polygon) CollidesWith ¶
func (p Wgs84Polygon) CollidesWith(other Wgs84Polygon) bool
CollidesWith reports whether this polygon collides with other (via the Separating-Axis Theorem).
The earth-wrapping sentinel collides with everything. Otherwise the SAT axis sets are taken from this polygon's edges (first test) and from other's edges (second test); if no separating axis is found on either, the polygons collide.
func (Wgs84Polygon) Equals ¶
func (p Wgs84Polygon) Equals(other Wgs84Polygon) bool
Equals reports order-sensitive vertex-wise equality via Wgs84 approximate equality.
func (Wgs84Polygon) IsValid ¶
func (p Wgs84Polygon) IsValid() bool
IsValid reports whether this is a valid polygon: at least three vertices. It overrides the embedded Polygon.IsValid (which requires only one vertex).
func (Wgs84Polygon) Median ¶
func (p Wgs84Polygon) Median() Wgs84
Median returns the centroid (mean longitude, mean latitude) of the polygon vertices. The means are accumulated as sum(coord / n) (not sum(coord) / n) to match the C++ reference's floating-point rounding.