Table of Contents

Class S102DatasetRules

Namespace
EncDotNet.S100.Datasets.S102.Validation
Assembly
EncDotNet.S100.Datasets.S102.dll

The default ValidationRuleSet<TModel> of normative rules for an S-102 S102Dataset. Rule identifiers follow the convention S102-R-{clause} for normative rules and S102-PROJ-{kind} for projection-diagnostic surrogates, traceable back to S-102 (Edition 3.0.0) and S-100 Part 10c.

public static class S102DatasetRules
Inheritance
S102DatasetRules
Inherited Members

Remarks

This is the V-1 rule pack as defined in docs/design/non-gml-validation.md §6.1. Rules read off the strongly-typed S102Dataset produced by S102DatasetReader; structural-schema failures the reader cannot tolerate are thrown as S100DatasetSchemaException at read time and (per design §5.1) surfaced as S102-PROJ-SCHEMA findings by the dataset processor's Validate() wrapper.

Tier-3 cross-dataset rules (e.g. tile coherency against a sibling chart) are out of scope; per-finding payload conventions follow design §4.3:

  • per-coverage finding — RelatedFeatureId = "{groupPath}"
  • per-cell finding — RelatedFeatureId = "{groupPath}[row,col]"

Properties

CoverageExtentDoesNotWrap

S102-R-4.2 — Each coverage's far grid corner (origin + (numPoints - 1) × spacing) is a plausible position in the dataset's HorizontalCRS. For a geographic CRS that means the extent does not wrap the antimeridian (longitude end > 180) or cross the pole (latitude end > 90) — antimeridian-spanning datasets are out of scope for V-1; for a projected CRS it means the corner stays within the projected bounds and reprojects to a valid WGS 84 position.

public static IValidationRule<S102Dataset> CoverageExtentDoesNotWrap { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-100 Part 10c §10.2.1.2; implements the s102-bathymetry skill review-checklist item "tile extent stays within range". See GridGeoreferencing. When the rule fires, the finding carries a BoundingBox approximating the offending tile extent in WGS 84 (edges ordered only; values may themselves be out of range) — for a projected grid only when it can be reprojected.

CoverageOriginInWgs84Range

S102-R-4.1 — Each coverage's grid origin (OriginLongitude, OriginLatitude) is a plausible position in the dataset's HorizontalCRS: within [-90, 90] / [-180, 180] degrees for a geographic CRS, or within the projected bounds (and reprojecting to a valid WGS 84 position) for a projected one.

public static IValidationRule<S102Dataset> CoverageOriginInWgs84Range { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-100 Part 10c §10.2.1.2 grid georeferencing; S-102 Edition 3.0.0 permits projected CRSs (e.g. WGS 84 / UTM), for which the gridOrigin* values are metres. See GridGeoreferencing for the CRS-specific checks; a CRS it cannot classify is not checked. Implements s102-bathymetry skill review-checklist item "georeferencing attributes within range".

CoverageValuesLengthMatchesShape

S102-R-1.1 — Every BathymetryCoverage's Values array length equals NumPointsLatitudinal × NumPointsLongitudinal.

public static IValidationRule<S102Dataset> CoverageValuesLengthMatchesShape { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-100 Part 10c §10.2.1.2 (gridded coverage shape contract) and S-102 Edition 3.0.0 §12.6 (BathymetryCoverage). Implements the s102-bathymetry skill review checklist item "values array shape matches numPointsLat × numPointsLon".

Default

The canonical default rule set for S-102 bathymetry datasets.

public static ValidationRuleSet<S102Dataset> Default { get; }

Property Value

ValidationRuleSet<S102Dataset>

DepthValuesInPlausibleRange

S102-R-5.1 — Non-NODATA depth values across each coverage lie within the plausible bathymetric range [-50, 12 000] metres.

public static IValidationRule<S102Dataset> DepthValuesInPlausibleRange { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Plausibility heuristic: continental shelves through the deepest trenches; catches common producer mistakes such as "depth recorded in centimetres" or "UTM-northing accidentally stored as depth". Per design §6.1, the rule emits one finding per coverage with the count of offending cells in the message — emitting one finding per cell on a broken tile would drown the report in cascade noise.

HorizontalCrsIsKnownEpsg

S102-R-3.1 — When HorizontalCRS is set, it resolves to a known EPSG code.

public static IValidationRule<S102Dataset> HorizontalCrsIsKnownEpsg { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-102 Edition 3.0.0 §10.2 root attribute horizontalCRS. Severity is Warning per design §6.1 — an unknown EPSG code typically reflects a producer mistake but does not render the dataset unusable; consumers may still be able to resolve the CRS through extended catalogues. See IsKnownEpsgCode(int) for the recognised set.

IssueDateIsIso8601

S102-R-3.2 — When IssueDate is set, it parses as an ISO 8601 date or date-time, in the basic (20260902) or extended (2026-09-02) format.

public static IValidationRule<S102Dataset> IssueDateIsIso8601 { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-102 Edition 3.0.0 §10.2 root attribute issueDate, which S-100 Part 10c writes in the ISO 8601 basic format YYYYMMDD. Implements the s102-bathymetry skill review-checklist item "root metadata parse cleanly". See IsDateOrDateTime(string?) for the accepted forms.

IssueTimeIsIso8601

S102-R-3.3 — When IssueTime is set, it parses as an ISO 8601 time of day, in the basic (105406Z, 105406+0000) or extended (10:54:06Z) format.

public static IValidationRule<S102Dataset> IssueTimeIsIso8601 { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-102 Edition 3.0.0 §10.2 root attribute issueTime, which S-100 Part 10c writes in the ISO 8601 basic format hhmmss with an optional zone designator. See IsTimeOfDay(string?) for the accepted forms.

NoDataFillValueIsCanonical

S102-R-2.1 — The NODATA fill value in a coverage's depth channel is exactly 1_000_000f. Any candidate-NODATA pattern other than that sentinel (NaN, NegativeInfinity, PositiveInfinity) is flagged.

public static IValidationRule<S102Dataset> NoDataFillValueIsCanonical { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

Spec reference: S-100 Part 10c §11 NODATA convention, S-102 Edition 3.0.0 §10 (mandatory fill = 1_000_000f). Implements s102-bathymetry skill review-checklist pitfall "NODATA must be exactly 1_000_000f". Conservative per design §6.1: only NaN / ±Infinity are flagged; finite values (even implausibly large) are NOT treated as candidate-NODATA because they are addressed by DepthValuesInPlausibleRange (S102-R-5.1).

ProjectionSchemaSurrogate

S102-PROJ-SCHEMA — defensive projection-diagnostic surrogate (design §5.1, §5.3).

public static IValidationRule<S102Dataset> ProjectionSchemaSurrogate { get; }

Property Value

IValidationRule<S102Dataset>

Remarks

The rule body is intentionally a no-op: by the time the rule pack runs the dataset is already constructed, so any S100DatasetSchemaException has already thrown out of the reader. The rule id is reserved in this rule set so that S102DatasetProcessor.Validate() can emit a single-finding report carrying the exception's GroupPath, AttributeOrDataset, and SpecReference under this same rule id when the defensive try/catch around the rule-pack call fires.

Methods

Validate(S102Dataset, ValidationContext?)

Convenience wrapper around Run(TModel, ValidationContext?) using the Default rule set.

public static ValidationReport Validate(S102Dataset dataset, ValidationContext? context = null)

Parameters

dataset S102Dataset
context ValidationContext

Returns

ValidationReport