Table of Contents

Class S101DatasetProcessor

Namespace
EncDotNet.S100.Datasets.Pipelines
Assembly
EncDotNet.S100.Datasets.Pipelines.dll

IDatasetProcessor for IHO S-101 Electronic Navigational Chart cells (S-100 Part 10a ISO 8211 encoding), portrayed through the S-101 Part 9A Lua portrayal catalogue. Also serves S-401 Inland ENC, which shares the encoding and portrayal model, by constructing it with spec: "S-401" so it resolves the S-401 catalogues.

public sealed class S101DatasetProcessor : IDatasetProcessor, IDepthAdjustableProcessor, IVectorPortrayalSource, IHeadlessImageRenderer, ILoadedDatasetProjection, IChartDepthCell, IDateDependentDatasetProcessor
Inheritance
S101DatasetProcessor
Implements
Inherited Members

Remarks

Normally created through the S101 / S401 registrations, or through a DatasetPipelineFactory.CreateS101ProcessorWithUpdates overload to fold a base cell's in-set sequential updates in before portrayal (the outcome is reported by UpdateReport).

Renders are serialized per processor, and the unfiltered Lua rule output is cached by the inputs that change it, so a display-category, viewing-group or display-plane change only re-filters it. A host may inject a shared IPortrayalInstructionCache so a freshly opened processor for a previously portrayed cell can skip the Lua run; otherwise a per-processor in-memory cache is used.

Constructors

S101DatasetProcessor(IAssetSource, string, PortrayalCatalogueManager, ILuaEngine, FeatureCatalogueManager, IPortrayalInstructionCache?, IReadOnlyDictionary<string, string>?, string)

Initializes a new S101DatasetProcessor by reading the ISO 8211 dataset relativePath from source. Used by exchange-set bulk loading.

public S101DatasetProcessor(IAssetSource source, string relativePath, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null, IReadOnlyDictionary<string, string>? supportFiles = null, string spec = "S-101")

Parameters

source IAssetSource
relativePath string
catalogueManager PortrayalCatalogueManager
luaEngine ILuaEngine
featureCatalogueManager FeatureCatalogueManager
sharedInstructionCache IPortrayalInstructionCache
supportFiles IReadOnlyDictionary<string, string>
spec string

S101DatasetProcessor(IAssetSource, string, IReadOnlyList<string>, PortrayalCatalogueManager, ILuaEngine, FeatureCatalogueManager, IPortrayalInstructionCache?, IReadOnlyDictionary<string, string>?, string)

Initializes a new S101DatasetProcessor for a base cell at baseRelativePath with the sequential update files at updateRelativePaths applied (best-effort) before portrayal. Used by exchange-set bulk loading to collapse a cell and its in-set updates into a single up-to-date dataset; the apply outcome is exposed via UpdateReport. S-101 / S-100 Part 10a.

public S101DatasetProcessor(IAssetSource source, string baseRelativePath, IReadOnlyList<string> updateRelativePaths, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null, IReadOnlyDictionary<string, string>? supportFiles = null, string spec = "S-101")

Parameters

source IAssetSource
baseRelativePath string
updateRelativePaths IReadOnlyList<string>
catalogueManager PortrayalCatalogueManager
luaEngine ILuaEngine
featureCatalogueManager FeatureCatalogueManager
sharedInstructionCache IPortrayalInstructionCache
supportFiles IReadOnlyDictionary<string, string>
spec string

S101DatasetProcessor(string, PortrayalCatalogueManager, ILuaEngine, FeatureCatalogueManager, IPortrayalInstructionCache?, string)

Initializes a new S101DatasetProcessor by reading and parsing the ISO 8211 cell at path. External text files the cell references are resolved relative to the cell's folder, including a sibling SUPPORT_FILES folder in an S-100 exchange-set layout.

public S101DatasetProcessor(string path, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null, string spec = "S-101")

Parameters

path string

Path to the ISO 8211 cell file.

catalogueManager PortrayalCatalogueManager

Supplies the portrayal catalogue for spec.

luaEngine ILuaEngine

Lua engine that executes the portrayal catalogue's rules.

featureCatalogueManager FeatureCatalogueManager

Supplies the feature catalogue used to decode feature and attribute names in feature info.

sharedInstructionCache IPortrayalInstructionCache

Optional cross-processor cache of portrayal drawing instructions; null uses a per-processor in-memory cache.

spec string

The product whose catalogues portray the cell: "S-101" (default) or "S-401" for inland ENC.

Exceptions

ArgumentException

spec is null or empty.

Properties

CellRankingScale

The cell's scale rank against overlapping cells (see CellScaleRanking): the most permissive DataCoverage minimum display scale, the same rank the display uses to hide a coarser cell under a finer one. Smaller is finer; null when the cell declares none.

public int? CellRankingScale { get; }

Property Value

int?

Metadata

