epsg_utils/crs.rs
1/// A top-level coordinate reference system.
2///
3/// This enum dispatches over the different CRS types that this parser can handle.
4#[derive(Debug, Clone, PartialEq)]
5pub enum Crs {
6 /// A projected CRS (WKT2 keyword: `PROJCRS`).
7 ProjectedCrs(Box<ProjectedCrs>),
8 /// A geographic CRS (WKT2 keyword: `GEOGCRS`).
9 GeogCrs(Box<GeogCrs>),
10 /// A geodetic CRS (WKT2 keyword: `GEODCRS`).
11 GeodCrs(Box<GeodCrs>),
12 /// A vertical CRS (WKT2 keyword: `VERTCRS`).
13 VertCrs(Box<VertCrs>),
14 /// A compound CRS (WKT2 keyword: `COMPOUNDCRS`).
15 CompoundCrs(Box<CompoundCrs>),
16}
17
18impl Crs {
19 /// Serialize this CRS to a WKT2 string.
20 ///
21 /// This is an alias for [`ToString::to_string()`] provided for discoverability.
22 pub fn to_wkt2(&self) -> String {
23 self.to_string()
24 }
25
26 /// Extract the EPSG code from this CRS's identifiers, if present.
27 pub fn to_epsg(&self) -> Option<i32> {
28 match self {
29 Crs::ProjectedCrs(crs) => crs.to_epsg(),
30 Crs::GeogCrs(crs) => crs.to_epsg(),
31 Crs::GeodCrs(crs) => crs.to_epsg(),
32 Crs::VertCrs(crs) => crs.to_epsg(),
33 Crs::CompoundCrs(crs) => crs.to_epsg(),
34 }
35 }
36}
37
38/// A geographic coordinate reference system (GEOGCRS).
39///
40/// A geographic CRS uses an ellipsoidal coordinate system with latitude and longitude.
41///
42/// WKT2 keywords: `GEOGCRS` (preferred), `GEOGRAPHICCRS`.
43#[derive(Debug, Clone, PartialEq)]
44pub struct GeogCrs {
45 /// The name of the geographic CRS (e.g. "WGS 84").
46 pub name: String,
47 /// Present only if the CRS is dynamic (has a time-varying reference frame).
48 pub dynamic: Option<DynamicCrs>,
49 /// The datum: either a geodetic reference frame or a datum ensemble.
50 pub datum: Datum,
51 /// The coordinate system describing axes, their directions, and units.
52 pub coordinate_system: CoordinateSystem,
53 /// Zero or more scope-extent pairings describing the applicability of this CRS.
54 pub usages: Vec<Usage>,
55 /// Zero or more external identifiers referencing this CRS.
56 pub identifiers: Vec<Identifier>,
57 /// An optional free-text remark about this CRS.
58 pub remark: Option<String>,
59}
60
61impl GeogCrs {
62 /// Extract the EPSG code from this CRS's identifiers, if present.
63 pub fn to_epsg(&self) -> Option<i32> {
64 self.identifiers.iter().find_map(|id| {
65 if id.authority_name == "EPSG"
66 && let AuthorityId::Number(n) = id.authority_unique_id
67 {
68 return Some(n as i32);
69 }
70 None
71 })
72 }
73}
74
75/// A geodetic coordinate reference system (GEODCRS).
76///
77/// A geodetic CRS uses a Cartesian or spherical coordinate system.
78///
79/// WKT2 keywords: `GEODCRS` (preferred), `GEODETICCRS`.
80#[derive(Debug, Clone, PartialEq)]
81pub struct GeodCrs {
82 /// The name of the geodetic CRS (e.g. "WGS 84").
83 pub name: String,
84 /// Present only if the CRS is dynamic (has a time-varying reference frame).
85 pub dynamic: Option<DynamicCrs>,
86 /// The datum: either a geodetic reference frame or a datum ensemble.
87 pub datum: Datum,
88 /// The coordinate system describing axes, their directions, and units.
89 pub coordinate_system: CoordinateSystem,
90 /// Zero or more scope-extent pairings describing the applicability of this CRS.
91 pub usages: Vec<Usage>,
92 /// Zero or more external identifiers referencing this CRS.
93 pub identifiers: Vec<Identifier>,
94 /// An optional free-text remark about this CRS.
95 pub remark: Option<String>,
96}
97
98impl GeodCrs {
99 /// Extract the EPSG code from this CRS's identifiers, if present.
100 pub fn to_epsg(&self) -> Option<i32> {
101 self.identifiers.iter().find_map(|id| {
102 if id.authority_name == "EPSG"
103 && let AuthorityId::Number(n) = id.authority_unique_id
104 {
105 return Some(n as i32);
106 }
107 None
108 })
109 }
110}
111
112/// A vertical coordinate reference system (VERTCRS).
113///
114/// A vertical CRS uses a vertical coordinate system (height or depth).
115/// It may be a standalone CRS (with a datum) or a derived CRS (with a base
116/// vertical CRS and a deriving conversion).
117///
118/// WKT2 keywords: `VERTCRS` (preferred), `VERTICALCRS`.
119#[derive(Debug, Clone, PartialEq)]
120pub struct VertCrs {
121 /// The name of the vertical CRS (e.g. "NAVD88").
122 pub name: String,
123 /// The source of this CRS: either a datum or a base vertical CRS with a
124 /// deriving conversion.
125 pub source: VertCrsSource,
126 /// The coordinate system describing axes, their directions, and units.
127 pub coordinate_system: CoordinateSystem,
128 /// Zero or more geoid model references.
129 pub geoid_models: Vec<GeoidModel>,
130 /// Zero or more scope-extent pairings describing the applicability of this CRS.
131 pub usages: Vec<Usage>,
132 /// Zero or more external identifiers referencing this CRS.
133 pub identifiers: Vec<Identifier>,
134 /// An optional free-text remark about this CRS.
135 pub remark: Option<String>,
136}
137
138/// Whether a vertical CRS is standalone (datum-based) or derived from a base
139/// vertical CRS.
140#[derive(Debug, Clone, PartialEq)]
141pub enum VertCrsSource {
142 /// A standalone vertical CRS with a datum.
143 Datum {
144 /// Present only if the CRS is dynamic.
145 dynamic: Option<DynamicCrs>,
146 /// The datum: either a vertical reference frame or a datum ensemble.
147 datum: VerticalDatum,
148 },
149 /// A derived vertical CRS with a base CRS and a deriving conversion.
150 Derived {
151 /// The base vertical CRS from which this CRS is derived.
152 base_vert_crs: BaseVertCrs,
153 /// The conversion applied to the base CRS.
154 deriving_conversion: MapProjection,
155 },
156}
157
158/// The base vertical CRS of a derived vertical CRS.
159///
160/// WKT2 keyword: `BASEVERTCRS`.
161#[derive(Debug, Clone, PartialEq)]
162pub struct BaseVertCrs {
163 /// The name of the base CRS.
164 pub name: String,
165 /// Present only if the base CRS is dynamic.
166 pub dynamic: Option<DynamicCrs>,
167 /// The datum: either a vertical reference frame or a datum ensemble.
168 pub datum: VerticalDatum,
169 /// Identifiers for this base CRS.
170 pub identifiers: Vec<Identifier>,
171}
172
173impl VertCrs {
174 /// Extract the EPSG code from this CRS's identifiers, if present.
175 pub fn to_epsg(&self) -> Option<i32> {
176 self.identifiers.iter().find_map(|id| {
177 if id.authority_name == "EPSG"
178 && let AuthorityId::Number(n) = id.authority_unique_id
179 {
180 return Some(n as i32);
181 }
182 None
183 })
184 }
185}
186
187/// A vertical datum is either a vertical reference frame or a datum ensemble.
188#[derive(Debug, Clone, PartialEq)]
189pub enum VerticalDatum {
190 /// A single vertical reference frame.
191 ReferenceFrame(VerticalReferenceFrame),
192 /// An ensemble of vertical reference frames.
193 Ensemble(Box<DatumEnsemble>),
194}
195
196/// A vertical reference frame (vertical datum).
197///
198/// WKT2 keywords: `VDATUM` (preferred), `VRF`, `VERTICALDATUM`.
199#[derive(Debug, Clone, PartialEq)]
200pub struct VerticalReferenceFrame {
201 /// The datum name (e.g. "North American Vertical Datum 1988").
202 pub name: String,
203 /// A textual description of the datum anchor point.
204 pub anchor: Option<String>,
205 /// The epoch at which a derived static reference frame is aligned to its parent
206 /// dynamic frame.
207 pub anchor_epoch: Option<f64>,
208 /// Identifiers for this datum.
209 pub identifiers: Vec<Identifier>,
210}
211
212/// A reference to a geoid model associated with a vertical CRS.
213///
214/// WKT2 keyword: `GEOIDMODEL`.
215#[derive(Debug, Clone, PartialEq)]
216pub struct GeoidModel {
217 /// The name of the geoid model.
218 pub name: String,
219 /// Identifiers for this geoid model.
220 pub identifiers: Vec<Identifier>,
221}
222
223/// A compound coordinate reference system (COMPOUNDCRS).
224///
225/// A compound CRS is a non-repeating sequence of two or more independent CRSs.
226///
227/// WKT2 keyword: `COMPOUNDCRS`.
228#[derive(Debug, Clone, PartialEq)]
229pub struct CompoundCrs {
230 /// The name of the compound CRS (e.g. "NAD83 + NAVD88").
231 pub name: String,
232 /// The constituent single CRSs (at least two).
233 pub components: Vec<SingleCrs>,
234 /// Zero or more scope-extent pairings describing the applicability of this CRS.
235 pub usages: Vec<Usage>,
236 /// Zero or more external identifiers referencing this CRS.
237 pub identifiers: Vec<Identifier>,
238 /// An optional free-text remark about this CRS.
239 pub remark: Option<String>,
240}
241
242impl CompoundCrs {
243 /// Extract the EPSG code from this CRS's identifiers, if present.
244 pub fn to_epsg(&self) -> Option<i32> {
245 self.identifiers.iter().find_map(|id| {
246 if id.authority_name == "EPSG"
247 && let AuthorityId::Number(n) = id.authority_unique_id
248 {
249 return Some(n as i32);
250 }
251 None
252 })
253 }
254}
255
256/// A single (non-compound) CRS, used as a component of a compound CRS.
257#[derive(Debug, Clone, PartialEq)]
258pub enum SingleCrs {
259 /// A projected CRS.
260 ProjectedCrs(Box<ProjectedCrs>),
261 /// A geographic CRS.
262 GeogCrs(Box<GeogCrs>),
263 /// A geodetic CRS.
264 GeodCrs(Box<GeodCrs>),
265 /// A vertical CRS.
266 VertCrs(Box<VertCrs>),
267 /// An unsupported CRS type, stored as raw WKT text.
268 Other(String),
269}
270
271/// A projected coordinate reference system (PROJCRS).
272///
273/// A projected CRS is derived from a geographic CRS by applying a map projection.
274/// It uses Cartesian coordinates (easting/northing) rather than angular coordinates.
275///
276/// WKT2 keywords: `PROJCRS` (preferred), `PROJECTEDCRS` (not supported by this parser).
277#[derive(Debug, Clone, PartialEq)]
278pub struct ProjectedCrs {
279 /// The name of the projected CRS (e.g. "WGS 84 / UTM zone 31N").
280 pub name: String,
281 /// The base geodetic or geographic CRS from which this CRS is derived.
282 pub base_geodetic_crs: BaseGeodeticCrs,
283 /// The map projection (conversion) applied to the base CRS.
284 pub map_projection: MapProjection,
285 /// The coordinate system describing axes, their directions, and units.
286 pub coordinate_system: CoordinateSystem,
287 /// Zero or more scope-extent pairings describing the applicability of this CRS.
288 pub usages: Vec<Usage>,
289 /// Zero or more external identifiers referencing this CRS.
290 pub identifiers: Vec<Identifier>,
291 /// An optional free-text remark about this CRS.
292 pub remark: Option<String>,
293}
294
295impl ProjectedCrs {
296 /// Extract the EPSG code from this CRS's identifiers, if present.
297 ///
298 /// Returns `Some(code)` if the CRS has an identifier with authority "EPSG"
299 /// and a numeric code, or `None` otherwise.
300 pub fn to_epsg(&self) -> Option<i32> {
301 self.identifiers.iter().find_map(|id| {
302 if id.authority_name == "EPSG"
303 && let AuthorityId::Number(n) = id.authority_unique_id
304 {
305 return Some(n as i32);
306 }
307 None
308 })
309 }
310}
311
312/// A coordinate system definition, consisting of a type, dimension, axes, and an optional
313/// shared unit.
314///
315/// WKT2 keyword: `CS`.
316#[derive(Debug, Clone, PartialEq)]
317pub struct CoordinateSystem {
318 /// The type of coordinate system (e.g. Cartesian, ellipsoidal).
319 pub cs_type: CsType,
320 /// The number of dimensions (1, 2, or 3).
321 pub dimension: u8,
322 /// Identifiers for the coordinate system itself.
323 pub identifiers: Vec<Identifier>,
324 /// The axes of the coordinate system. These appear as siblings after the `CS[...]` node.
325 pub axes: Vec<Axis>,
326 /// An optional unit shared by all axes. If absent, each axis specifies its own unit.
327 pub cs_unit: Option<Unit>,
328}
329
330/// The type of a coordinate system.
331#[derive(Debug, Clone, PartialEq)]
332pub enum CsType {
333 /// An affine coordinate system.
334 Affine,
335 /// A Cartesian coordinate system with orthogonal straight axes.
336 Cartesian,
337 /// A 3D coordinate system with a polar and a longitudinal axis, plus a straight axis.
338 Cylindrical,
339 /// A coordinate system on the surface of an ellipsoid using latitude and longitude.
340 Ellipsoidal,
341 /// A 1D coordinate system along a straight line.
342 Linear,
343 /// A coordinate system for parametric values (e.g. pressure levels).
344 Parametric,
345 /// A 2D coordinate system with a straight radial axis and an angular axis.
346 Polar,
347 /// A 3D coordinate system on a sphere using two angular coordinates plus radius.
348 Spherical,
349 /// A 1D coordinate system for height or depth.
350 Vertical,
351 /// A temporal coordinate system using integer counts of a time unit.
352 TemporalCount,
353 /// A temporal coordinate system using real-valued measurements of a time unit.
354 TemporalMeasure,
355 /// A coordinate system using discrete ordinal values (ranks).
356 Ordinal,
357 /// A temporal coordinate system using date-time values.
358 TemporalDateTime,
359}
360
361/// A single axis of a coordinate system.
362///
363/// WKT2 keyword: `AXIS`.
364#[derive(Debug, Clone, PartialEq)]
365pub struct Axis {
366 /// The axis name and/or abbreviation (e.g. "easting (E)").
367 pub name_abbrev: String,
368 /// The axis direction (e.g. "north", "east", "up", "clockwise").
369 pub direction: String,
370 /// The meridian from which the axis direction is measured. Only used with
371 /// certain directions like "north" or "south".
372 pub meridian: Option<Meridian>,
373 /// The bearing angle for "clockwise" or "counterClockwise" directions, in degrees.
374 pub bearing: Option<f64>,
375 /// The ordering of this axis within the coordinate system (1-based).
376 pub order: Option<u32>,
377 /// The unit for values along this axis. If absent, the coordinate system's shared unit applies.
378 pub unit: Option<Unit>,
379 /// The minimum value for this axis.
380 pub axis_min_value: Option<f64>,
381 /// The maximum value for this axis.
382 pub axis_max_value: Option<f64>,
383 /// Whether the axis range is exact or wraps around (e.g. longitude 0-360).
384 pub range_meaning: Option<RangeMeaning>,
385 /// Identifiers for this axis.
386 pub identifiers: Vec<Identifier>,
387}
388
389/// A meridian from which an axis direction is measured.
390///
391/// WKT2 keyword: `MERIDIAN`.
392#[derive(Debug, Clone, PartialEq)]
393pub struct Meridian {
394 /// The meridian value (typically longitude in the given angle unit).
395 pub value: f64,
396 /// The angle unit for the meridian value.
397 pub unit: Unit,
398}
399
400/// How the axis range between min and max values is interpreted.
401///
402/// WKT2 keyword: `RANGEMEANING`.
403#[derive(Debug, Clone, Copy, PartialEq)]
404pub enum RangeMeaning {
405 /// The range boundaries are exact limits.
406 Exact,
407 /// The range wraps around (e.g. longitude 0 to 360 degrees).
408 Wraparound,
409}
410
411/// A map projection (coordinate conversion) applied to a base CRS to produce a projected CRS.
412///
413/// WKT2 keyword: `CONVERSION`.
414#[derive(Debug, Clone, PartialEq)]
415pub struct MapProjection {
416 /// The name of the map projection (e.g. "UTM zone 31N").
417 pub name: String,
418 /// The projection method (e.g. "Transverse Mercator").
419 pub method: MapProjectionMethod,
420 /// The parameters of the projection (e.g. central meridian, scale factor).
421 pub parameters: Vec<MapProjectionParameter>,
422 /// Identifiers for this conversion as a whole.
423 pub identifiers: Vec<Identifier>,
424}
425
426/// The method (algorithm) used by a map projection.
427///
428/// WKT2 keywords: `METHOD` (preferred), `PROJECTION` (backward compatibility).
429#[derive(Debug, Clone, PartialEq)]
430pub struct MapProjectionMethod {
431 /// The name of the method (e.g. "Transverse Mercator").
432 pub name: String,
433 /// Identifiers for this method.
434 pub identifiers: Vec<Identifier>,
435}
436
437/// A single parameter of a map projection.
438///
439/// WKT2 keyword: `PARAMETER`.
440#[derive(Debug, Clone, PartialEq)]
441pub struct MapProjectionParameter {
442 /// The parameter name (e.g. "Latitude of natural origin").
443 pub name: String,
444 /// The numeric value of the parameter.
445 pub value: f64,
446 /// The unit for the parameter value (angle, length, or scale).
447 pub unit: Option<Unit>,
448 /// Identifiers for this parameter.
449 pub identifiers: Vec<Identifier>,
450}
451
452/// The keyword used for a base geodetic CRS within a projected CRS.
453#[derive(Debug, Clone, PartialEq)]
454pub enum BaseGeodeticCrsKeyword {
455 /// `BASEGEODCRS` -- a geodetic (geocentric) base CRS.
456 BaseGeodCrs,
457 /// `BASEGEOGCRS` -- a geographic base CRS (the more common form).
458 BaseGeogCrs,
459}
460
461/// The base geodetic or geographic CRS from which a projected CRS is derived.
462///
463/// WKT2 keywords: `BASEGEOGCRS` (preferred), `BASEGEODCRS`.
464#[derive(Debug, Clone, PartialEq)]
465pub struct BaseGeodeticCrs {
466 /// Which keyword was used in the WKT.
467 pub keyword: BaseGeodeticCrsKeyword,
468 /// The name of the base CRS.
469 pub name: String,
470 /// Present only if the CRS is dynamic (has a time-varying reference frame).
471 pub dynamic: Option<DynamicCrs>,
472 /// The datum: either a geodetic reference frame or a datum ensemble.
473 pub datum: Datum,
474 /// An optional ellipsoidal coordinate system unit for the base CRS.
475 pub ellipsoidal_cs_unit: Option<Unit>,
476 /// Identifiers for this base CRS.
477 pub identifiers: Vec<Identifier>,
478}
479
480/// Dynamic CRS attributes for a CRS with a time-varying reference frame.
481///
482/// In a dynamic CRS, coordinate values of a point change with time.
483///
484/// WKT2 keyword: `DYNAMIC`.
485#[derive(Debug, Clone, PartialEq)]
486pub struct DynamicCrs {
487 /// The epoch at which the reference frame is defined (e.g. 2010.0).
488 pub frame_reference_epoch: f64,
489 /// An optional reference to a deformation model or velocity grid.
490 pub deformation_model: Option<DeformationModel>,
491}
492
493/// A reference to a deformation model or velocity grid associated with a dynamic CRS.
494///
495/// WKT2 keywords: `MODEL` (preferred), `VELOCITYGRID`.
496#[derive(Debug, Clone, PartialEq)]
497pub struct DeformationModel {
498 /// The name of the deformation model.
499 pub name: String,
500 /// Identifiers for this deformation model.
501 pub identifiers: Vec<Identifier>,
502}
503
504/// A datum is either a geodetic reference frame or a datum ensemble.
505#[derive(Debug, Clone, PartialEq)]
506pub enum Datum {
507 /// A single geodetic reference frame (classical datum or modern terrestrial reference frame).
508 ReferenceFrame(GeodeticReferenceFrame),
509 /// An ensemble of reference frames that are considered approximately equivalent.
510 Ensemble(DatumEnsemble),
511}
512
513/// A geodetic reference frame (datum), defining the relationship between a coordinate
514/// system and the Earth.
515///
516/// WKT2 keywords: `DATUM` (preferred), `TRF`, `GEODETICDATUM`.
517#[derive(Debug, Clone, PartialEq)]
518pub struct GeodeticReferenceFrame {
519 /// The datum name (e.g. "World Geodetic System 1984").
520 pub name: String,
521 /// The reference ellipsoid.
522 pub ellipsoid: Ellipsoid,
523 /// A textual description of the datum anchor point.
524 pub anchor: Option<String>,
525 /// The epoch at which a derived static reference frame is aligned to its parent
526 /// dynamic frame.
527 pub anchor_epoch: Option<f64>,
528 /// Identifiers for this datum.
529 pub identifiers: Vec<Identifier>,
530 /// The prime meridian. Appears as a sibling after the DATUM node in WKT2.
531 /// If absent, the international reference meridian (Greenwich) is assumed.
532 pub prime_meridian: Option<PrimeMeridian>,
533}
534
535/// The prime meridian defining zero longitude.
536///
537/// WKT2 keywords: `PRIMEM` (preferred), `PRIMEMERIDIAN`.
538#[derive(Debug, Clone, PartialEq)]
539pub struct PrimeMeridian {
540 /// The name of the prime meridian (e.g. "Greenwich", "Paris").
541 pub name: String,
542 /// The longitude of this meridian measured from the international reference meridian,
543 /// positive eastward.
544 pub irm_longitude: f64,
545 /// The angle unit for the longitude value. If absent, the value is in the CRS's
546 /// angular unit (if available), otherwise in decimal degrees.
547 pub unit: Option<Unit>,
548 /// Identifiers for this prime meridian.
549 pub identifiers: Vec<Identifier>,
550}
551
552/// A reference ellipsoid (the mathematical figure of the Earth).
553///
554/// WKT2 keywords: `ELLIPSOID` (preferred), `SPHEROID` (backward compatibility).
555#[derive(Debug, Clone, PartialEq)]
556pub struct Ellipsoid {
557 /// The ellipsoid name (e.g. "WGS 84", "GRS 1980").
558 pub name: String,
559 /// The semi-major axis length.
560 pub semi_major_axis: f64,
561 /// The inverse flattening (0 for a sphere).
562 pub inverse_flattening: f64,
563 /// The length unit for the semi-major axis. If absent, metres are assumed.
564 pub unit: Option<Unit>,
565 /// Identifiers for this ellipsoid.
566 pub identifiers: Vec<Identifier>,
567}
568
569/// A datum ensemble: a collection of reference frames considered approximately equivalent.
570///
571/// Use of datum ensembles comes with a caveat: it will not be possible to identify which
572/// member the data is most accurately referenced to.
573///
574/// WKT2 keyword: `ENSEMBLE`.
575#[derive(Debug, Clone, PartialEq)]
576pub struct DatumEnsemble {
577 /// The ensemble name (e.g. "WGS 84 ensemble").
578 pub name: String,
579 /// The member reference frames of this ensemble.
580 pub members: Vec<EnsembleMember>,
581 /// The reference ellipsoid. Present for geodetic datum ensembles, absent for vertical.
582 pub ellipsoid: Option<Ellipsoid>,
583 /// The positional accuracy of the ensemble in metres, indicating the difference in
584 /// coordinate values between members.
585 pub accuracy: f64,
586 /// Identifiers for this ensemble.
587 pub identifiers: Vec<Identifier>,
588 /// The prime meridian. Present for geodetic datum ensembles, appears as a sibling
589 /// after the ENSEMBLE node.
590 pub prime_meridian: Option<PrimeMeridian>,
591}
592
593/// A member of a datum ensemble.
594///
595/// WKT2 keyword: `MEMBER`.
596#[derive(Debug, Clone, PartialEq)]
597pub struct EnsembleMember {
598 /// The member name (e.g. "WGS 84 (G730)").
599 pub name: String,
600 /// Identifiers for this member.
601 pub identifiers: Vec<Identifier>,
602}
603
604/// An external identifier referencing an authority's definition of an object.
605///
606/// WKT2 keyword: `ID`.
607#[derive(Debug, Clone, PartialEq)]
608pub struct Identifier {
609 /// The name of the authority (e.g. "EPSG").
610 pub authority_name: String,
611 /// The unique identifier within the authority (e.g. 4326 or "Abcd_Ef").
612 pub authority_unique_id: AuthorityId,
613 /// The version of the cited object or repository.
614 pub version: Option<AuthorityId>,
615 /// A citation giving further details of the authority.
616 pub citation: Option<String>,
617 /// A URI referencing an online resource.
618 pub uri: Option<String>,
619}
620
621/// An authority identifier value, which can be either numeric or textual.
622#[derive(Debug, Clone, PartialEq)]
623pub enum AuthorityId {
624 /// A numeric identifier (e.g. `4326`).
625 Number(f64),
626 /// A textual identifier (e.g. `"Abcd_Ef"`).
627 Text(String),
628}
629
630/// The keyword used for a unit.
631#[derive(Debug, Clone, PartialEq)]
632pub enum UnitKeyword {
633 /// `ANGLEUNIT` -- for angular measurements.
634 AngleUnit,
635 /// `LENGTHUNIT` -- for linear measurements.
636 LengthUnit,
637 /// `PARAMETRICUNIT` -- for parametric values (e.g. pressure).
638 ParametricUnit,
639 /// `SCALEUNIT` -- for dimensionless scale factors.
640 ScaleUnit,
641 /// `TIMEUNIT` (or `TEMPORALQUANTITY`) -- for temporal measurements.
642 TimeUnit,
643 /// `UNIT` -- the generic backward-compatible keyword.
644 Unit,
645}
646
647/// A scope-extent pairing describing the applicability of a CRS or coordinate operation.
648///
649/// WKT2 keyword: `USAGE`.
650#[derive(Debug, Clone, PartialEq)]
651pub struct Usage {
652 /// A textual description of the scope (purpose) of the CRS.
653 pub scope: String,
654 /// A textual description of the geographic area of applicability.
655 pub area: Option<String>,
656 /// A geographic bounding box describing the area of applicability.
657 pub bbox: Option<BBox>,
658 /// A vertical height range of applicability.
659 pub vertical_extent: Option<VerticalExtent>,
660 /// A temporal range of applicability.
661 pub temporal_extent: Option<TemporalExtent>,
662}
663
664/// A geographic bounding box in decimal degrees relative to the international reference meridian.
665///
666/// WKT2 keyword: `BBOX`.
667#[derive(Debug, Clone, PartialEq)]
668pub struct BBox {
669 /// The southern latitude boundary (-90 to +90).
670 pub lower_left_latitude: f64,
671 /// The western longitude boundary (-180 to +180).
672 pub lower_left_longitude: f64,
673 /// The northern latitude boundary (-90 to +90).
674 pub upper_right_latitude: f64,
675 /// The eastern longitude boundary (-180 to +180). May be less than
676 /// `lower_left_longitude` when the area crosses the 180 degree meridian.
677 pub upper_right_longitude: f64,
678}
679
680/// A vertical height range of applicability. Depths have negative height values.
681///
682/// WKT2 keyword: `VERTICALEXTENT`.
683#[derive(Debug, Clone, PartialEq)]
684pub struct VerticalExtent {
685 /// The minimum height (most negative = deepest).
686 pub minimum_height: f64,
687 /// The maximum height.
688 pub maximum_height: f64,
689 /// The unit for the height values. If absent, metres are assumed.
690 pub unit: Option<Unit>,
691}
692
693/// A temporal range of applicability.
694///
695/// WKT2 keyword: `TIMEEXTENT`.
696#[derive(Debug, Clone, PartialEq)]
697pub struct TemporalExtent {
698 /// The start of the temporal range. Either a date/time string (e.g. "2013-01-01")
699 /// or descriptive text (e.g. "Jurassic").
700 pub start: String,
701 /// The end of the temporal range.
702 pub end: String,
703}
704
705/// A unit of measurement with an optional conversion factor to the SI base unit.
706///
707/// WKT2 keywords: `ANGLEUNIT`, `LENGTHUNIT`, `SCALEUNIT`, `PARAMETRICUNIT`,
708/// `TIMEUNIT`, `TEMPORALQUANTITY`, `UNIT`.
709#[derive(Debug, Clone, PartialEq)]
710pub struct Unit {
711 /// Which keyword was used in the WKT.
712 pub keyword: UnitKeyword,
713 /// The unit name (e.g. "metre", "degree").
714 pub name: String,
715 /// The conversion factor to the SI base unit (metres for length, radians for angle,
716 /// seconds for time, unity for scale). Optional only for `TIMEUNIT` when the
717 /// conversion is not a simple scaling (e.g. "calendar month").
718 pub conversion_factor: Option<f64>,
719 /// Identifiers for this unit.
720 pub identifiers: Vec<Identifier>,
721}