diff --git a/src/iso19111/operation/singleoperation.cpp b/src/iso19111/operation/singleoperation.cpp index 9141679f27..928ee6021a 100644 --- a/src/iso19111/operation/singleoperation.cpp +++ b/src/iso19111/operation/singleoperation.cpp @@ -2187,12 +2187,20 @@ createSimilarPropertiesMethod(common::IdentifiedObjectNNPtr obj) { // --------------------------------------------------------------------------- -static bool isRegularVerticalGridMethod(int methodEPSGCode) { +static bool isRegularVerticalGridMethod(int methodEPSGCode, + bool &reverseOffsetSign) { + if (methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_NRCAN_BYN) { + // NRCAN vertical shift grids use a reverse convention from other + // grids: the value in the grid is the value to subtract from the + // source vertical CRS to get the target value. + reverseOffsetSign = true; + return true; + } + reverseOffsetSign = false; return methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_NZLVD || methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_BEV_AT || methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_GTX || - methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_PL_TXT || - methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_NRCAN_BYN; + methodEPSGCode == EPSG_CODE_METHOD_VERTICALGRID_PL_TXT; } // --------------------------------------------------------------------------- @@ -2477,8 +2485,9 @@ TransformationNNPtr SingleOperation::substitutePROJAlternativeGridNames( } } + bool reverseOffsetSign = false; if (methodEPSGCode == EPSG_CODE_METHOD_VERTCON || - isRegularVerticalGridMethod(methodEPSGCode)) { + isRegularVerticalGridMethod(methodEPSGCode, reverseOffsetSign)) { auto fileParameter = parameterValue(EPSG_NAME_PARAMETER_VERTICAL_OFFSET_FILE, EPSG_CODE_PARAMETER_VERTICAL_OFFSET_FILE); @@ -4146,7 +4155,8 @@ bool SingleOperation::exportToPROJStringGeneric( } } - if (isRegularVerticalGridMethod(methodEPSGCode)) { + bool reverseOffsetSign = false; + if (isRegularVerticalGridMethod(methodEPSGCode, reverseOffsetSign)) { auto fileParameter = parameterValue(EPSG_NAME_PARAMETER_VERTICAL_OFFSET_FILE, EPSG_CODE_PARAMETER_VERTICAL_OFFSET_FILE); @@ -4154,7 +4164,7 @@ bool SingleOperation::exportToPROJStringGeneric( fileParameter->type() == ParameterValue::Type::FILENAME) { formatter->addStep("vgridshift"); formatter->addParam("grids", fileParameter->valueFile()); - formatter->addParam("multiplier", 1.0); + formatter->addParam("multiplier", reverseOffsetSign ? -1.0 : 1.0); return true; } } diff --git a/test/unit/test_operationfactory.cpp b/test/unit/test_operationfactory.cpp index 144a01d652..09865b35ff 100644 --- a/test/unit/test_operationfactory.cpp +++ b/test/unit/test_operationfactory.cpp @@ -9698,7 +9698,7 @@ TEST(operation, "+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_CGG2013a.tif " - "+multiplier=1 " + "+multiplier=-1 " "+step +proj=utm +zone=19 +ellps=GRS80"); } { @@ -9712,7 +9712,7 @@ TEST(operation, "+step +inv +proj=utm +zone=19 +ellps=GRS80 " "+step +inv +proj=vgridshift " "+grids=ca_nrc_HT2_1997_CGG2013a.tif " - "+multiplier=1 " + "+multiplier=-1 " "+step +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 " "+x_0=304800 +y_0=0 +ellps=GRS80"); } @@ -9746,7 +9746,7 @@ TEST(operation, "+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_2002v70_CGG2013a.tif " - "+multiplier=1 " + "+multiplier=-1 " "+step +proj=utm +zone=19 +ellps=GRS80"); } { @@ -9760,7 +9760,7 @@ TEST(operation, "+step +inv +proj=utm +zone=19 +ellps=GRS80 " "+step +inv +proj=vgridshift " "+grids=ca_nrc_HT2_2002v70_CGG2013a.tif " - "+multiplier=1 " + "+multiplier=-1 " "+step +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 " "+x_0=304800 +y_0=0 +ellps=GRS80"); } @@ -9794,7 +9794,7 @@ TEST(operation, "+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 " + "+multiplier=-1 " "+step +proj=utm +zone=19 +ellps=GRS80"); } { @@ -9808,7 +9808,7 @@ TEST(operation, "+step +inv +proj=utm +zone=19 +ellps=GRS80 " "+step +inv +proj=vgridshift " "+grids=ca_nrc_HT2_2010v70_CGG2013a.tif " - "+multiplier=1 " + "+multiplier=-1 " "+step +proj=tmerc +lat_0=0 +lon_0=-70.5 +k=0.9999 " "+x_0=304800 +y_0=0 +ellps=GRS80"); }