The lightweight, product-agnostic DatasetMetadata for this dataset — its declared specification and, where cheaply derivable, its geographic extent, horizontal CRS, display-scale window, and temporal coverage. Overriding processors derive it once from the already-parsed dataset (never a second parse) and cache it, so hosts can frame a viewport, register a layer, draw an out-of-scale indicator, or gate visibility without re-reading the dataset. The default implementation does not override this and instead returns a fresh, minimal value carrying only Spec on each access; processors that can supply an extent (and other facts) override it with the derive-once-and-cache behaviour above. See issue #467 / #460.

public DatasetMetadata Metadata { get; }

Property Value

DatasetMetadata

Remarks

Derived once from the already-parsed S101Dataset (folding its spatial records into the extent); no second parse is incurred (issue #467, WS1).

PortrayalTimeIntervals

The distinct time intervals of the last portrayal's drawing instructions; empty when none is date-dependent or nothing has been portrayed yet.

public IReadOnlyList<PortrayalTimeInterval> PortrayalTimeIntervals { get; }

Property Value

IReadOnlyList<PortrayalTimeInterval>

SoundingDatum

The cell's vertical datum: the S-100 code its SoundingDatum areas declare (the most common one when they declare several), or null when the cell declares none.

public int? SoundingDatum { get; }

Property Value

int?

Spec

The product specification (name + edition) this dataset declares conformance to. Each per-spec processor returns a fixed name (e.g. "S-101"); the edition portion is populated from the dataset itself (HDF5 productSpecification attribute, GML application namespace, S-101 ProductSpecificationEdition, etc.) when known, otherwise defaults to SpecVersion default.

public SpecRef Spec { get; }

Property Value

SpecRef

UpdateReport

Outcome of applying sequential updates when this processor was constructed for a base cell plus in-set update files; otherwise null.

public S101UpdateReport? UpdateReport { get; }

Property Value

S101UpdateReport

VersionAssessment

How the dataset's declared product specification edition (Spec) relates to the version of the catalogue used to process it, or null when no catalogue self-describes its version (so no assessment can be made). Computed once at construction — catalogue resolution is a one-shot per processor — and surfaced by hosts (CLI info/render, viewer layer list) to warn on a version mismatch per S-100 Edition 5.2.1 Part 2 §6.

public SpecVersionAssessment? VersionAssessment { get; }

Property Value

SpecVersionAssessment

Methods

BuildVectorPortrayalAsync(RenderContext?, CancellationToken)

Builds an immutable, Mapsui-free snapshot of this dataset's vector portrayal for the supplied render context. Implementations run under the processor's render gate and snapshot all mutable portrayal state (palette, ECDIS display, asset pre-warm) so the result is safe to convert to Mapsui layers off the gate.

public Task<VectorPortrayalResult> BuildVectorPortrayalAsync(RenderContext? context = null, CancellationToken cancellationToken = default)

Parameters

context RenderContext

Optional render context (palette, scales, ECDIS, mariner).

cancellationToken CancellationToken

Cancellation token.

Returns

Task<VectorPortrayalResult>

The Mapsui-free vector portrayal result.

CoversPoint(double, double)

Whether the cell's DataCoverage contains a WGS-84 point. A cell that declares no coverage is treated as covering every point.

public bool CoversPoint(double latitude, double longitude)

Parameters

latitude double

Latitude in decimal degrees (WGS-84).

longitude double

Longitude in decimal degrees (WGS-84).

Returns

bool

true when the cell covers the point.

CreateLoadedData()

Allocates the LoadedDatasetData variant wrapping this processor's already-parsed model. Never re-reads the source bytes.

public LoadedDatasetData CreateLoadedData()

Returns

LoadedDatasetData

The catalog payload wrapping the resident model (e.g. an S125DatasetData or S102CoverageData).

EnumerateFeatures()

Enumerates a lightweight summary of every feature exposed by this processor — used to seed the viewer's feature-search index without forcing a full GetFeatureInfo(string) call per feature.

public IEnumerable<FeatureSummary> EnumerateFeatures()

Returns

IEnumerable<FeatureSummary>

Remarks

Coverage products (S-102, S-104, S-111) and any processor that does not expose discrete features should leave this returning the default empty enumeration.

GetFeatureInfo(string)

Returns information about a feature identified by its reference string (as stored in the rendered feature via the renderer's feature-ref key), or null if the feature cannot be found.

public FeatureInfo? GetFeatureInfo(string featureRef)

Parameters

featureRef string

Returns

FeatureInfo

Remarks

Real-world datasets occasionally contain features that share a gml:id (a producer bug), so callers that already know the feature's position within the dataset should prefer GetFeatureInfoAt(int) for a collision-free lookup.

GetFeatureInfoAt(int)

Returns information about the feature at the given enumeration ordinal — the same index reported via Ordinal from EnumerateFeatures(). Used by the search index so duplicate gml:ids (a real producer bug) still route to the correct feature.

public FeatureInfo? GetFeatureInfoAt(int ordinal)

Parameters

ordinal int

Returns

FeatureInfo

Feature info, or null when the ordinal is out of range or this processor does not expose discrete features.

HitTestFeatures(double, double, double)

Hit-tests this dataset's vector features against a geographic point, returning every feature whose geometry contains the point (area features) or lies within radiusMeters of it (point / curve features), in feature-enumeration order. The reusable geographic complement to GetCoverageInfo(double, double, DateTime?): a caller resolves each hit to full attributes via GetFeatureInfoAt(int) (or GetFeatureInfo(string)) and ranks the results across datasets itself — for example by a rendering paint stack, which the processor contract deliberately knows nothing about.

public IReadOnlyList<FeatureGeometryHit> HitTestFeatures(double latitude, double longitude, double radiusMeters)

Parameters

latitude double

Pick latitude in WGS-84 degrees.

longitude double

Pick longitude in WGS-84 degrees.

radiusMeters double

Search tolerance for point/curve features in metres; area features use exact containment and ignore it. Negative or non-finite values are treated as 0.

Returns

IReadOnlyList<FeatureGeometryHit>

The matching features in enumeration order — each Ordinal aligns with GetFeatureInfoAt(int) — or an empty list. Vector processors override this; coverage / non-vector processors leave the default empty implementation and expose picks through GetCoverageInfo(double, double, DateTime?) instead.

RenderHeadlessAsync(int, int, RenderContext?, RgbaColor?, CancellationToken)

Renders this S-101 cell to a standalone SKBitmap through the headless, backend-agnostic Skia vector core (VectorSceneBuilder → SkiaDisplayListRenderer), bypassing Mapsui entirely. This is the vector analogue of the direct-Skia coverage renderer and the basis for a headless tile-serving API.

public Task<SKBitmap> RenderHeadlessAsync(int widthPixels, int heightPixels, RenderContext? context = null, RgbaColor? background = null, CancellationToken cancellationToken = default)

Parameters

widthPixels int

Output bitmap width in pixels.

heightPixels int

Output bitmap height in pixels.

context RenderContext

Optional render context (palette, symbol/text scale, ECDIS display, mariner settings).

background RgbaColor?

Optional background fill; defaults to opaque white.

cancellationToken CancellationToken

Cancellation token.

Returns

Task<SKBitmap>

A newly allocated bitmap owned by the caller.

Remarks

Tiled-symbol pattern area-fills (e.g. shallow-water diamonds, quality-of-bathymetry overlays) are rasterised through RasterizePatternTile(string, AreaFill, double) and tiled across the polygon, anchored to a global world-space origin so adjacent polygons sharing a pattern align seamlessly. Unlike the Mapsui path, the headless renderer does not perform NetTopologySuite priority-clipping of overlapping patterns or land-occlusion, so patterns may visibly bleed across opaque overlay fills. Use BuildVectorPortrayalAsync(RenderContext?, CancellationToken) (the Mapsui path) for full pattern-fill fidelity. Unlike that path, this produces a single bitmap (no S-102 interleave split) and draw order follows the shared core's S-100 Part 9 ordering.

SampleNearestSounding(double, double)

Samples the nearest charted S-101 Sounding (per-point depth) to a WGS-84 location for depth assimilation, or null when the dataset contains no soundings. Delegates to SampleNearest(S101Document, double, double) (S-101 multipoint spatial records, S-100 Part 10a §10a-6).

public S101SoundingSample? SampleNearestSounding(double latitude, double longitude)

Parameters

latitude double

Latitude in decimal degrees (WGS-84).

longitude double

Longitude in decimal degrees (WGS-84).

Returns

S101SoundingSample?

The nearest sounding sample, or null.

SoundingDatumAt(double, double)

The vertical datum the cell's depths are relative to at a WGS-84 point: the S-100 vertical datum code of the SoundingDatum area that contains it, or null when none does. The route check reads the same areas.

public int? SoundingDatumAt(double latitude, double longitude)

Parameters

latitude double

Latitude in decimal degrees (WGS-84).

longitude double

Longitude in decimal degrees (WGS-84).

Returns

int?

The datum code, or null.

Validate()

Runs the V-4 S-101 validation rule pack (Default) against the parsed document, returning the resulting ValidationReport.

public ValidationReport? Validate()

Returns

ValidationReport

Remarks

Implements the processor integration shape defined by docs/design/non-gml-validation.md §9.3: the document is projected through the spec-vocabulary S101DatasetView façade (design §3.1, option (b)) using the bundled FeatureCatalogueDecoder for FC-conformance rules, then handed to the cached default rule set. The report is cached on first call; subsequent calls return the same instance (design §9.4).

When no S-101 Feature Catalogue is available the façade is built without a decoder; rules requiring catalogue lookup (S101-R-1.2, S101-R-4.1) degrade to no-ops per design §8.1. Reader-level parse failures occur in the constructor and never reach this method; the S101-PROJ-PARSE rule is a documented placeholder for future reader diagnostics (design §5.2 Stance A).