Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

rouault
Copy link
Member

@rouault rouault commented Aug 26, 2025

CC @kbevers @phakli I presume one or both of you have been involved in the batch of NKG related records in the latest EPSG update. The import of it into the PROJ database does not include yet the below new transformations because they rely on a new method 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)' which isn't mapped yet in PROJ:

(10809, 'transformation', 'ETRF2014 to NKG_ETRF14 (1)', 1144, 'Geocentric translations using NEU velocity grid (gtg)', 8401, 10805, 0.003, 0)
(10810, 'transformation', 'NKG_ETRF14 to EUREF-FIN (1)', 1143, 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)', 10805, 10688, 0.002, 0)
(10811, 'transformation', 'NKG_ETRF14 to ETRS89-NOR [EUREF89] (1)', 1142, 'Geocen translations by grid (gtg) & Geocen translations NEU velocities (gtg)', 10805, 10873, 0.005, 0)
(10812, 'transformation', 'NKG_ETRF14 to LKS94 (1)', 1143, 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)', 10805, 4950, 0.008, 0)
(10813, 'transformation', 'NKG_ETRF14 to SWEREF99 (1)', 1143, 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)', 10805, 4976, 0.001, 0)
(10814, 'transformation', 'NKG_ETRF14 to EST97 (1)', 1143, 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)', 10805, 4934, 0.002, 0)
(10815, 'concatenated operation', 'ITRF2014 to NKG_ETRF14 (1)', None, None, 7789, 10805, 0.001, 0)
(10816, 'concatenated operation', 'ITRF2014 to EUREF-FIN (1)', None, None, 7789, 10688, 0.004, 0)
(10817, 'concatenated operation', 'ITRF2014 to ETRS89-NOR [EUREF89] (1)', None, None, 7789, 10873, 0.006, 0)
(10818, 'concatenated operation', 'ITRF2014 to LKS94 (1)', None, None, 7789, 4950, 0.013, 0)
(10824, 'concatenated operation', 'ITRF2014 to SWEREF99 (1)', None, None, 7789, 4976, 0.004, 0)
(10825, 'concatenated operation', 'ITRF2014 to EST97 (1)', None, None, 7789, 4934, 0.005, 0)
(10868, 'concatenated operation', 'ITRF2020 to EST97 (1)', None, None, 9988, 4934, 0.005, 0)
(10869, 'concatenated operation', 'ITRF2020 to EUREF-FIN (1)', None, None, 9988, 10688, 0.004, 0)
(10870, 'concatenated operation', 'ITRF2020 to ETRS89-NOR [EUREF89] (1)', None, None, 9988, 10873, 0.006, 0)
(10871, 'concatenated operation', 'ITRF2020 to LKS94 (1)', None, None, 9988, 4950, 0.013, 0)
(10872, 'concatenated operation', 'ITRF2020 to SWEREF99 (1)', None, None, 9988, 4976, 0.004, 0)
(10893, 'transformation', 'NKG_ETRF14 to ETRS89-DNK (1)', 1143, 'Position Vector (geocen) & Geocen translations NEU velocities (gtg)', 10805, 10890, 0.001, 0)
(10894, 'concatenated operation', 'ITRF2014 to ETRS89-DNK (1)', None, None, 7789, 10890, 0.006, 0)
(10895, 'concatenated operation', 'ITRF2020 to ETRS89-DNK (1)', None, None, 9988, 10890, 0.006, 0)

comparing that to the current nkg.sql, I presume this is the concatenation of a Helmert + deformation, but without using an explicit intermediate CRS. There's however a possible subtle difference. For example, for the https://epsg.org/transformation_10814/NKG_ETRF14-to-EST97-1.html transformation, EPSG records NKG_ETRF14 as the interpolation CRS for the grid interpolation, that is the initial CRS. But in NKG:ETRF14_TO_EE the interplation is done after the Helmert transformation. Maybe doing the grid interpolation before or after the Helmert transformation has little consequence on the final value, or maybe it has not?

