Table of Contents

Struct WorldToScreen

Namespace
EncDotNet.S100.Rendering.Scene
Assembly
EncDotNet.S100.Rendering.Scene.dll

A linear EPSG:3857-world → screen-pixel affine derived from a Viewport — the second half of the S-100 Part 9 projection (EPSG:3857 → screen pixels) that a PaintOp deliberately leaves to each rendering backend (see the unit contract on PaintOp).

public readonly struct WorldToScreen
Inherited Members

Remarks

The viewport's geographic bounds are projected to EPSG:3857 via FromLonLat(double, double) and mapped linearly to the pixel rectangle with origin top-left and screen-space +Y pointing down (northing decreases downward). The transform is north-up only — it applies no rotation.

This helper is intentionally framework-neutral (it depends only on Viewport and WebMercator), so a rendering backend that does not use SkiaSharp or Mapsui can project the world coordinates carried on each PaintOp to output pixels without taking a dependency on either backend. It provides only the geometry (world → pixel) projection; size values on the IR are already in display pixels and must not be passed through this transform.

Methods

Create(Viewport)

Builds the world → screen affine for the supplied viewport. The viewport's geographic corners are projected to EPSG:3857 and mapped to the [0, WidthPixels] × [0, HeightPixels] pixel rectangle. A viewport with a zero-width or zero-height projected span yields a zero scale on that axis (all coordinates collapse to the axis origin).

public static WorldToScreen Create(Viewport viewport)

Parameters

viewport Viewport

The display viewport (geographic bounds + pixel size).

Returns

WorldToScreen

The world → screen affine.

Remarks

When the viewport is expressed in a longitude frame shifted across the ±180° antimeridian (MaxLongitude > 180 or MinLongitude < −180, as produced by the seam-aware auto-fit — see SeamAwareBoundsAccumulator), each op's world-X is wrapped into [minX, minX + Circumference) before projection so geometry on the far side of the seam registers in the shifted window. For every normal viewport (which never exceeds ±180°) wrapping is disabled, so partially off-screen features are never teleported. Wrapping is also disabled for a viewport spanning a full world or more of longitude, where every op already lies inside the window unwrapped.

Create(Viewport, bool)

As Create(Viewport), but with control over whether the antimeridian seam-wrap is applied. When allowSeamWrap is false, world-X is never wrapped into the viewport's longitude window even if the viewport is shifted across ±180°. The tiled renderer passes false because it draws already-continuous geometry from narrow per-tile viewports, where wrapping would smear polygons that extend beyond a single tile (see the flag's remarks on the tiled renderer).

public static WorldToScreen Create(Viewport viewport, bool allowSeamWrap)

Parameters

viewport Viewport

The display viewport (geographic bounds + pixel size).

allowSeamWrap bool

true to wrap world-X into a viewport shifted across the ±180° seam (headless auto-fit); false to disable wrapping (tiled continuous-X rasterisation).

Returns

WorldToScreen

The world → screen affine.

Project((double X, double Y))

Projects an EPSG:3857 world coordinate to a screen pixel (origin top-left, +Y down).

public (float X, float Y) Project((double X, double Y) world)

Parameters

world (double X, double Y)

The world coordinate in EPSG:3857 metres.

Returns

(float X, float Y)

The screen pixel coordinate.