Skip to content

Commit 7e5f574

Browse files
rouaultgithub-actions[bot]
authored andcommitted
Doc: add a page specific to time dependent transformations
1 parent 1292916 commit 7e5f574

File tree

4 files changed

+191
-2
lines changed

4 files changed

+191
-2
lines changed

docs/source/operations/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ exert a change in reference frame are called transformations.
2020
transformations/index
2121
pipeline
2222
operations_computation
23+
time_dependent_transformations
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
.. _time_dependent_transformations:
2+
3+
================================================================================
4+
Time-dependent transformations
5+
================================================================================
6+
7+
Introduction
8+
------------
9+
10+
PROJ offers several coordinate operation methods that can deal with time-dependent
11+
transformations:
12+
13+
* 15-parameter :ref:`Helmert <helmert>` operation, with the translation rates
14+
(``dx``, ``dy``, ``dz``), the scale rate (``dz``),
15+
the rotation rates (``drx``, ``dry``, ``drz``) and the central epoch of
16+
transformation (``t_epoch``). Such transformations are typically used between
17+
a static CRS (bound to a tectonic plate) and a dynamic CRS (such as one of the
18+
ITRF or WGS 84 realizations).
19+
20+
To transform Sydney coordinates at epoch 2026.0 from ITRF2014 to GDA2020,
21+
you can use for example:
22+
23+
::
24+
25+
echo -33.8623 151.2077 0 2026 | cs2cs -d 8 ITRF2014 GDA2020
26+
27+
-33.86230294 151.20769882 0.00101330 2026
28+
29+
30+
or equivalently using the PROJ pipeline returned by ``projinfo ITRF2014 GDA2020``:
31+
32+
::
33+
34+
echo -33.8623 151.2077 0 2026 | cct -d 8 \
35+
+proj=pipeline \
36+
+step +proj=axisswap +order=2,1 \
37+
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
38+
+step +proj=cart +ellps=GRS80 \
39+
+step +proj=helmert +x=0 +y=0 +z=0 +rx=0 +ry=0 +rz=0 +s=0 +dx=0 +dy=0 +dz=0 \
40+
+drx=0.00150379 +dry=0.00118346 +drz=0.00120716 +ds=0 +t_epoch=2020 \
41+
+convention=coordinate_frame \
42+
+step +inv +proj=cart +ellps=GRS80 \
43+
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
44+
+step +proj=axisswap +order=2,1
45+
46+
-33.86230294 151.20769882 0.00101330 2026.0000
47+
48+
49+
and the reverse transformation:
50+
51+
::
52+
53+
echo -33.86230294 151.20769882 0.00101330 2026 | cs2cs -d 8 GDA2020 ITRF2014
54+
55+
-33.86230000 151.20770000 0.00000002 2026
56+
57+
Note that in the reverse transformation the epoch is also specified as seemingly
58+
being an input information, whereas it is the target epoch for ITRF2014. This
59+
is an historic PROJ behavior before the introduction of a more generic framework
60+
to deal with coordinate epochs. Since PROJ 9.4, you can also qualify a dynamic
61+
CRS with a coordinate epoch using the syntax "<CRS name>@<epoch>" or "<CRS code>@<epoch>"
62+
63+
For example, re-using above use cases
64+
65+
::
66+
67+
echo -33.8623 151.2077 | cs2cs -d 8 ITRF2014@2026.0 GDA2020
68+
69+
-33.86230294 151.20769882 0.00101330
70+
71+
::
72+
73+
echo -33.86230294 151.20769882 0.00101330 | cs2cs -d 8 EPSG:7844 EPSG:9000@2026.0
74+
75+
-33.86230000 151.20770000 0.00000002
76+
77+
78+
* Point motion operation between two epochs of a dynamic CRS using a velocity grid-based
79+
transformation, with the :ref:`deformation` operator.
80+
81+
For example, to transform coordinates in NAD83(CSRS)v7 CRS from epoch 2010.0 to epoch 2002.0
82+
83+
::
84+
85+
echo 60 -100 0 | PROJ_NETWORK=ON cs2cs -d 8 "NAD83(CSRS)v7 @ 2010.0" "NAD83(CSRS)v7 @ 2002.0"
86+
87+
60.00000011 -100.00000045 -0.06764700
88+
89+
or equivalently using the PROJ pipeline returned by
90+
``projinfo "NAD83(CSRS)v7 @ 2010.0" "NAD83(CSRS)v7 @ 2002.0" --spatial-test intersects``
91+
92+
::
93+
94+
echo 60 -100 0 | PROJ_NETWORK=ON cct -d 8 \
95+
+proj=pipeline \
96+
+step +proj=set +v_4=2010 \
97+
+step +proj=axisswap +order=2,1 \
98+
+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m \
99+
+step +proj=cart +ellps=GRS80 \
100+
+step +proj=set +v_4=2010 +omit_fwd \
101+
+step +proj=deformation +dt=-8 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80 \
102+
+step +proj=set +v_4=2002 +omit_inv \
103+
+step +inv +proj=cart +ellps=GRS80 \
104+
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
105+
+step +proj=axisswap +order=2,1 \
106+
+step +proj=set +v_4=2002
107+
108+
60.00000011 -100.00000045 -0.06764700 2002.0000
109+
110+
111+
* Using a multi-component time-based deformation model with the :ref:`defmodel` operator.
112+
113+
For example, to transform coordinates from ITRF96 at epoch 2026.0 to NZGD2000
114+
115+
::
116+
117+
$ echo -41.2924 174.7787 0 2026 | PROJ_NETWORK=ON cs2cs -d 8 ITRF96 NZGD2000
118+
119+
-41.29240855 174.77870601 0.00000000 2026
120+
121+
or (since PROJ 9.9)
122+
123+
::
124+
125+
$ echo -41.2924 174.7787 0 | PROJ_NETWORK=ON cs2cs -d 8 ITRF96@2026 NZGD2000
126+
127+
-41.29240855 174.77870601 0.00000000
128+
129+
130+
or equivalently using the PROJ pipeline returned by
131+
``projinfo ITRF96@2026 NZGD2000 --spatial-test intersects``
132+
133+
::
134+
135+
echo -41.2924 174.7787 0 | PROJ_NETWORK=ON cct -d 8 \
136+
+proj=pipeline \
137+
+step +proj=axisswap +order=2,1 \
138+
+step +proj=unitconvert +xy_in=deg +xy_out=rad \
139+
+step +proj=set +v_4=2026 \
140+
+step +inv +proj=defmodel +model=nz_linz_nzgd2000-20180701.json \
141+
+step +proj=set +v_4=2026 \
142+
+step +proj=unitconvert +xy_in=rad +xy_out=deg \
143+
+step +proj=axisswap +order=2,1
144+
145+
-41.29240855 174.77870601 0.00000000 2026.0000
146+
147+
148+
Other types of time-dependent transformations are not yet supported when
149+
PROJ must infer the transformation pipelines:
150+
151+
- time-specific Helmert transformations
152+
- transformations between two dynamic CRS at different epochs
153+
- plate motion models (as available in :source_file:`data/ITRF2008`,
154+
:source_file:`data/ITRF2014` and :source_file:`data/ITRF2020`).
155+
156+
157+
Through C API
158+
-------------
159+
160+
Since PROJ 9.9, the most convenient way, that will work with all above mentioned
161+
coordinate operations, is to attach an epoch to a dynamic CRS,
162+
forming a :cpp:class:`osgeo::proj::coordinates::CoordinateMetadata` instance,
163+
either by passing a string of the form "<CRS string> @ <epoch>" to :cpp:func:`proj_create`
164+
or :cpp:func:`proj_create_crs_to_crs`. Or when operating on ``PJ*`` instance, to
165+
use :cpp:func:`proj_coordinate_metadata_create` from an existing CRS instance,
166+
and pass it to :cpp:func:`proj_create_crs_to_crs_from_pj` or :cpp:func:`proj_create_operations`
167+
168+
.. code-block:: c
169+
170+
PJ_CONTEXT *ctxt = proj_context_create();
171+
PJ *transf = proj_create_crs_to_crs(C, "ITRF2014@2026.0", "GDA2020", nullptr);
172+
PROJ_COORD coord;
173+
coord.xyz.y = -33.8623; // latitude in degree
174+
coord.xyz.y = 151.2077; // longitude in degree
175+
coord.xyz.z = 0; // ellipsoidal height in meter
176+
PROJ_COORD coord_in_gda2020 = proj_trans(transf, PJ_FWD, coord);
177+
proj_destroy(transf);
178+
proj_context_destroy(ctxt);
179+
180+
181+
When using the :cpp:func:`proj_create_operations` functionality,
182+
:cpp:func:`proj_coordoperation_requires_per_coordinate_input_time` can be used on
183+
the returned operations to check if they have a time dependency.
184+
185+
Note that with PROJ 9.3 or earlier for 15-parameter Helmert or, PROJ 9.8 or
186+
earlier, for multi-component time-based deformation model transformations, you
187+
must set the epoch in the ``PROJ_COORD::xyzt::t`` or ``PROJ_COORD::v[3]`` member
188+
since CoordinateMetadata is not available.