Otherwise, the other currently only record I've mapped is the point motion model within ETRF2014. Could you confirm if the below test transformation is correct? (looks plausible to me for an uplift deformation)
$ echo 60 20 0 | PROJ_DATA=data PROJ_NETWORK=ON bin/cs2cs -d 8 "ETRF2014@2020" "ETRF2014@2025" --3d
59.99999996 20.00000000 0.03128600

@rouault rouault added this to the 9.7.0 milestone Aug 26, 2025
@rouault rouault added the funded through GSP Work funded through the GDAL Sponsorship Program label Aug 26, 2025
@kbevers
Copy link
Member

kbevers commented Aug 28, 2025

I presume this is the concatenation of a Helmert + deformation, but without using an explicit intermediate CRS

That's the idea, yes.

But in NKG:ETRF14_TO_EE the interplation is done after the Helmert transformation. Maybe doing the grid interpolation before or after the Helmert transformation has little consequence on the final value, or maybe it has not?

I believe in the end this should replicate the current nkg.sql implementation:

PROJ/data/sql/nkg.sql

Lines 1810 to 1817 in ff43c46

INSERT INTO "concatenated_operation_step" (
operation_auth_name, operation_code, step_number, step_auth_name, step_code, step_direction
) VALUES
('NKG', 'ITRF2014_TO_EE', 1, 'EPSG', '8366', 'forward'), -- ITRF2014 -> ETRF2014
('NKG', 'ITRF2014_TO_EE', 2, 'NKG', 'NKG_ETRF14_TO_ETRF2014', 'reverse'),
('NKG', 'ITRF2014_TO_EE', 3, 'NKG', 'PAR_2020_EE', 'forward'),
('NKG', 'ITRF2014_TO_EE', 4, 'NKG', 'EE_2020_INTRAPLATE', 'forward')
;

I think it's difficult to get the metadata of the deformation model correct. Technically it is aligned to NKG_ETRF14 but it is (also) used in conjunction with the different national realizations of ETRS89. From a data modelling viewpoint it might have been better to simple say the interpolation CRS is ETRS89. In practice it works because the differences between the realizations are very small. In conclusion, I don't think there's a problem here.

@phakli
Copy link

phakli commented Aug 28, 2025

