EncDotNet.S100.Core
0.27.0
See the version list below for details.
dotnet add package EncDotNet.S100.Core --version 0.27.0
NuGet\Install-Package EncDotNet.S100.Core -Version 0.27.0
<PackageReference Include="EncDotNet.S100.Core" Version="0.27.0" />
<PackageVersion Include="EncDotNet.S100.Core" Version="0.27.0" />
<PackageReference Include="EncDotNet.S100.Core" />
paket add EncDotNet.S100.Core --version 0.27.0
#r "nuget: EncDotNet.S100.Core, 0.27.0"
#:package EncDotNet.S100.Core@0.27.0
#addin nuget:?package=EncDotNet.S100.Core&version=0.27.0
#tool nuget:?package=EncDotNet.S100.Core&version=0.27.0
EncDotNet.S100.Core
EncDotNet.S100.Core holds the abstractions and pipeline framework that the
other EncDotNet.S100 packages share: asset sources, HDF5 and Lua interfaces,
the coverage and vector portrayal pipelines, the validation framework, dataset
metadata, spec-version checks and dynamic feature sources. Reference it
directly when you write a product reader, an HDF5 or Lua backend, a validation
rule pack or a rendering host. If you only want to open and render datasets,
use the EncDotNet.S100 facade, which brings
this package in.
Install
dotnet add package EncDotNet.S100.Core
Example: read a file from a folder or ZIP
Readers get their files through IAssetSource, so the same code reads from a
folder or a ZIP archive:
using EncDotNet.S100.Core;
using IAssetSource source = FileSystemAssetSource.Create("path/to/exchange-set");
// or: using IAssetSource source = ZipAssetSource.Create("path/to/exchange-set.zip");
await using Stream catalogue = await source.OpenAsync("CATALOG.XML");
Main entry points
Asset sources
IAssetSource (namespace EncDotNet.S100.Core) reads files by relative path.
FileSystemAssetSource reads from a folder, ZipAssetSource from a ZIP
archive, and CachingAssetSource caches reads from another source.
HDF5
IHdf5File and IHdf5Group (namespace EncDotNet.S100.Hdf5) read HDF5 data
without binding to a specific HDF5 library.
EncDotNet.S100.Hdf5.PureHdf
implements them.
HDF5 readers throw two exception types:
S100DatasetSchemaException: a required attribute or group is missing or malformed.S100DatasetNotSupportedException: the file uses an optional part of the specification that the reader doesn't implement yet.
Both carry the product, file, group path and specification reference, and a
WithFile(...) helper that processors use to attach the source file name.
S100DatasetSchemaException also carries an optional AdditionalContext, set
with WithAdditionalContext(...) and kept across WithFile(...). Readers use
it to add an explanation, such as a note that the dataset declares an
unexpected product-specification edition.
Hdf5RequiredAttributeExtensions provides ReadRequiredDoubleAttribute,
ReadRequiredInt64Attribute and ReadRequiredStringAttribute. They turn a
backend's "missing attribute" failure into these typed exceptions.
Lua scripting
ILuaEngine and ILuaContext (namespace EncDotNet.S100.Scripting) run
sandboxed Lua portrayal scripts. S100LuaHost is the host API the scripts
call.
EncDotNet.S100.Scripting.LuaCSharp
(the default) and
EncDotNet.S100.Scripting.MoonSharp
implement the engine. LuaEngineKind names them, and LuaEngineKinds parses
a name such as luacsharp and reads the S100_LUA_ENGINE override.
Coverage pipeline
ICoverageSource, ICoverageRenderer<T> and CoveragePipeline (namespace
EncDotNet.S100.Pipelines.Coverage) render gridded data, with
GridGeoreferencer, CoverageColorScheme and StyledCoverageLayer.
ICoverageStyle.ResolveColorSchemereturnsCoverageColorScheme?. Catalogues that only emit symbols, such as S-111's arrow-only portrayal, returnnull. The coverage renderers throw if you pass them a layer with anullscheme.CoveragePipeline.ProcessAsynctakes an optionalViewport. When you pass one, it usesGridRegion.FromViewportto sample only the cells inside the viewport, at the viewport's ground resolution. It clamps the subset to the intersection of the viewport and the grid extent, and picks a stride so the ground resolution isn't finer than the cell size. Without a viewport it samples the full grid.- For a grid in a CRS other than EPSG:4326, also pass
wgs84ToNative, anICrsTransformfrom WGS 84 to the grid's CRS. - The georeferencer on the resulting
StyledCoverageLayeris built from the sampled subset'sGridMetadata: its origin is adjusted for the subset and its spacing scaled by the stride. A sampled subset is drawn at its true location. - Viewport sampling happens when the pipeline builds the layer.
ICoverageSourcecan also serve an overview pyramid (S-100 Part 10c):AvailableOverviewLevelslists the levels andSelectOverviewLevelpicks one.CoveragePyramidandCoveragePyramidBuilder(namespaceEncDotNet.S100.Pipelines.Coverage.Pyramid) build one in memory.
Vector pipeline
IVectorSource, IVectorPortrayalCatalogue and VectorPipeline (namespace
EncDotNet.S100.Pipelines.Vector) run vector portrayal. The output is the
DrawingInstruction hierarchy (AreaInstruction, LineInstruction,
PointInstruction, TextInstruction), modelled on the S-100 Part 9 display
list.
- Rule execution is pluggable behind
IVectorRuleExecutor. There are two implementations:Pipelines.Vector.Xslt.XsltRuleExecutor(S-100 Part 9 §9.4) gets the FeatureXML, selects rules, runs the XSLT transformation and assembles the display list.Pipelines.Vector.Lua.LuaRuleExecutor(S-100 Part 9A) is one product-independent executor. Products supply their own parts throughILuaDataProviderandILuaDataProviderFactory(the host bridge),LuaContextParameterBinding(mariner settings to context parameters),IFeatureAnchorProviderandIDrawingInstructionTransform. S-101 and S-131 share the executor this way.
VectorPipelineruns the built-in XSLT executor, appends the output of an optional injected Lua executor, then filters by viewing group and display plane and sorts by priority. It contains no XSLT-specific code.DrawingInstructionParserparses Lua-emitted drawing instructions.Part9DisplayListReaderparses the Part 9 display-list XML produced by the XSLT pipelines (S-124, S-129, S-421) into the sameDrawingInstructionhierarchy that S-101's Lua pipeline emits, so one renderer handles both.
Portrayal-instruction caching
IPortrayalInstructionCache (namespace
EncDotNet.S100.Pipelines.Vector.Caching) caches the DrawingInstruction list
that the vector pipeline produces. When you reopen a dataset you've portrayed
before, a cache hit skips the portrayal run, which for S-101 is a Lua run
taking several seconds.
GetOrCompute(key, factory)returns the cached list or computes it.InMemoryPortrayalInstructionCacheis a bounded LRU cache that holds list references.DiskPortrayalInstructionCachewrites each list to a.dlistfile withDrawingInstructionSerializer, in a kind of aContentStore(see Content store). A miss queues the write as a background job, and reads see it before it lands. A corrupt file or aFormatVersionmismatch counts as a miss, so a stale or partial file never breaks a render.- You supply a key that captures every portrayal input.
S101DatasetProcessorhashes the dataset bytes, the feature and portrayal catalogue content (including overrides and Lua rules) and the engine assembly versions. - The cache stores the pipeline's final output, so a hit returns exactly the list a fresh run would produce.
Dataset metadata
DatasetMetadata (namespace EncDotNet.S100.Core) is what every dataset
reader returns from its ReadMetadata path: the facts a host can get without a
full parse and portrayal.
- It has
Spec(SpecRef),Extent(BoundingBox?),HorizontalCrsEpsg(int?),DisplayScale(DisplayScaleRange?) andTimeCoverage(TimeCoverage?). - Only
Specis always set. Anulloptional value means it isn't available cheaply; load the dataset fully to get it. - A host can use it to load a folder of datasets with no catalogue in phases: read every dataset's metadata, frame the viewport from the union of their extents, and load each dataset fully when it comes into view.
Gml.GmlDatasetMetadata.Create(specName, declaredEdition, features)folds feature geometry into an extent for the GML products.
The EncDotNet.S100.Core.Metadata namespace caches metadata between sessions:
DatasetMetadataSerializerwrites aDatasetMetadatato a small versioned binary blob. A corrupt blob or aFormatVersionmismatch counts as a miss.IDatasetMetadataCacheandDiskDatasetMetadataCachestore one.dmetafile per dataset, keyed by the source file's last-write time and length. Any mismatch, or an unwritable or corrupt entry, is a miss and never breaks loading. Writes are atomic and the content store's budget bounds the cache, as for the portrayal-instruction cache.
Content store
ContentStore (EncDotNet.S100.Core.Caching) is one disk store for every
cached asset kind: tiles, portrayal display lists, pattern clips, dataset
metadata and the like.
- A folder per kind, a file per key.
Open(name, shareBytes, options)opens a kind under the store's root. A kind with aFormatVersionkeeps its files in av<n>folder and deletes the folders of other versions in the background, so a format change ignores every older entry at once. - One budget. Each kind has a share of the store's budget, and the budget is their sum. A kind may grow past its share while the store is within budget. Over budget, the kinds furthest over their share give back their least recently used entries, down to 95% of the budget.
- A running size index. Each kind's folder is scanned once; after that, reads and writes keep an in-memory index of sizes and recency, so a write never lists the folder. It's rescanned when an eviction finds a file already gone, and at most every ten minutes.
- IO.
Writewrites through a temporary file and an atomic move.QueueWriteruns the write (and, given a producer, the encoding) as a background job on the work scheduler; until it lands,ReadandContainssee the queued bytes.ReadAsyncawaits the file read, so a scheduler job gives its worker back while it waits. - Empty markers. A zero-byte entry means the producer had nothing to store;
it reads back as
ContentState.Emptywithout anything to decode.
Validation
The EncDotNet.S100.Validation namespace has the product-independent types
for checking normative clauses against the typed data models:
IValidationRule<TModel>is one rule.ValidationRuleSet<TModel>runs a set of rules, collects every finding, and catches exceptions from individual rules.ValidationFindinghas the rule id, severity, message, an optionalGeoPositionorBoundingBox, and a related feature id.ValidationSeverityandValidationReport.ValidationContextcarriesReferenceTimeand an optionalIServiceProviderfor rules that look across datasets.ValidationRuleBuilderbuilds rules fluently:RuleFor<T>("rule-id").Check(predicate, message).Build(), or.Yield(producer)for rules that return several findings.
Each product's rule pack lives in the Validation/ folder of its
EncDotNet.S100.Datasets.Sxxx project.
- S-101, S-102, S-104, S-111, S-122, S-124, S-125, S-127, S-128, S-129, S-131, S-201, S-411 and S-421 ship a rule pack. S-57 delegates to the S-101 pack.
- S-401 (IEHG Inland ENC) is read and portrayed but has no rule pack. The S-101
pack checks S-101 clauses and doesn't run against inland data, so
Validate()reports that no rules are available. - Rule packs for vector products read from a façade that follows the
specification, not from the raw reader types. For S-101 that's
S101DatasetView,S101FeatureViewandS101AttributeView. Rule code then doesn't change if a typed data model replaces the reader types later. - Coverage records have a
GroupPath(BathymetryCoverage.GroupPathin S-102,WaterLevelCoverage.GroupPathin S-104). Rule packs use it as theValidationFinding.RelatedFeatureIdfor each coverage.
Custom catalogues and validation shows how to run the bundled rules and write your own.
Spec-version assessment
SpecRef, CatalogueRef and SpecVersion identify product specifications
and catalogues. SpecCompatibility.Classify(declared, implemented) compares
two editions (S-100 Edition 5.2.1 Part 2 §6).
SpecVersionAssessment compares a dataset's declared product-specification
edition with the editions the application supports.
- It doesn't compare against the feature or portrayal catalogue version. A catalogue declares only its own version, not the product-specification edition it targets, so that comparison would give false warnings.
IsWarningistrueonly when the application supports an older edition on the same major version, or no edition on the declared major version.BuildMessage()returns the note to show the user.Gml.GmlDatasetIdentification.ReadDeclaredEdition(root)reads the declared edition from a GML dataset'sDatasetIdentificationInformation/productEdition(S-100 GML 5.0 or the legacy 1.0 profile).
Geodesy
Wgs84Geodesy (namespace EncDotNet.S100.Geodesy) measures distances and
bearings, solves the direct problem, and places points along geodesics and
rhumb lines on the WGS-84 ellipsoid. GeodesicHelper uses it to draw the
arcs and rays of augmented line geometry (S-100 Part 9A §11.5).
Both are built on GeographicLib.NET, a C# port of Charles Karney's GeographicLib (MIT; see THIRD-PARTY-NOTICES.md).
Shared types
IPortrayalCatalogue,ICrsTransform,ICrsTransformFactory,Viewport,BoundingBox,RgbaColorandColorPalette(namespaceEncDotNet.S100.Pipelines).MarinerSettings: the S-100 Part 9 §4.2 mariner selections, including the four depth contours and S-101 portrayal options such asFourShades,SimplifiedSymbols,RadarOverlayandNationalLanguage.DepthUnitandDepthFormatting: culture-invariant conversion, formatting and parsing of depths in metres, feet, fathoms, and fathoms and feet.EncDotNet.S100.Crs.ProjNetimplementsICrsTransformFactory.
Data-coverage geometry
DataModel.CoverageArea is the data-coverage footprint of a vector cell, in
EPSG:4326 latitude and longitude (S-100 Part 10b §6.2). It has an
ExteriorRing and optional InteriorRings (holes with no coverage). The S-101
and S-57 processors build it from DataCoverage surfaces with
categoryOfCoverage = 1. A host uses it to hide a coarser cell where a finer,
overlapping cell in the display band has coverage.
Dynamic feature sources
The EncDotNet.S100.DynamicSources namespace describes features that change
over time and are pushed to the host, such as own ship, AIS targets, route
previews and sensor overlays. They're drawn alongside static datasets. The
types don't depend on any graphics library.
IDynamicFeatureSourceprovides a snapshot of features and aChangedevent.DynamicFeatureuses the same geometry vocabulary as the static vector pipeline: theGeometryTypeenum and(Latitude, Longitude)tuples.DynamicMotionadds motion to a moving point feature.DynamicVesselGeometryadds vessel dimensions: length, beam, and the CCRP and GPS-antenna offsets (IEC 62388). It matches the AIS type 5dimA/dimB/dimC/dimDfields.DynamicSourceMetadatacarriesDisplayNameandRendererKey.EncDotNet.S100.Renderers.Mapsuiuses the key to find the renderer. ItsPlane(defaultDynamicArrows) andWithinPlanePrioritysay which S-98 plane the source belongs to, for a host's layer stack.IDynamicFeatureDescriberis an optional capability: a source that implements it describes a feature for a pick report as a title and labelled values with units (DynamicFeatureDescription).DynamicFeatureGeometryProvideris anIFeatureGeometryProviderover dynamic features, so drawing instructions built for them (feature reference = id) go through the vector renderers.DynamicFeaturesChangedandDynamicSourceChangeKinddescribe a change.DynamicFeatureTracker<TInbound>helps adapters that age features out, such as AIS sleep and lost timers or stale-sensor styling.
Dynamic feature sources explains the design.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- GeographicLib.NET (>= 2.3.2)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
NuGet packages (35)
Showing the top 5 NuGet packages that depend on EncDotNet.S100.Core:
| Package | Downloads |
|---|---|
|
EncDotNet.S100.Portrayals
Libraries for manipulating S-100 based nautical charts. |
|
|
EncDotNet.S100.Features
Libraries for manipulating S-100 based nautical charts. |
|
|
EncDotNet.S100.Datasets.S101
Libraries for manipulating S-100 based nautical charts. |
|
|
EncDotNet.S100.Renderers.Skia
Headless SkiaSharp rasteriser for the IHO S-100 portrayal pipeline. Renders the backend-neutral scene IR from EncDotNet.S100.Rendering.Scene (VectorScene / PaintOp) to an image with no GUI or map framework: SkiaDisplayListRenderer.RenderOnto, HeadlessVectorRenderer, CoverageHeadlessRenderer, and the multi-layer HeadlessCompositeRenderer. Lets a consumer embed just the renderer + IR without the EncDotNet.S100 facade or Mapsui. |
|
|
EncDotNet.S100.ExchangeSets
Libraries for manipulating S-100 based nautical charts. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.28.0 | 0 | 11/14/2026 |
| 0.27.0 | 418 | 11/9/2026 |
| 0.26.0 | 666 | 10/24/2026 |
| 0.25.1 | 550 | 10/12/2026 |
| 0.25.0 | 535 | 10/12/2026 |
| 0.24.0 | 590 | 10/4/2026 |
| 0.23.0 | 570 | 9/17/2026 |
| 0.22.0 | 663 | 7/19/2026 |
| 0.21.0 | 672 | 7/10/2026 |
| 0.20.0 | 658 | 6/29/2026 |
| 0.19.0 | 664 | 6/27/2026 |
| 0.18.0 | 641 | 6/17/2026 |
| 0.17.1 | 636 | 6/16/2026 |
| 0.17.0 | 621 | 6/15/2026 |
| 0.16.0 | 631 | 6/8/2026 |
| 0.15.0 | 332 | 6/6/2026 |
| 0.14.0 | 328 | 6/6/2026 |
| 0.13.0 | 319 | 6/3/2026 |
| 0.12.0 | 324 | 5/29/2026 |
| 0.11.0 | 326 | 5/19/2026 |