-
Notifications
You must be signed in to change notification settings - Fork 791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for transformations involving coordinate epoch changes (PointMotionOperation), mostly for Canadian NAD83(CSRS) case #3884
Conversation
…OJJSON, and instanciation from database
…pted/moved from coordinateoperationfactory logic
…inateMetadata to be built for CRS that are not officially dynamic but have a PointMotionOperation
52208e8
to
be5501d
Compare
…nce built from SetFromUserInput() This is useful to get the epoch for a SpatialReference built from a string like 'urn:ogc:def:coordinateMetadata:AUTHORTIY::CODE code' (since OSGeo/gdal#8340 and OSGeo/PROJ#3884), which resolves to a CoordinateMetadata object with a CRS and potentially a coordinate epoch
…etween CoordinateMetadata
…adata transformations
…RS)v7 as interpolation CRS
…reateCoordinateMetadata() method Bump database layout version to 1.3
…ta:AUTH_NAME::CODE syntax
…hen substituting source/target CRS
69a769b
to
47ad6a3
Compare
@rouault impressive work! I haven't had time to give it more than a shallow look at this point but I look forward to go over the PR properly when I have a bit more time on my hands. |
…nce built from SetFromUserInput() This is useful to get the epoch for a SpatialReference built from a string like 'urn:ogc:def:coordinateMetadata:AUTHORTIY::CODE code' (since OSGeo/gdal#8340 and OSGeo/PROJ#3884), which resolves to a CoordinateMetadata object with a CRS and potentially a coordinate epoch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell this is solid. I did stop for a second when I noticed that the coordinate epochs (4th component) were deliberately overwritten by some of the pipelines but as far as I understand that is how point motion operations are supposed to work.
When I did the time-varying Helmert implementations I decided on not changing the coordinate epochs since it's difficult to transform your coordinates back to where they came from, but having both options available is good. Depending on the use case on can be preferable over the other.
For a transformation like "NAD83(CSRS)v7 @ 2005.0" to "ITRF2014 @ 2020.0", you need to do first a point motion operation within NAD83(CSRS)v7 to go from 2005 to 2020, and then apply the time-dependent Helmert transformation from NAD83(CSRS)v7 to ITRF2014 at epoch 2020. So the point motion operation has to set the epoch to 2020 after it has completed. |
I guess that is a matter of taste. The NKG-transformations are quite similar to the examples in this PR, as far as I can tell. In those transformations we keep the original epoch of the coordinate. A difference might be that the pipelines are hand-written which may make things simpler. I can see how a more generic approach benefits from the coordinate epochs changing. In the end what matters is how the Canadians have defined their transformations - if they have specified that epochs should change then that is how it should be implemented :-) |
…mation method (e.g for NAD83(CSRS)v7 to NAD83(CSRS)v3)
…: use candidateSrcGeod and candidateDstGeod of same type in priority
…e vertical CRS has a geoid model
…2010_UTMyy_CGVD2013_2010
…CSRS_1997_yyyy_CGVD2013_1997' or 'NAD83_CSRS_2002_xxxx_HT2_2002 to NAD83_CSRS_2002_yyyy_CGVD2013_2002'
…s, i.e. when the point motion operation is on the end, and also make sure that the time-dependent Helmert transformation receives coordinates in the right epoch
… the sign of the value of the grid
2ce37db
to
bee4a90
Compare
…nce built from SetFromUserInput() This is useful to get the epoch for a SpatialReference built from a string like 'urn:ogc:def:coordinateMetadata:AUTHORTIY::CODE code' (since OSGeo/gdal#8340 and OSGeo/PROJ#3884), which resolves to a CoordinateMetadata object with a CRS and potentially a coordinate epoch
* SpatialReference::set(): store coordinate epoch from OGRSpatialReference built from SetFromUserInput() This is useful to get the epoch for a SpatialReference built from a string like 'urn:ogc:def:coordinateMetadata:AUTHORTIY::CODE code' (since OSGeo/gdal#8340 and OSGeo/PROJ#3884), which resolves to a CoordinateMetadata object with a CRS and potentially a coordinate epoch * SrsTransform: make sure to propagate coordinate epoch when rebuilding OGRSpatialReference objects * SpatialReference: add a m_wkt2 member filled in set() and returned by getWKT2() * SrsTransform: use SpatialReference::getWKT2() This limits the loss of information, particularly for CRS like 'urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_1997_MTM7_HT2_1997' which include a GEOIDMODEL[] node, that would be lost otherwise * SpatialReference::isWKT2(): add missing keywords, and fix typo VERITCALCRS -> VERTICALCRS
Summary
This pull request contains API, utility and database enhancements to better support dynamic CRS, PointMotionOperation and CoordinateMetadata concepts. All those changes address mostly changes of epoch within the same dynamic CRS, typically NAD83(CSRS)v7 using the NAD83v70VG grid.
"CRS A @ epoch X" to "CRS B @ epoch Y" is implemented, for geodetic CRS, currently by doing "CRS A @ epoch X" -> "CRS A @ epoch Y" -> "CRS B @ epoch Y".
Note: time-specific Helmert, which might be needed in some situations, is not implemented
Detailed contents
Improvements done that can be useful in other contexts:
Tests
Note: all the needed grids are already in PROJ-data (NAD83v70VG, HT2_1997/2002/2010 geoid grids for CGVD28 height, CGG2013an83 geoid grid for CGVD2013a(1997/2002/2010) height, and HT2_xxxx_CGG2013a grids for CGVD28 to CGVD2013a heights
1. Change of epoch on geographic coordinates on NAD83(CSRS)v7 using velocity grid NAD83v70VG
$ bin/projinfo -s "NAD83(CSRS)v7" --s_epoch 2010 -t "NAD83(CSRS)v7" --t_epoch 2002
+proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=2010 +omit_fwd
+step +proj=deformation +dt=-8 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2002 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +proj=unitconvert +xy_in=rad +xy_out=deg
+step +proj=axisswap +order=2,1
$ echo 60 -100 0 | PROJ_NETWORK=ON bin/cct -d 8 +proj=pipeline
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=2010 +omit_fwd
+step +proj=deformation +dt=-8 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2002 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +proj=unitconvert +xy_in=rad +xy_out=deg
+step +proj=axisswap +order=2,1
60.00000011 -100.00000045 -0.06764700 2002.0000
$ echo 60 -100 0 | PROJ_NETWORK=ON bin/cs2cs -d 8 "NAD83(CSRS)v7 @ 2010.0" "NAD83(CSRS)v7 @ 2002.0"
60.00000011 -100.00000045 -0.06764700
Matches results of the official TRX tool (https://webapp.csrs-scrs.nrcan-rncan.gc.ca/geod/tools-outils/trx.php?locale=fr):
2. Another instance
$ echo 45.42936526 -75.70165558 39.524 | PROJ_NETWORK=ON PROJ_DATA=data bin/cs2cs -d 8 "NAD83(CSRS)v7 @ 1997" "NAD83(CSRS)v7 @ 2010"
45.42936503 -75.70165526 39.55114382
Matches results of the official TRX tool (https://webapp.csrs-scrs.nrcan-rncan.gc.ca/geod/tools-outils/trx.php?locale=fr):
3. CompoundCRS to CompoundCRS: MTM projection + CGVD28 height @ 1997 to UTM projection + CGVD2013a(2010) height @ 2010
==> Chains HT2_1997, NAD83v70VG and CGG2013an83
$ bin/projinfo -s urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_1997_MTM7_HT2_1997 -t urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM19_CGVD2013_2010 --single-line
+proj=pipeline
+step +inv +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 +x_0=304800 +y_0=0
+ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_HT2_1997.tif +multiplier=1
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=1997 +omit_fwd
+step +proj=deformation +dt=13 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2010 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +inv +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=utm +zone=19 +ellps=GRS80
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cct -d 3 +proj=pipeline
+step +inv +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 +x_0=304800 +y_0=0
+ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_HT2_1997.tif +multiplier=1
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=1997 +omit_fwd
+step +proj=deformation +dt=13 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2010 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +inv +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=utm +zone=19 +ellps=GRS80
356670.104 5540546.584 -0.306 2010.0000
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cs2cs -d 3 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_1997_MTM7_HT2_1997 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM19_CGVD2013_2010
356670.104 5540546.584 -0.306
4. CompoundCRS to CompoundCRS: UTM projection + CGVD2013a(2002) height @ 2002 to UTM projection + CGVD2013a(2010) height @ 2010
==> Chains CGG2013an83, NAD83v70VG and CGG2013an83
$ bin/projinfo -s urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2002_UTM17_CGVD2013_2002 -t urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM17_CGVD2013_2010
+proj=pipeline
+step +inv +proj=utm +zone=17 +ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=2002 +omit_fwd
+step +proj=deformation +dt=8 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2010 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +inv +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=utm +zone=17 +ellps=GRS80
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cct -d 3 +proj=pipeline
+step +inv +proj=utm +zone=17 +ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=2002 +omit_fwd
+step +proj=deformation +dt=8 +grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2010 +omit_inv
+step +inv +proj=cart +ellps=GRS80
+step +inv +proj=vgridshift +grids=ca_nrc_CGG2013an83.tif +multiplier=1
+step +proj=utm +zone=17 +ellps=GRS80
268955.015 5540411.986 0.047 2010.0000
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cs2cs -d 3 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2002_UTM17_CGVD2013_2002 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM17_CGVD2013_2010
268955.015 5540411.986 0.047
5. CompoundCRS to CompoundCRS: UTM projection + CGVD28 height @ 2010 to UTM projection + CGVD2013a(2010) height @ 2010
==> Uses HT2_2010v70_CGG2013a grid
$ bin/projinfo -s urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_MTM7_HT2_2010 -t urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM19_CGVD2013_2010
+proj=pipeline
+step +inv +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 +x_0=304800 +y_0=0
+ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_HT2_2010v70_CGG2013a.tif +multiplier=-1
+step +proj=utm +zone=19 +ellps=GRS80
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cct -d 3
+proj=pipeline
+step +inv +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 +x_0=304800 +y_0=0
+ellps=GRS80
+step +proj=vgridshift +grids=ca_nrc_HT2_2010v70_CGG2013a.tif +multiplier=-1
+step +proj=utm +zone=19 +ellps=GRS80
356670.074 5540546.618 -0.306 inf
$ echo 268955 5540412 0 | PROJ_NETWORK=ON bin/cs2cs -d 3 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_MTM7_HT2_2010 urn:ogc:def:coordinateMetadata:NRCAN::NAD83_CSRS_2010_UTM19_CGVD2013_2010
356670.074 5540546.618 -0.306
6. Change of epoch on geographic coordinates between NAD83(CSRS)v7 and ITRF2014 using velocity grid NAD83v70VG and time-dependent Helmert transformation
$ bin/projinfo -s "NAD83(CSRS)v7 @ 2005.0" -t "ITRF2014 @ 2020.0"
+proj=pipeline
+step +proj=set +v_4=2005
+step +proj=axisswap +order=2,1
+step +proj=unitconvert +xy_in=deg +z_in=m +xy_out=rad +z_out=m
+step +proj=cart +ellps=GRS80
+step +proj=set +v_4=2005 +omit_fwd
+step +proj=deformation +dt=15+grids=ca_nrc_NAD83v70VG.tif +ellps=GRS80
+step +proj=set +v_4=2020 +omit_inv
+step +inv +proj=helmert +x=1.0053 +y=-1.90921 +z=-0.54157 +rx=-0.02678138
+ry=0.00042027 +rz=-0.01093206 +s=0.00036891 +dx=0.00079 +dy=-0.0006
+dz=-0.00144 +drx=-6.667e-05 +dry=0.00075744 +drz=5.133e-05
+ds=-7.201e-05 +t_epoch=2010 +convention=position_vector
+step +inv +proj=cart +ellps=GRS80
+step +proj=unitconvert +xy_in=rad +xy_out=deg
+step +proj=axisswap +order=2,1
+step +proj=set +v_4=2020
$ echo 60 -100 0 | PROJ_NETWORK=ON bin/cs2cs -d 8 "NAD83(CSRS)v7 @ 2005.0" "ITRF2014 @ 2020.0"
60.00000772 -100.00002159 -0.24708346
Matches TRX:
Funded by Natural Resources Canada