Yes, as @kbevers pointed out, any ETRS89 realization as the interpolation CRS is ok because the velocity model is so smooth (even much bigger differences in input coordinates will still give the same result with significant digits). This is also mentioned in the remarks of the EPSG:10808 (https://epsg.org/point-motion-operation_10808/NKG-land-uplift-deformation-model-NKG_RF17vel.html).

@rouault, yes I can confirm the results from your test transformation (in the height I get 0.03128500 but that's probably rounding error somewhere and anyway not significant)

@rouault
Copy link
Member Author

rouault commented Aug 28, 2025

I've added a commit that maps the 3 new EPSG methods used by NKG transformations: "Position Vector (geocen) & Geocen translations NEU velocities (gtg)", "Geocentric translations using NEU velocity grid (gtg)" and "Geocen translations by grid (gtg) & Geocen translations NEU velocities (gtg)"

Quick check shows that it seems to be consistent with nkg.sql records, but could receive more testing...

# Tests "Position Vector (geocen) & Geocen translations NEU velocities (gtg)"

$ echo 3140996.6730 596336.8511 5500477.1338 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct NKG:ETRF14_TO_FI
 3140996.7242    596336.8904  5500477.0896     inf
$ echo 3140996.6730 596336.8511 5500477.1338 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct EPSG:10810
 3140996.7242    596336.8904  5500477.0896     inf

$ echo 3140996.7242 596336.8904 5500477.0896 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I NKG:ETRF14_TO_FI
 3140996.6730    596336.8511  5500477.1338     inf
$ echo 3140996.7242 596336.8904 5500477.0896 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I EPSG:10810
 3140996.6730    596336.8511  5500477.1338     inf

# Tests "Geocentric translations using NEU velocity grid (gtg)" and "Geocen translations by grid (gtg) & Geocen translations NEU velocities (gtg)"

$ echo 3140996.6730 596336.8511 5500477.1338 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct NKG:ITRF2014_TO_NO
 3140997.2140    596336.4062  5500476.6768     2025.0000
$ echo 3140996.6730 596336.8511 5500477.1338 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct EPSG:10817
 3140997.2140    596336.4062  5500476.6768     2025.0000

$ echo 3140997.2140 596336.4062 5500476.6768 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I NKG:ITRF2014_TO_NO
 3140996.6730    596336.8511  5500477.1338     2025.0000
$ echo 3140997.2140 596336.4062 5500476.6768 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I EPSG:10817
 3140996.6730    596336.8511  5500477.1338     2025.0000

@kbevers
Copy link
Member

kbevers commented Aug 29, 2025

Thanks, Even! I'll try to run some tests as soon as possible. Likely it'll be on Monday.

@phakli
Copy link

phakli commented Aug 29, 2025

Thanks a lot Even and Kristian!

@phakli
Copy link

phakli commented Aug 29, 2025

@rouault, just to let you know (or maybe this was found by you?), I just heard that there is a mistake in the parameters of the Danish NKG2020 transformation (in EPSG:10893). There will be a fix in the very near future.

…1.6)

Demo
```
 # Tests "Position Vector (geocen) & Geocen translations NEU velocities (gtg)"

$ echo 3140996.6730 596336.8511 5500477.1338 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct NKG:ETRF14_TO_FI
 3140996.7242    596336.8904  5500477.0896     inf
$ echo 3140996.6730 596336.8511 5500477.1338 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct EPSG:10810
 3140996.7242    596336.8904  5500477.0896     inf

$ echo 3140996.7242 596336.8904 5500477.0896 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I NKG:ETRF14_TO_FI
 3140996.6730    596336.8511  5500477.1338     inf
$ echo 3140996.7242 596336.8904 5500477.0896 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I EPSG:10810
 3140996.6730    596336.8511  5500477.1338     inf

 # Tests "Geocentric translations using NEU velocity grid (gtg)" and "Geocen translations by grid (gtg) & Geocen translations NEU velocities (gtg)"

$ echo 3140996.6730 596336.8511 5500477.1338 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct NKG:ITRF2014_TO_NO
 3140997.2140    596336.4062  5500476.6768     2025.0000
$ echo 3140996.6730 596336.8511 5500477.1338 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct EPSG:10817
 3140997.2140    596336.4062  5500476.6768     2025.0000

$ echo 3140997.2140 596336.4062 5500476.6768 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I NKG:ITRF2014_TO_NO
 3140996.6730    596336.8511  5500477.1338     2025.0000
$ echo 3140997.2140 596336.4062 5500476.6768 2025 | PROJ_NETWORK=ON PROJ_DATA=data bin/cct -I EPSG:10817
 3140996.6730    596336.8511  5500477.1338     2025.0000
```
@rouault
Copy link
Member Author

rouault commented Aug 29, 2025

just to let you know (or maybe this was found by you?)

yes I warned EPSG about that. This PR includes a workaround to fix the wrong values.

Regarding the "Geocentric translations using NEU velocity grid (gtg)" method used by EPSG:10809 ""ETRF2014 to NKG_ETRF14 (1)"", I've noticed that this transformation is in the reverse direction than NKG:NKG_ETRF14_TO_ETRF2014 , consequently to get the same results as that later operation, I've mapped it to "+proj=pipeline +step +inv +proj=deformation +t_epoch=2000 +grids=eur_nkg_nkgrf17vel.tif +ellps=GRS80". So we map the forward direction of the EPSG method to the reverse direction of the correspondig PROJ operation. Not a big deal, but just wanted to mention it.

@rouault rouault changed the title Database: update to EPSG v12.021 Database: update to EPSG v12.022 Aug 30, 2025
@rouault
Copy link
Member Author

rouault commented Aug 30, 2025

I've added a commit that integrates EPSG v12.022, which contains in particular the fix for operation EPSG:10893 and typo fixes in grid file names
This updates also includes a Href_Svalbard_EUREF89_EGG2015_2024.bin grid for 'ETRS89-NOR [EUREF89] to ETRS89-NOR [EUREF89] + SVD2024 height (1)' . @himsve Do you intend to add it into PROJ-data ?

@himsve
Copy link
Contributor

himsve commented Sep 1, 2025

@rouault Yes, I will. :-)

@kbevers
Copy link
Member

