Class SeamAwareBoundsAccumulator
Accumulates the EPSG:3857 extent of a headless render while remaining aware of the ±180° antimeridian seam, so the auto-fit viewport frames a dataset on its true extent even when its geometry wraps the dateline.
public sealed class SeamAwareBoundsAccumulator
- Inheritance
-
SeamAwareBoundsAccumulator
- Inherited Members
Remarks
A naive min/max over projected world-X collapses for antimeridian- spanning data (e.g. the Alaska NWS S-411 product, ~175°E → ~225°E): one cluster near +179° and another near −179° make the X-span ≈ the full world width, so the fitted viewport becomes near-global and every feature draws sub-pixel (issue #413).
To detect the seam robustly the accumulator maintains a coarse
longitude occupancy histogram (BinCount bins over
[−180°, 180°)), tracking the exact observed [minX, maxX] per bin. On
TryResolve(out double, out double, out double, out double) it locates the largest empty longitude arc
(the emptiest gap): if that gap is an interior band — rather than the arc
that already wraps the seam — the data straddles ±180°, so the western
cluster is shifted by one Circumference to produce
a contiguous world-X window whose maxX may exceed +½ circumference.
The paired WorldToScreen wrap re-homes the shifted ops at draw
time.
The seam logic only engages when the naive longitude span exceeds 180°; narrower extents (the overwhelming majority) take the fast path and behave exactly as the previous naive min/max fit. Genuinely wide / global datasets — whose emptiest gap is the seam-wrapping arc, not an interior band — also keep the naive extent, so the heuristic does not false-positive.
Constructors
SeamAwareBoundsAccumulator()
Creates an empty accumulator.
public SeamAwareBoundsAccumulator()
Fields
BinCount
Number of longitude occupancy bins (0.5° each).
public const int BinCount = 720
Field Value
Properties
HasGeometry
Whether any geometry has been accumulated.
public bool HasGeometry { get; }
Property Value
Methods
Add(double, double)
Accumulates a single EPSG:3857 world coordinate (metres).
public void Add(double x, double y)
Parameters
AddLonLatBox(double, double, double, double)
Accumulates a WGS-84 lon/lat bounding box (degrees), projecting its
corners to EPSG:3857 and marking every longitude bin it covers as
occupied so a wide extent (e.g. a coverage grid) does not introduce a
spurious interior gap. Boxes whose west exceeds
east are treated as crossing the ±180° seam, as are
boxes that run past +180° (a grid stored in 0°–360° longitudes) or
before −180°.
public void AddLonLatBox(double west, double east, double south, double north)
Parameters
westdoubleWestern longitude edge, degrees.
eastdoubleEastern longitude edge, degrees.
southdoubleSouthern latitude edge, degrees.
northdoubleNorthern latitude edge, degrees.
Remarks
The occupancy bins are 0.5° wide, but the X extent recorded in each bin is clipped to the box's own edges, so a sub-degree coverage resolves to its true extent rather than to the enclosing bin edges (issue #1097).
AddScene(VectorScene)
Accumulates every vertex of a resolved VectorScene — point and text anchors, polyline vertices, and area shell + hole rings.
public void AddScene(VectorScene scene)
Parameters
sceneVectorSceneThe lowered scene whose paint ops to bound.
TryResolve(out double, out double, out double, out double)
Resolves the accumulated geometry to a seam-aware EPSG:3857 window.
public bool TryResolve(out double minX, out double minY, out double maxX, out double maxY)
Parameters
minXdoubleResolved minimum easting, metres.
minYdoubleResolved minimum northing, metres.
maxXdoubleResolved maximum easting, metres. May exceed +½ Circumference when the extent was shifted across the antimeridian; the paired WorldToScreen wrap re-homes ops into this window at draw time.
maxYdoubleResolved maximum northing, metres.