EncDotNet.S100.Datasets.S128
0.24.0
See the version list below for details.
dotnet add package EncDotNet.S100.Datasets.S128 --version 0.24.0
NuGet\Install-Package EncDotNet.S100.Datasets.S128 -Version 0.24.0
<PackageReference Include="EncDotNet.S100.Datasets.S128" Version="0.24.0" />
<PackageVersion Include="EncDotNet.S100.Datasets.S128" Version="0.24.0" />
<PackageReference Include="EncDotNet.S100.Datasets.S128" />
paket add EncDotNet.S100.Datasets.S128 --version 0.24.0
#r "nuget: EncDotNet.S100.Datasets.S128, 0.24.0"
#:package EncDotNet.S100.Datasets.S128@0.24.0
#addin nuget:?package=EncDotNet.S100.Datasets.S128&version=0.24.0
#tool nuget:?package=EncDotNet.S100.Datasets.S128&version=0.24.0
EncDotNet.S100.Datasets.S128
Reader and portrayal-pipeline integration for IHO S-128 (Catalogue of Nautical Products) datasets, encoded as GML per S-100 Part 10b.
Upstream source
| Property | Value |
|---|---|
| Edition | 2.0.0 |
| Application namespace | http://www.iho.int/S128/2.0 |
| Upstream repo | iho-ohi/S-128-Product-Specification-Development |
| Pinned commit | c266c43820ceadcf5b71ceb2a084c279c3a51801 |
| Bundled assets | FC + entire PC tree (byte-identical to upstream) |
The bundled FC and PC live under
src/EncDotNet.S100.Specifications/content/S128/{fc,pc}/ and are surfaced
through the standard Specification.OpenFeatureCatalogueAsync() /
Specification.CreatePortrayalCatalogueSource() factory methods.
What S-128 encodes
An S-128 dataset is a catalogue of the nautical products produced by a single agency. Each "feature" describes one product and its coverage:
| Feature class | Encodes |
|---|---|
ElectronicProduct |
ENCs (S-101), digital cells, online services |
PhysicalProduct |
Paper charts and printed publications |
S100Service |
HDF5-based services such as S-104 / S-111 |
Plus metadata records modelled in the FC as information types but
encoded as features inside the inline <S128:members> container in the
upstream sample (DistributorInformation, ProducerInformation,
ContactDetails, CatalogueSectionHeader).
Public surface
| Type | Purpose |
|---|---|
S128Dataset |
Root data model: Features, InformationTypes, lazy Entries projection. ReadMetadata() / static ReadMetadata(path) / ReadMetadata(stream) is the phased-loading "peek" path (issue #460): declared spec + raw WGS-84 extent from feature geometry (null when geometry-less), skipping XSLT portrayal |
S128DatasetReader |
GML parser. Use S128Dataset.Open(path) for the typical case |
S128Feature, S128InformationType |
FC-faithful feature/information instances |
S128ProductEntry |
Façade over an S128Feature whose type is one of the navigational product classes; surfaces strongly-typed accessors (ProductSpecificationName, Status, CoverageRing, etc.) |
S128ProductStatus |
Heuristic enum: InForce | Superseded | Withdrawn | Planned | Unknown |
S128CatalogueQuery |
Static helpers: FilterByExtent, FilterByProductType, FilterBySpecification, FilterByStatus |
S128ProductCatalogue (DataModel/) |
Strongly-typed projection of the dataset as a catalogue of typed S128CatalogueEntry subclasses with resolved Supersedes/SupersededBy navigation. See Strongly-typed data model. |
S128CatalogueRules (Validation/) |
Default pilot rule pack for S128ProductCatalogue (rule IDs S128-R-12.* traced to S-128 § 12). See Validation. |
S128FeatureXmlSource |
Projects the dataset into the S-100 Part 9 FeatureXML neutral form consumed by the bundled XSLT |
S128PortrayalCatalogue |
IVectorPortrayalCatalogue over the bundled PC (Day / Dusk / Night palettes), with the outline-only adapter on the main rule (see Outline-only coverages) |
Outline-only coverages
The bundled portrayal catalogue is the IHO upstream's, unedited. Its rules
fill each product's coverage with CHYLW / CHGRN / CHMGD at
transparency 0.30 (70 % opaque) on displayPlane OVERRADAR, and the
S-98 layer stack puts S-128 on OtherChartOverlays, above the ENC's line
work. Nested products (a harbour cell inside an approach cell) compound to
about 91 % opaque and hide the chart, against S-98 Main §9.2.1.
Upstream has since reached the same view: issue
#51
recommends outlines only, and the Lua port of the catalogue
(#56)
comments the fills out. S128PortrayalCatalogue does the same with an
adapter, Adapter/outlineOnly.xsl. It xsl:imports the upstream
main.xsl and, for ElectronicProduct, PhysicalProduct and
S100Service surfaces, keeps everything the upstream rule emits except its
areaInstruction. Coverages draw as the upstream dashed outlines.
S128CoverageOverlayTests checks that the adapter output equals the
upstream output minus the fills, and that the upstream rule still emits
them. When a catalogue refresh drops the fills, that test fails and the
adapter can be removed. Moving to the upstream Lua catalogue is tracked in
#763.
Producer-bug compensations
The reader inherits the four mitigations applied to other GML-encoded products in this codebase (S-122 in particular). When real-world S-128 samples surface, edge cases here may need expanding.
s100gmlnamespace tolerance. Acceptshttp://www.iho.int/s100gml/5.0(canonical for 2.0.0),http://www.iho.int/s100gml/1.0, and the legacy profile namespacehttp://www.iho.int/S100/profile/s100gml/1.0.<member>and<members>containers. Both the wrapper and inline variants are accepted; the upstream 2.0.0 sample uses inline<S128:members>.- Comma-and-whitespace tokenisation in
gml:posList/gml:pos. Handleslon,lat lon,lattokens smuggled in via thegml:coordinatesconvention. - lon-lat axis-order swap heuristic. When a
<gml:Envelope>is present and parsed coords clearly fall outside as-is but inside when swapped, the reader globally flips axes. Skipped silently when no envelope is declared (the upstream 2.0.0 sample omits it). gml:gmlIdidentifier fallback. Some S-128 GML 1.0 IC-ENC/DK catalogue datasets key features with the non-standardgml:gmlIdattribute instead ofgml:id. The reader accepts either; without this the feature identifier is empty and the geometry provider drops the feature (rendering blank — see issue #243).- Exterior-less polygons. Some GML 1.0 datasets emit
<gml:Polygon><gml:posList>…directly, omitting the<gml:exterior>/<gml:LinearRing>wrapper. The sharedGmlCoordinateParserfalls back to a directposList/possequence under the surface as the exterior ring. - Single-ordinate
<gml:pos>rings. Some GML 1.0 datasets split each coordinate's ordinates across consecutive single-value<gml:pos>elements (<gml:pos>41.68</gml:pos><gml:pos>21.61</gml:pos>…). The sharedGmlCoordinateParserdetects this and flattens the ordinates into (lat, lon) pairs.
Note on GML 1.0 datasets. Compensations 5–7 recover geometry from the older S-128 GML 1.0 encoding so those catalogues are no longer blank. Full portrayal of GML 1.0 feature classes (
ElectronicChart,PaperChart, …) and a reliable axis order for lon-lat datasets that ship no<gml:Envelope>are tracked separately in issue #247.
Status heuristic
S-128 2.0.0 does not surface a single status enum on product entries.
S128ProductEntry.Status is derived as follows:
- If
serviceStatusis present →Planned (1),InForce (2),Withdrawn (3). - Else if
distributionStatusis present →InForce (1)/Withdrawn (2). - Otherwise defaults to
InForce.
Resolution of theReference xlink references with
ProductMapping/categoryOfProductMapping=1 (supersedes) is handled by
the typed-model projection — see
Strongly-typed data model.
Strongly-typed data model
EncDotNet.S100.Datasets.S128.DataModel.S128ProductCatalogue projects
the feature-bag S128Dataset into a strongly-typed catalogue with:
- Polymorphic
Productscollection over the commonS128CatalogueEntrybase; instances are sealedS128ElectronicProduct,S128PhysicalProduct, orS128Service. - Dedicated typed records for
Producers,Distributors,Contacts, andSectionHeadersmetadata. - Resolved supersedes navigation. Every
theReferencexlink withProductMapping/categoryOfProductMapping=1("Higher Priority Alternative", S-128 § 12) is resolved at projection time. Each entry exposesSupersedes(forward traversal) andSupersededBy(reverse traversal, populated by inverting the forward map). Cycles and chains tolerated. - Other
categoryOfProductMappingvalues surface inRelatedProductswith their raw category text preserved for future-edition compatibility. - Permissive projection: unresolved xlinks and parse failures emit
ProjectionDiagnosticentries rather than throwing. The projection only throws when bothFeaturesandInformationTypesare empty.
Quick start (typed model)
using EncDotNet.S100.Datasets.S128;
using EncDotNet.S100.Datasets.S128.DataModel;
var dataset = S128Dataset.Open("catalogue.gml");
var catalogue = S128ProductCatalogue.From(dataset, out var diagnostics);
foreach (var product in catalogue.Products)
{
Console.WriteLine($"{product.FeatureType} {product.Id} " +
$"(ed. {product.EditionNumber}, spec {product.ProductSpecificationName})");
foreach (var superseded in product.Supersedes)
Console.WriteLine($" supersedes → {superseded.Id}");
foreach (var successor in product.SupersededBy)
Console.WriteLine($" superseded by → {successor.Id}");
}
foreach (var d in diagnostics)
Console.WriteLine(d);
Coordinate ordering
Per S-100 Part 10b §6.2, all coordinates inside <gml:pos> /
<gml:posList> for EPSG:4326 are lat lon.
Validation
Validation/S128CatalogueRules.cs ships a pilot pack of seven Tier-1 /
Tier-2 rules over S128ProductCatalogue. Rule identifiers follow the
convention S128-R-{clause} and trace to clauses of S-128 Edition
2.0.0 (§ 12 Feature Catalogue, plus S-100 Part 10b §6 for geometry).
| Rule ID | Severity | Summary |
|---|---|---|
S128-R-12.1 |
Error | When present, every catalogue entry's editionNumber is ≥ 1. |
S128-R-12.2 |
Error | When both are present, issueDate ≤ updateDate. |
S128-R-12.3 |
Error | Every coverage coordinate lies in the WGS-84 lat/lon ranges. |
S128-R-12.4 |
Error | Surface exterior rings have ≥ 4 vertices and are closed. |
S128-R-12.5 |
Error | Product gml:id values are unique across the catalogue. |
S128-R-12.6 |
Warning | onlineResource/linkage values parse as absolute URIs when present. |
S128-R-12.7 |
Warning | The catalogue carries at least one ProducerInformation or DistributorInformation record. |
Run the default pack:
using EncDotNet.S100.Datasets.S128;
using EncDotNet.S100.Datasets.S128.DataModel;
using EncDotNet.S100.Datasets.S128.Validation;
await using var stream = File.OpenRead("catalogue.gml");
var dataset = S128Dataset.Open(stream);
var catalogue = S128ProductCatalogue.From(dataset, out _);
var report = S128CatalogueRules.Validate(catalogue);
foreach (var f in report.Findings)
Console.WriteLine($"[{f.Severity}] {f.RuleId}: {f.Message}");
Tier-3 cross-dataset rules (e.g. cross-referencing catalogue entries
against actually loaded S-1xx datasets) are deferred until the MCP
validate_all surface lands.
Portrayal
The bundled main.xsl includes per-feature templates
(ElectronicProduct.xsl, PhysicalProduct.xsl, S100Service.xsl,
DistributorInformation.xsl) plus simpleLineStyle.xsl /
textStyle.xsl and a Default.xsl fallback. No locally-authored XSLT
ships in this PR — status-driven (in-force / superseded / withdrawn /
planned) styling is not in the upstream PC and is left as a TODO.
Out of scope (this release)
- Status-driven local XSLT styling (in-force / superseded /
withdrawn / planned). The data-model side of supersedes is now
resolved via
S128ProductCatalogue; the corresponding XSLT portrayal hook is still deferred. - Auto-downloading datasets pointed at by
onlineResource.linkageURLs. - Dataset authoring / serialisation.
- Multi-language label resolution.
- A dedicated catalogue browser side panel in the viewer (datasets load through the existing pipeline and render as coverage polygons).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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
- EncDotNet.S100.Core (>= 0.24.0)
- EncDotNet.S100.Portrayals (>= 0.24.0)
-
net8.0
- EncDotNet.S100.Core (>= 0.24.0)
- EncDotNet.S100.Portrayals (>= 0.24.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on EncDotNet.S100.Datasets.S128:
| Package | Downloads |
|---|---|
|
EncDotNet.S100.Datasets.Pipelines
Per-spec IDatasetProcessor implementations, the DatasetPipelineFactory (file -> processor detection), the headless image-render capability, the S-98 interoperability authority, and the validation runner for IHO S-100 product datasets. Consumed by the EncDotNet.S100 convenience package, the viewer, and the s100 CLI. |
|
|
EncDotNet.S100.Collections
Libraries for manipulating S-100 based nautical charts. |
GitHub repositories
This package is not used by any popular GitHub repositories.