kbevers commented Sep 1, 2025

@himsve, it would be preferable if you can do it before the weekend. I'll prepare the next releases early next week and it would be good to have your additions included.

@kbevers
Copy link
Member

kbevers commented Sep 1, 2025

I've tried to compare the current nkg.sql implementation with the new in EPSG.
In my initial findings it seems there's a slight difference in Helmert parameters
between the two. If we first look at the old implementation, we see that only the
rotation rate parameters are set in the initial step. Addtionally +t_epoch is
set to 1989.

$ PROJ_DATA=./data/ ./bin/projinfo -k operation NKG:ITRF2014_TO_DK -o PROJ
PROJ string:
+proj=pipeline
  +step +proj=helmert +x=0 +y=0 +z=0 +rx=0 +ry=0 +rz=0 +s=0 +dx=0 +dy=0 +dz=0
        +drx=8.5e-05 +dry=0.000531 +drz=-0.00077 +ds=0 +t_epoch=1989
        +convention=position_vector
  +step +inv +proj=deformation +t_epoch=2000.0 +grids=eur_nkg_nkgrf17vel.tif
  +step +proj=helmert +x=0.66818 +y=0.04453 +z=-0.45049 +rx=0.00312883
        +ry=-0.02373423 +rz=0.00442969 +s=-0.003136 +convention=position_vector
  +step +proj=deformation +dt=15.829 +grids=eur_nkg_nkgrf17vel.tif

The EPSG equivalent has the same rotation rate parameters but also includes
translations. The epoch is now 2010. Note also that projinfo can't locate
NKG_RF17vel.tif:

$ PROJ_DATA=./data/ ./bin/projinfo -s EPSG:7789 -t EPSG:10890 -o PROJ
Candidate operations found: 2
-------------------------------------
Operation No. 1:

EPSG:10894, ITRF2014 to ETRS89-DNK (1), 0.006 m, Denmark - onshore and offshore., at least one grid missing, time-dependent operation

PROJ string:
+proj=pipeline
  +step +proj=helmert +x=0 +y=0 +z=0 +rx=0.001785 +ry=0.011151 +rz=-0.01617 +s=0
        +dx=0 +dy=0 +dz=0 +drx=8.5e-05 +dry=0.000531 +drz=-0.00077 +ds=0
        +t_epoch=2010 +convention=position_vector
  +step +inv +proj=deformation +t_epoch=2000 +grids=eur_nkg_nkgrf17vel.tif
        +ellps=GRS80
  +step +proj=helmert +x=0.66818 +y=0.04453 +z=-0.45049 +rx=0.00312883
        +ry=-0.02373423 +rz=0.00442969 +s=-0.003136 +convention=position_vector
  +step +proj=deformation +dt=15.829 +grids=eur_nkg_nkgrf17vel.tif +ellps=GRS80

Grid NKG_RF17vel.tif needed but not found on the system.

-------------------------------------
Operation No. 2:

unknown id, Ballpark geocentric translation from ITRF2014 to ETRS89-DNK, unknown accuracy, World, has ballpark transformation

PROJ string:
+proj=noop

In the above output the final +proj=deformation step includes +ellps=GRS80
which I don't believe have any effect.

