Coordinate epoch support
Added in version 3.4.
Dynamic CRS and coordinate epoch
This document is intended to document the support for coordinate epoch, linked to dynamic CRS.
In a dynamic CRS, coordinates of a point on the surface of the Earth may change with time. To be unambiguous the coordinates must always be qualified with the epoch at which they are valid. The coordinate epoch is not necessarily the epoch at which the observation was collected.
Examples of dynamic CRS are WGS 84 (G1762)
, ITRF2014
, ATRF2014
.
The generic EPSG:4326 WGS 84 CRS is also considered dynamic, although it is not recommended to use it due to being based on a datum ensemble whose positional accuracy is 2 meters, but prefer one of its realizations, such as WGS 84 (G1762)
The OGRSpatialReference::IsDynamic()
method can be used to test if
a CRS is a dynamic one.
The OGRSpatialReference::SetCoordinateEpoch()
and
OGRSpatialReference::GetCoordinateEpoch()
methods can be used to
set/retrieve a coordinate epoch associated with a CRS. The coordinate epoch is
expressed as a decimal year (e.g. 2021.3 for April 21, 2021).
Formally, the coordinate epoch of an observation belongs to the observation. However, almost all formats do not allow for storing per-observation epoch, and typical usage is a set of observations with the same epoch. Therefore we store the epoch as property of the CRS, and assume that it is valid for every observation. This choice eases processing, storage and format complexity for most usage. For now, this means that a dataset containing observations or points with different epochs cannot be handled.
For vector formats, per-geometry coordinate epoch could also make sense, but as most formats only support a per-layer CRS, we also for now limit support of coordinate epoch at the layer level. The underlying coordinate transformation mechanics can support per-vertex coordinate epoch.
Support in raster and vector formats
At time of writing, no formats handled by GDAL/OGR have a standardized way of encoding a coordinate epoch. We consequently have made choices how to encode it, with the aim of being as much as possible backward compatible with existing readers. Those encodings might change if corresponding official specifications evolve to take this concept into account. The coordinate epoch is only written when attached to the SRS of the layer/dataset that is created.
FlatGeoBuf
The coordinate epoch is encoded as a WKT:2019 string using the EPOCH
subnode of the
COORDINATEMETADATA
construct, set in the Crs.wkt
header field of the FlatGeoBuf file.
COORDINATEMETADATA[
GEOGCRS["WGS 84 (G1762)",
DYNAMIC[FRAMEEPOCH[2005.0]],
DATUM["World Geodetic System 1984 (G1762)",
ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1.0]]
],
CS[ellipsoidal,3],
AXIS["(lat)",north,ANGLEUNIT["degree",0.0174532925199433]],
AXIS["(lon)",east,ANGLEUNIT["degree",0.0174532925199433]],
AXIS["ellipsoidal height (h)",up,LENGTHUNIT["metre",1.0]]
],
EPOCH[2016.47]
]
Note
Such construct will not be understood by GDAL < 3.4, but if the CRS has an associated EPSG code, this will not cause issues in those older GDAL versions.
GeoPackage vector/raster
Each vector/raster table which has an associated coordinate epoch encodes it
in the epoch
column of the gpkg_spatial_ref_sys
table, using an extended
version of the CRS WKT extension (https://github.com/opengeospatial/geopackage/pull/600).
GeoTIFF
The coordinate epoch is encoded as a new GeoTIFF GeoKey, CoordinateEpochGeoKey
of code 5120 and type DOUBLE.
Geotiff_Information:
Version: 1
Key_Revision: 1.0
Tagged_Information:
ModelTiepointTag (2,3):
0 0 0
440720 3751320 0
ModelPixelScaleTag (1,3):
60 60 0
End_Of_Tags.
Keyed_Information:
GTModelTypeGeoKey (Short,1): ModelTypeProjected
GTRasterTypeGeoKey (Short,1): RasterPixelIsArea
GTCitationGeoKey (Ascii,22): "WGS 84 / UTM zone 11N"
GeogCitationGeoKey (Ascii,7): "WGS 84"
GeogAngularUnitsGeoKey (Short,1): Angular_Degree
ProjectedCSTypeGeoKey (Short,1): PCS_WGS84_UTM_zone_11N
ProjLinearUnitsGeoKey (Short,1): Linear_Meter
CoordinateEpochGeoKey (Double,1): 2021.3
End_Of_Keys.
End_Of_Geotiff.
JPEG2000
GeoJP2 boxes use the above mentioned GeoTIFF encoding.
Persistent Auxiliary Metadata (.aux.xml)
The coordinate epoch is encoded as coordinateEpoch
attribute of the SRS
element.
<PAMDataset>
<SRS dataAxisToSRSAxisMapping="1,2" coordinateEpoch="2021.3">PROJCS["WGS 84 / UTM zone 11N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-117],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32611"]]</SRS>
<!-- snip -->
</PAMDataset>
GDAL VRT
The coordinate epoch is encoded as coordinateEpoch
attribute of the SRS
element.
<VRTDataset rasterXSize="20" rasterYSize="20">
<SRS dataAxisToSRSAxisMapping="1,2" coordinateEpoch="2021.3">PROJCS["WGS 84 / UTM zone 11N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-117],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32611"]]</SRS>
<!-- snip -->
</VRTDataset>
Support in utilities
gdalinfo and ogrinfo report the coordinate epoch, when attached to a dataset/layer SRS.
gdal_edit.py has a -a_coord_epoch
option to define the epoch of a dataset in place.
gdal_translate and ogr2ogr have a -a_coord_epoch
option to be used
together with -a_srs
, and otherwise preserve the coordinate epoch in the output SRS
from the source SRS when no SRS related options are specified.
gdalwarp and ogr2ogr have a -s_coord_epoch
option to be used together with -s_srs
(resp. -t_coord_epoch
option to be used together with -t_srs
) to override/set the
coordinate epoch of the source (resp. target) CRS.
Before PROJ 9.4, -s_coord_epoch
and -t_coord_epoch
were mutually exclusive, due to lack
of support for transformations between two dynamic CRS.
gdalwarp preserves the coordinate epoch in the output SRS when appropriate.
Support in coordinate transformation
The OGRCoordinateTransformation
class can perform time-dependent
transformations between a static and dynamic CRS based on the coordinate epoch
passed per vertex.
It can also take into account the coordinate epoch associated with a dynamic
CRS, when doing time-dependent transformations between a static and dynamic CRS.
The OGR_CT_USE_SRS_COORDINATE_EPOCH
configuration option
can be set to NO
to disable using the coordinate epoch associated with the
source or target CRS.
If a per-vertex time is specified, it overrides the one associated with the CRS.