Table of Contents

Class S57DatasetProcessor

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

Renders an S-57 ENC base cell by translating it in-memory to an S101Document and reusing the S-101 portrayal pipeline. A maritime ENC is translated into, and portrayed with, S-101; an inland ENC (DSID PRSP = InlandElectronicNavigationalChart) is translated into S-401 and portrayed with the S-401 catalogues (issue #608), provided the host has an S-401 portrayal catalogue (otherwise it falls back to S-101). Either way the product identity stays S-57. Symbology is S-100 (not S-52); coverage is breadth-first.

public sealed class S57DatasetProcessor : IDatasetProcessor, IVectorPortrayalSource, IHeadlessImageRenderer, ILoadedDatasetProjection, IChartDepthCell
Inheritance
S57DatasetProcessor
Implements
Inherited Members

Remarks

Normally created through the S57 registration, or through CreateS57ProcessorWithUpdates(IAssetSource, string, IReadOnlyList<string>) to fold a base cell's in-set update files into the S-57 document before translation. The raw S-57 document is retained so validation can run S-57 pre-translation rules against fields the translation drops.

Constructors

S57DatasetProcessor(IAssetSource, string, PortrayalCatalogueManager, ILuaEngine, FeatureCatalogueManager, IPortrayalInstructionCache?)

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

public S57DatasetProcessor(IAssetSource source, string relativePath, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null)

Parameters

source IAssetSource
relativePath string
catalogueManager PortrayalCatalogueManager
luaEngine ILuaEngine
featureCatalogueManager FeatureCatalogueManager
sharedInstructionCache IPortrayalInstructionCache

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

Initializes a new S57DatasetProcessor by reading the base cell baseRelativePath from source and applying the in-set sequential update files at updateRelativePaths (in ascending update-number order) before translation. Used by exchange-set bulk loading to collapse a cell and its updates into a single up-to-date dataset (S-57 Part 3, dataset updating).

public S57DatasetProcessor(IAssetSource source, string baseRelativePath, IReadOnlyList<string> updateRelativePaths, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null)

Parameters

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

Remarks

Updates are folded into the S57Document before the S-57 → S-101 translation runs; the translator and portrayal pipeline only ever see the fully-updated document.

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

Initializes a new S57DatasetProcessor by reading the S-57 base cell at path and translating it in memory.

public S57DatasetProcessor(string path, PortrayalCatalogueManager catalogueManager, ILuaEngine luaEngine, FeatureCatalogueManager featureCatalogueManager, IPortrayalInstructionCache? sharedInstructionCache = null)

Parameters

path string

Path to the S-57 ISO 8211 base cell (….000).

catalogueManager PortrayalCatalogueManager

Supplies the portrayal catalogue of the translation target (S-101, or S-401 for an inland cell when that catalogue is available).

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

Cross-load cache of the Lua rule output, shared by every processor the host creates (typically a DiskPortrayalInstructionCache), so reopening a cell skips the Part 9A rules. null uses a cache private to this processor.

Exceptions

ArgumentException

path is null or empty.

Properties

CellRankingScale

The cell's scale rank against overlapping cells (see CellScaleRanking): its compilation scale (DSPM CSCL), else the translated DataCoverage minimum display scale, the same rank the display and the route check use. Smaller is finer; null when the cell declares none.

public int? CellRankingScale { get; }

Property Value

int?

Metadata

The lightweight DatasetMetadata for this cell — canonical S-57 specification, WGS-84 extent, and compilation-scale display window — derived from the already-parsed (update-folded) document without a second read, and memoized (issue #460 / #467 WS1). The extent folds the raw spatial coordinates directly rather than going through the S-101 translation, so it is a cheap byproduct.

public DatasetMetadata Metadata { get; }

Property Value

DatasetMetadata

PortrayalSpec

The specification whose catalogues portray this cell: S-101 for a maritime ENC, S-401 for an inland ENC. Unlike the default PortrayalSpec trait (S-101) this depends on the cell, not just on its S-57 identity.

public SpecRef PortrayalSpec { get; }

Property Value

SpecRef

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

Remarks

Always S-57 with no edition, whichever product the cell is translated into; see PortrayalSpec for that.

UpdateReport

What happened to the cell's updates when it was opened with them (S57UpdateApplicator), or null when it was opened without. S-57 Part 3, sequential updating.

public S57UpdateReport? UpdateReport { get; }

Property Value

S57UpdateReport

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 translated DataCoverage (from M_COVR with CATCOV = 1) 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-57 cell to a standalone SKBitmap through the headless, backend-agnostic Skia vector core, bypassing Mapsui. The S-57 dataset is translated to S-101 in-memory (the same pipeline as BuildVectorPortrayalAsync(RenderContext?, CancellationToken)) and the resulting drawing instructions are rasterised by HeadlessVectorRenderer.

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).

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

Same caveats apply as for the S-101 headless path: pattern area-fills are not yet represented in the shared IR, so areas with an area-fill reference are omitted; the dominant solid depth-area colour fills, lines, soundings/symbols, and text are rendered.

SampleNearestSounding(double, double)

Samples the nearest translated Sounding (from SOUNDG) to a WGS-84 location, or null when the cell has none. Delegates to SampleNearest(S101Document, double, double).

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 S-57 validation pipeline against this dataset and returns the aggregated report. Composes two rule packs:

  1. Default against the raw S57Document — catches the few dataset-identity / coverage-metadata issues that do not survive translation.
  2. Default against the translated S101Document via the S101DatasetView façade — every finding produced here is rebadged with the prefix "S101-as-S57/" so downstream consumers can distinguish native S-101 findings from those inherited via translation (docs/design/non-gml-validation.md §9.3, Q-s57-rebadge).

The second pass runs only for a maritime cell translated into S-101. An inland cell is translated into S-401, which has no rule pack (the S-101 pack asserts S-101 normative clauses), so its report carries the pre-translation findings alone. The result is cached on the processor and returned verbatim on subsequent calls.

public ValidationReport? Validate()

Returns

ValidationReport