Trying an actual transformation using cs2cs fails because NKG_RF17vel.tif is not located. See below.
I assume a grid alternative is missing.

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DEBUG=2 PROJ_DATA=./data/ ./bin/cs2c
s  -d 4 EPSG:7789 EPSG:10890
pj_open_lib(proj.ini): call fopen(./data//proj.ini) - succeeded
pj_open_lib(proj.db): call fopen(./data//proj.db) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/e012349/.local/share/proj/eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(NKG_RF17vel.tif): call fopen(./data//NKG_RF17vel.tif) - failed
3496736.2286    743254.2298 5264461.3868 2025.52

The output is the same as the input. Obviously not what we want. The equivalent from
nkg.sql does not fail:

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DEBUG=2 PROJ_DATA=./data/ ./bin/cct
NKG:ITRF2014_TO_DK
pj_open_lib(proj.ini): call fopen(./data//proj.ini) - succeeded
pj_open_lib(proj.db): call fopen(./data//proj.db) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/e012349/.local/share/proj/eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/e012349/.local/share/proj/eur_nkg_nkgrf17vel.tif) - succeeded
 3496736.8491    743253.7135  5264461.0077     2025.5200

@rouault
Copy link
Member Author

rouault commented Sep 1, 2025

@kbevers I've just added a commit that fixes the issue with the lack of substitution of NKG_RF17vel.tif . Now I get exactly the same results when using the EPSG or NKG pipelines:

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DEBUG=2 PROJ_DATA=./data/:/home/even/proj/PROJ-data/eur_nkg/ ./bin/cs2cs  -d 4 EPSG:7789 EPSG:10890
pj_open_lib(proj.ini): call fopen(./data//proj.ini) - succeeded
pj_open_lib(proj.db): call fopen(./data//proj.db) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
Using coordinate operation ITRF2014 to ETRS89-DNK (1)
3496736.8491	743253.7135 5264461.0077 2025.52

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DEBUG=2 PROJ_DATA=./data/:/home/even/proj/PROJ-data/eur_nkg/  ./bin/cct NKG:ITRF2014_TO_DK
pj_open_lib(proj.ini): call fopen(./data//proj.ini) - succeeded
pj_open_lib(proj.db): call fopen(./data//proj.db) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
pj_open_lib(eur_nkg_nkgrf17vel.tif): call fopen(/home/even/proj/PROJ-data/eur_nkg//eur_nkg_nkgrf17vel.tif) - succeeded
 3496736.8491    743253.7135  5264461.0077     2025.5200

The pipelines are not the same, but are equivalent. For ITRF2014 to ETRF2014 , EPSG uses "ITRF2014 to ETRF2014 (2)" with a pivot epoch of 2010, whereas the NKG one uses "ITRF2014 to ETRF2014 (1)" with a pivot epoch of 1989.0. But both use the same translation and rotation rate, and the difference in static terms is just the rates times the diference of epoch. For example for +rx=0.001785 in "ITRF2014 to ETRF2014 (2)" : this is equal to drx * (2010 -1989) = 8.5e-5 * (2010 -1989) = 0.001785 . So both transformations are effectively equivalent. Comment of "ITRF2014 to ETRF2014 (1)" mentions "See ITRF2014 to ETRF2014 (2) (code 8880) for an exactly equivalent transformation but with the transformation's parameter values at epoch 2010.00"

@rouault
Copy link
Member Author

rouault commented Sep 1, 2025

In the above output the final +proj=deformation step includes +ellps=GRS80
which I don't believe have any effect.

It actually has a (small) effect since deformation does a inverse cart to transform geocentric coordinates to geographic ones, to be able to fetch the grid point. But in practice, you need to define a very different ellipsoid than the default one (GRS80) to see an effect:

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DATA=./data/:/home/even/proj/PROJ-data/eur_nkg/  ./bin/cct +proj=deformation +dt=15.829 +grids=eur_nkg_nkgrf17vel.tif +ellps=GRS80
 3496736.2470    743254.2263  5264461.4001     2025.5200

vs

$ echo 3496736.2286    743254.2298  5264461.3868 2025.52 | PROJ_DATA=./data/:/home/even/proj/PROJ-data/eur_nkg/  ./bin/cct +proj=deformation +dt=15.829 +grids=eur_nkg_nkgrf17vel.tif +a=1 +rf=1.5
 3496736.2454    743254.2262  5264461.3983     2025.5200

@kbevers
Copy link
Member

kbevers commented Sep 2, 2025

Now I get exactly the same results when using the EPSG or NKG pipelines

So do I. Thanks!

It actually has a (small) effect since deformation does a inverse cart to transform geocentric coordinates to geographic ones, to be able to fetch the grid point.

Oh yeah, of course. I really should know this since I implemented the darn thing in the first place :) I guess +ellps=GRS80 is implied when it's missing.

@rouault rouault merged commit 080fd7a into OSGeo:master Sep 2, 2025
28 checks passed
@himsve
Copy link
Contributor

himsve commented Sep 5, 2025

You will find the related PR in OSGeo/PROJ-data#146.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

funded through GSP Work funded through the GDAL Sponsorship Program

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants