Class PatternPriorityClipper
Backend-neutral priority-clipping of S-100 Part 9 §11.3 tiled pattern area fills. Given the pattern areas grouped by (pattern reference, drawing priority) and the opaque non-patterned colour fills, this computes the visible portion of each pattern group by subtracting every higher-priority pattern area and every opaque colour fill (e.g. land) from it, so that a lower-priority pattern does not show through a higher-priority pattern zone and no pattern bleeds over an opaque area.
public static class PatternPriorityClipper
- Inheritance
-
PatternPriorityClipper
- Inherited Members
Remarks
This is the single, shared implementation used by both render paths:
the Mapsui feature path (MapsuiDisplayListRenderer) invokes it
directly, and the VectorScene IR path
(VectorSceneBuilder, consumed by the headless Skia backend and
the Mapsui TiledScene subsystem) applies it when lowering pattern ops. Both
therefore clip identically.
All geometry is expressed in EPSG:3857 (Web-Mercator) metres, matching the PaintOp unit contract. The algorithm uses NetTopologySuite NetTopologySuite.Operation.OverlayNG.OverlayNGRobust (OverlayNG) for full-precision, robust overlay and generalizes dense areas via NetTopologySuite.Simplify.TopologyPreservingSimplifier (gated by MinPointsToSimplify) to keep the overlay cost bounded on very dense coverage cells. The clip geometry is palette-independent, so results are cacheable keyed on the palette-independent portrayal key.
Fields
MinPointsToSimplify
Minimum vertex count at which SimplifyForClip(Geometry) generalizes a
geometry before the clip overlay. Below this, the NetTopologySuite
Difference/Union cost is already small (profiling: a
~2,600-vertex pattern area clips in ~50 ms) and the simplifier's own
fixed setup cost would be net overhead. The cost the optimization targets is
super-linear and only becomes significant for very dense areas (profiling: a
~64,000-vertex M_QUAL coverage area took ~7.7 s), so gating on vertex
count applies the generalization only where it provides a clear net win and
leaves the common case (small/moderate areas) byte-identical to no
generalization at all.
public const int MinPointsToSimplify = 2000
Field Value
SimplifyToleranceMetres
Tolerance, in EPSG:3857 (Web Mercator) metres, used to generalize pattern and exclusion geometries before clipping. Web Mercator inflates distances by 1/cos(latitude), so this projected tolerance is conservative (smaller in ground metres) away from the equator. The clipped boundary only bounds a tiled raster pattern fill, so this generalization is not visually significant.
public const double SimplifyToleranceMetres = 1
Field Value
Methods
Clip(IReadOnlyList<PatternGroup>, IReadOnlyList<Polygon>)
Clips each pattern group against all higher-priority pattern areas and the supplied non-patterned colour fills.
public static IReadOnlyList<PatternPriorityClipper.ClippedPattern> Clip(IReadOnlyList<PatternPriorityClipper.PatternGroup> entries, IReadOnlyList<Polygon> nonPatternedColorFills)
Parameters
entriesIReadOnlyList<PatternPriorityClipper.PatternGroup>The pattern groups, pre-sorted ascending by priority. The returned list is in the same order as this input.
nonPatternedColorFillsIReadOnlyList<Polygon>Non-patterned colour-fill polygons (e.g. land) that should occlude every pattern fill. The clipper treats each polygon as a full occluder; the caller is responsible for supplying only fills that are actually opaque. May be empty.
Returns
- IReadOnlyList<PatternPriorityClipper.ClippedPattern>
The clipped geometry for each input group, in input order. A group whose area is fully occluded yields an empty geometry.
Remarks
The overlay favours robustness: when an individual Difference
or Union fails (a NetTopologySuite.Geometries.TopologyException or
ArgumentException on degenerate input, or the
AggregateException that NetTopologySuite.Operation.OverlayNG.OverlayNGRobust throws
when all of its fallback strategies fail), the algorithm
falls back to the unclipped geometry for that step rather than failing the
whole clip. This keeps a pattern visible (un-clipped) in preference to
dropping it, matching the historical Mapsui behaviour.
Every overlay result is reduced to its polygonal components before it is used again or returned. OverlayNG's snapping fallback can collapse a sliver of an areal result to a line, yielding a mixed-dimension NetTopologySuite.Geometries.GeometryCollection that a following overlay rejects.
ExtractPolygonal(Geometry)
Reduces an arbitrary geometry to its polygonal components, returning a NetTopologySuite.Geometries.Polygon or NetTopologySuite.Geometries.MultiPolygon (or null when no polygonal component exists). This guards the pattern-clip overlays against the mixed-dimension NetTopologySuite.Geometries.GeometryCollection that topology-preserving simplification can emit, which OverlayNG rejects.
public static Geometry? ExtractPolygonal(Geometry geometry)
Parameters
geometryGeometryThe geometry to reduce; may be any dimension.
Returns
- Geometry
The polygonal-only geometry, or null when the input contains no polygon.
RemoveDuplicateComponents(Geometry)
Drops exact duplicate components (equal vertex sequences) from a collection, keeping the first of each. A duplicate adds nothing to a fill or clip area, and NetTopologySuite.Simplify.TopologyPreservingSimplifier keys rings by value, so it throws on a repeated ring. NOAA ENCs give such areas in 14 of 7,184 cells, among them pattern areas of over 80,000 vertices that would otherwise skip simplification.
public static Geometry RemoveDuplicateComponents(Geometry geometry)
Parameters
geometryGeometryThe geometry to deduplicate.
Returns
- Geometry
geometryitself when it has no duplicates or isn't a collection; otherwise a new collection of the distinct components.
SimplifyForClip(Geometry)
Generalizes a polygonal geometry for use as a clip subject/mask, preserving topological validity so the result is safe for subsequent NetTopologySuite overlay operations. Geometries below MinPointsToSimplify vertices are returned unchanged (the overlay is already inexpensive at that size). Exact duplicate components are dropped first (see RemoveDuplicateComponents(Geometry)). Returns the original geometry if simplification fails or degenerates to empty.
public static Geometry SimplifyForClip(Geometry geometry)
Parameters
geometryGeometryThe geometry to generalize.
Returns
- Geometry
The generalized (or original) geometry.