src/apps/projapps_lib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ typedef void (*projinfo_cb_t)(PJ_PROJINFO_LOG_LEVEL level, const char *msg,
5555
* @param argv list of char* with the command parameters of projinfo.
5656
* It does not contain the program name as first parameter.
5757
* @param cb callback that to get the output of projinfo.
58-
* It can be very fragmented, no necesarily by lines.
58+
* It can be very fragmented, no necessarily by lines.
5959
* @param user_data pointer for data passed to the callback.
6060
*/
6161
int PROJ_DLL projinfo(PJ_CONTEXT *ctx, int argc, char **argv, projinfo_cb_t cb,

src/networkfilemanager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2028,7 +2028,7 @@ static size_t pj_emscripten_read_range(PJ_CONTEXT *ctx,
20282028
// Documentation says compiling with pthread flag is needed.
20292029
// https://emscripten.org/docs/api_reference/fetch.html#synchronous-fetches
20302030
// We encapsulate the code related to empscripten_fetch in a lamda.
2031-
// Some tests runing this lambda in a thread were partially successful.
2031+
// Some tests running this lambda in a thread were partially successful.
20322032
size_t real_read = 0;
20332033
const std::string url = handle->m_url;
20342034
auto fetching = [&]() {

0 commit comments

Comments
 (0)