Class S57DatasetProcessor
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
sourceIAssetSourcerelativePathstringcatalogueManagerPortrayalCatalogueManagerluaEngineILuaEnginefeatureCatalogueManagerFeatureCatalogueManagersharedInstructionCacheIPortrayalInstructionCache
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
sourceIAssetSourcebaseRelativePathstringupdateRelativePathsIReadOnlyList<string>catalogueManagerPortrayalCatalogueManagerluaEngineILuaEnginefeatureCatalogueManagerFeatureCatalogueManagersharedInstructionCacheIPortrayalInstructionCache
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
pathstringPath to the S-57 ISO 8211 base cell (
….000).catalogueManagerPortrayalCatalogueManagerSupplies the portrayal catalogue of the translation target (S-101, or S-401 for an inland cell when that catalogue is available).
luaEngineILuaEngineLua engine that executes the portrayal catalogue's rules.
featureCatalogueManagerFeatureCatalogueManagerSupplies the feature catalogue used to decode feature and attribute names in feature info.
sharedInstructionCacheIPortrayalInstructionCacheCross-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
pathis 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
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
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
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
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
contextRenderContextOptional render context (palette, scales, ECDIS, mariner).
cancellationTokenCancellationTokenCancellation 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
latitudedoubleLatitude in decimal degrees (WGS-84).
longitudedoubleLongitude in decimal degrees (WGS-84).
Returns
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
S125DatasetDataorS102CoverageData).
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
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
featureRefstring
Returns
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
ordinalint
Returns
- FeatureInfo
Feature info, or
nullwhen 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
latitudedoublePick latitude in WGS-84 degrees.
longitudedoublePick longitude in WGS-84 degrees.
radiusMetersdoubleSearch 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
widthPixelsintOutput bitmap width in pixels.
heightPixelsintOutput bitmap height in pixels.
contextRenderContextOptional render context (palette, symbol/text scale).
backgroundRgbaColor?Optional background fill; defaults to opaque white.
cancellationTokenCancellationTokenCancellation token.
Returns
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
latitudedoubleLatitude in decimal degrees (WGS-84).
longitudedoubleLongitude 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
latitudedoubleLatitude in decimal degrees (WGS-84).
longitudedoubleLongitude in decimal degrees (WGS-84).
Returns
Validate()
Runs the S-57 validation pipeline against this dataset and returns the aggregated report. Composes two rule packs:
- Default against the raw S57Document — catches the few dataset-identity / coverage-metadata issues that do not survive translation.
-
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()