Repository: OSGeo/PROJ (C++)

Issue:
COMPOUNDCRS with BOUNDCRS fails to apply ABRIDGEDTRANSFORMATION
When a BOUNDCRS is included in a COMPOUNDCRS, the ABRIDGEDTRANSFORMATION is not included in the generated transform if the target CRS is a COMPOUNDCRS, even if the BASEGEOGCRS matches. However, if the target CRS is a regular PROJCRS the ABRIDGEDTRANSFORMATION works as expected.


#### Partially working case:
For example, consider this source CRS:

```
COMPOUNDCRS["AGD66 / AMG zone 55 + AHD height",
    BOUNDCRS[
        SOURCECRS[
            PROJCRS["AGD66 / AMG zone 55 + AHD height",
                BASEGEOGCRS["AGD66",
                    DATUM["User datum (no grid)",
                        ELLIPSOID["Australian National Spheroid",6378160,298.25,
                            LENGTHUNIT["metre",1]]],
                    PRIMEM["Greenwich",0,
                        ANGLEUNIT["degree",0.0174532925199433]]],
                CONVERSION["Australian Map Grid zone 55",
                    METHOD["Transverse Mercator"],
                    PARAMETER["Latitude of natural origin",0,
                        ANGLEUNIT["degree",0.0174532925199433]],
                    PARAMETER["Longitude of natural origin",147,
                        ANGLEUNIT["degree",0.0174532925199433]],
                    PARAMETER["Scale factor at natural origin",0.9996,
                        SCALEUNIT["unity",1]],
                    PARAMETER["False easting",500000,
                        LENGTHUNIT["metre",1]],
                    PARAMETER["False northing",10000000,
                        LENGTHUNIT["metre",1]]],
                CS[Cartesian,2],
                    AXIS["(E)",east,
                        ORDER[1],
                        LENGTHUNIT["metre",1]],
                    AXIS["(N)",north,
                        ORDER[2],
                        LENGTHUNIT["metre",1]],
                USAGE[
                    SCOPE["Engineering survey, topographic mapping."],
                    AREA["Australia - onshore and offshore between 144°E and 150°E. Papua New Guinea (PNG) - onshore between 144°E and 150°E."],
                    BBOX[-47.2,144,-1.3,150.01]]]],
        TARGETCRS[
            GEOGCRS["GDA2020",
                DATUM["Geocentric Datum of Australia 2020",
                    ELLIPSOID["GRS 1980",6378137,298.257222101,
                        LENGTHUNIT["metre",1]]],
                PRIMEM["Greenwich",0,
                    ANGLEUNIT["degree",0.0174532925199433]],
                CS[ellipsoidal,2],
                    AXIS["geodetic latitude (Lat)",north,
                        ORDER[1],
                        ANGLEUNIT["degree",0.0174532925199433]],
                    AXIS["geodetic longitude (Lon)",east,
                        ORDER[2],
                        ANGLEUNIT["degree",0.0174532925199433]]]],
        ABRIDGEDTRANSFORMATION["User-defined Bursa-Wolf Transform",
            METHOD["Position Vector transformation (geog2D domain)"],
            PARAMETER["X-axis translation",-153.501992013804,
                ID["EPSG",8605]],
            PARAMETER["Y-axis translation",91.8979603422544,
                ID["EPSG",8606]],
            PARAMETER["Z-axis translation",-76.7203604254192,
                ID["EPSG",8607]],
            PARAMETER["X-axis rotation",-11.9539464931016,
                ID["EPSG",8608]],
            PARAMETER["Y-axis rotation",13.9315768664084,
                ID["EPSG",8609]],
            PARAMETER["Z-axis rotation",-3.45993996519333,
                ID["EPSG",8610]],
            PARAMETER["Scale difference",0.999965937122937,
                ID["EPSG",8611]]]],
    VERTCRS["AHD height",
        VDATUM["Australian Height Datum"],
        CS[vertical,1],
            AXIS["gravity-related height (H)",up,
                LENGTHUNIT["metre",1]],
        USAGE[
            SCOPE["Cadastre, engineering surveying applications over distances up to 10km."],
            AREA["Australia - Australian Capital Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Western Australia and Victoria - onshore. Christmas Island - onshore. Cocos and Keeling Islands - onshore."],
            BBOX[-43.7,96.76,-9.86,153.69]],
        ID["EPSG",5711]]]
```

When transforming to `EPSG:7855`, the helmert transform is included in the pipeline as expected (I'm not sure the vertical coordinate should be pushed however, but thats a separate question for another day..):

```
Candidate operations found: 1
-------------------------------------
Operation No. 1:

unknown id, Inverse of Australian Map Grid zone 55 + User-defined Bursa-Wolf Transform + Map Grid of Australia zone 55, unknown accuracy, World

PROJ string:
+proj=pipeline
  +step +inv +proj=utm +zone=55 +south +ellps=aust_SA
  +step +proj=push +v_3
  +step +proj=cart +ellps=aust_SA
  +step +proj=helmert +x=-153.501992013804 +y=91.8979603422544
        +z=-76.7203604254192 +rx=-11.9539464931016 +ry=13.9315768664084
        +rz=-3.45993996519333 +s=-34.0628770629792 +convention=position_vector
  +step +inv +proj=cart +ellps=GRS80
  +step +proj=pop +v_3
  +step +proj=utm +zone=55 +south +ellps=GRS80
```

#### Failing case:
However, if the target is `EPSG:7855+EPSG:5711`, the helmert step is missed completely:

```
Candidate operations found: 1
-------------------------------------
Operation No. 1:

unknown id, Inverse of Australian Map Grid zone 55 + Conversion from AHD height to AHD height + Ballpark geographic offset from AGD66 to GDA2020 + Map Grid of Australia zone 55, unknown accuracy
, World, has ballpark transformation

PROJ string:
+proj=pipeline
  +step +inv +proj=utm +zone=55 +south +ellps=aust_SA
  +step +proj=utm +zone=55 +south +ellps=GRS80
```

#### Working cases:
If instead a similar BOUNDCRS is defined without being included in a COMPOUNDCRS, then it works as expected for both target CRS cases. 

For example, consider this source CRS:

```
BOUNDCRS[
    SOURCECRS[
        PROJCRS["AGD66 / AMG zone 55",
            BASEGEOGCRS["AGD66",
                DATUM["User datum (no grid)",
                    ELLIPSOID["Australian National Spheroid",6378160,298.25,
                        LENGTHUNIT["metre",1]]],
                PRIMEM["Greenwich",0,
                    ANGLEUNIT["degree",0.0174532925199433]]],
            CONVERSION["Australian Map Grid zone 55",
                METHOD["Transverse Mercator"],
                PARAMETER["Latitude of natural origin",0,
                    ANGLEUNIT["degree",0.0174532925199433]],
                PARAMETER["Longitude of natural origin",147,
                    ANGLEUNIT["degree",0.0174532925199433]],
                PARAMETER["Scale factor at natural origin",0.9996,
                    SCALEUNIT["unity",1]],
                PARAMETER["False easting",500000,
                    LENGTHUNIT["metre",1]],
                PARAMETER["False northing",10000000,
                    LENGTHUNIT["metre",1]]],
            CS[Cartesian,3],
                AXIS["(E)",east,
                    ORDER[1],
                    LENGTHUNIT["metre",1]],
                AXIS["(N)",north,
                    ORDER[2],
                    LENGTHUNIT["metre",1]],
                AXIS["ellipsoidal height (h)",up,
                    ORDER[3],
                    LENGTHUNIT["metre",1]],
            USAGE[
                SCOPE["unknown"],
                AREA["Australia - onshore and offshore between 144°E and 150°E. Papua New Guinea (PNG) - onshore between 144°E and 150°E."],
                BBOX[-47.2,144,-1.3,150.01]],
            REMARK["Promoted to 3D from EPSG:20255"]]],
    TARGETCRS[
        GEOGCRS["GDA2020",
            DATUM["Geocentric Datum of Australia 2020",
                ELLIPSOID["GRS 1980",6378137,298.257222101,
                    LENGTHUNIT["metre",1]]],
            PRIMEM["Greenwich",0,
                ANGLEUNIT["degree",0.0174532925199433]],
            CS[ellipsoidal,3],
                AXIS["geodetic latitude (Lat)",north,
                    ORDER[1],
                    ANGLEUNIT["degree",0.0174532925199433]],
                AXIS["geodetic longitude (Lon)",east,
                    ORDER[2],
                    ANGLEUNIT["degree",0.0174532925199433]],
                AXIS["ellipsoidal height (h)",up,
                    ORDER[3],
                    LENGTHUNIT["metre",1,
                        ID["EPSG",9001]]]]],
    ABRIDGEDTRANSFORMATION["User-defined Bursa-Wolf Transform",
        METHOD["Position Vector transformation (geog2D domain)"],
        PARAMETER["X-axis translation",-153.302844997652,
            ID["EPSG",8605]],
        PARAMETER["Y-axis translation",92.4153712086044,
            ID["EPSG",8606]],
        PARAMETER["Z-axis translation",-76.4869212856832,
            ID["EPSG",8607]],
        PARAMETER["X-axis rotation",-11.9644937558611,
            ID["EPSG",8608]],
        PARAMETER["Y-axis rotation",13.9284887447329,
            ID["EPSG",8609]],
        PARAMETER["Z-axis rotation",-3.44390727325759,
            ID["EPSG",8610]],
        PARAMETER["Scale difference",0.999965772441661,
            ID["EPSG",8611]]]]
```

When the target is `EPSG:7855`:

```
Candidate operations found: 1
-------------------------------------
Operation No. 1:

unknown id, Inverse of Australian Map Grid zone 55 + User-defined Bursa-Wolf Transform + Null geographic offset from GDA2020 (geog3D) to GDA2020 (geog2D) + Map Grid of Australia zone 55, unknown
 accuracy, World

PROJ string:
+proj=pipeline
  +step +inv +proj=utm +zone=55 +south +ellps=aust_SA
  +step +proj=cart +ellps=aust_SA
  +step +proj=helmert +x=-153.302844997652 +y=92.4153712086044
        +z=-76.4869212856832 +rx=-11.9644937558611 +ry=13.9284887447329
        +rz=-3.44390727325759 +s=-34.2275583390395 +convention=position_vector
  +step +inv +proj=cart +ellps=GRS80
  +step +proj=utm +zone=55 +south +ellps=GRS80
```

Likewise, when the target is `EPSG:7855+EPSG:5711`:

```
Candidate operations found: 2
-------------------------------------
Operation No. 1:

unknown id, Inverse of Australian Map Grid zone 55 + User-defined Bursa-Wolf Transform + GDA2020 to AHD height (1) + Map Grid of Australia zone 55, unknown accuracy, Australia - Australian Capit
al Territory, New South Wales, Northern Territory, Queensland, South Australia, Tasmania, Western Australia and Victoria - onshore. Christmas Island - onshore. Cocos and Keeling Islands - onshor
e.

PROJ string:
+proj=pipeline
  +step +inv +proj=utm +zone=55 +south +ellps=aust_SA
  +step +proj=cart +ellps=aust_SA
  +step +proj=helmert +x=-153.302844997652 +y=92.4153712086044
        +z=-76.4869212856832 +rx=-11.9644937558611 +ry=13.9284887447329
        +rz=-3.44390727325759 +s=-34.2275583390395 +convention=position_vector
  +step +inv +proj=cart +ellps=GRS80
  +step +inv +proj=vgridshift +grids=au_ga_AUSGeoid2020_20180201.tif
        +multiplier=1
  +step +proj=utm +zone=55 +south +ellps=GRS80

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

unknown id, Inverse of Australian Map Grid zone 55 + User-defined Bursa-Wolf Transform + Inverse of Transformation from AHD height to GDA2020 (ballpark vertical transformation, without ellipsoid
 height to vertical height correction) + Map Grid of Australia zone 55, unknown accuracy, World, has ballpark transformation

PROJ string:
+proj=pipeline
  +step +inv +proj=utm +zone=55 +south +ellps=aust_SA
  +step +proj=cart +ellps=aust_SA
  +step +proj=helmert +x=-153.302844997652 +y=92.4153712086044
        +z=-76.4869212856832 +rx=-11.9644937558611 +ry=13.9284887447329
        +rz=-3.44390727325759 +s=-34.2275583390395 +convention=position_vector
  +step +inv +proj=cart +ellps=GRS80
  +step +proj=utm +zone=55 +south +ellps=GRS80 
```

Is there a way to fix the Compound Bound CRS case? I need to be able to define a local grid for coordinates with AHD height.


#### Environment Information

- PROJ version (`proj-9.6.1`)
- Operation System Information: Ubuntu 20.04

#### Installation method

- Built from source



Discussion:

Patch:
diff --git a/src/iso19111/operation/coordinateoperationfactory.cpp b/src/iso19111/operation/coordinateoperationfactory.cpp
index c6e8f9f8c7..95bc15278f 100644
--- a/src/iso19111/operation/coordinateoperationfactory.cpp
+++ b/src/iso19111/operation/coordinateoperationfactory.cpp
@@ -3714,7 +3714,8 @@ CoordinateOperationFactory::Private::createOperations(
     }
 
     if (dynamic_cast<const crs::EngineeringCRS *>(sourceCRS.get()) &&
-        sourceCRS->_isEquivalentTo(targetCRS.get())) {
+        sourceCRS->_isEquivalentTo(targetCRS.get(),
+                                   util::IComparable::Criterion::EQUIVALENT)) {
         std::string name("Identity transformation from ");
         name += sourceCRS->nameStr();
         name += " to ";
@@ -3845,7 +3846,9 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
             if (pmoDst.size() == pmoSrc.size()) {
                 bool ok = true;
                 for (size_t i = 0; i < pmoSrc.size(); ++i) {
-                    if (pmoSrc[i]->_isEquivalentTo(pmoDst[i].get())) {
+                    if (pmoSrc[i]->_isEquivalentTo(
+                            pmoDst[i].get(),
+                            util::IComparable::Criterion::EQUIVALENT)) {
                         auto pmo = pmoSrc[i]->cloneWithEpochs(*sourceEpoch,
                                                               *targetEpoch);
                         std::vector<operation::CoordinateOperationNNPtr> ops;
@@ -6629,7 +6632,9 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
         const auto vertSrc = componentsSrc[1]->extractVerticalCRS();
         const auto vertDst = componentsDst[1]->extractVerticalCRS();
         if (vertSrc && vertDst &&
-            !componentsSrc[1]->_isEquivalentTo(componentsDst[1].get())) {
+            !componentsSrc[1]->_isEquivalentTo(
+                componentsDst[1].get(),
+                util::IComparable::Criterion::EQUIVALENT)) {
             if ((!vertSrc->geoidModel().empty() ||
                  !vertDst->geoidModel().empty()) &&
                 // To be able to use "CGVD28 height to
@@ -6966,7 +6971,8 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
                 dynamic_cast<crs::GeographicCRS *>(
                     compSrc0BoundCrs->hubCRS().get()) &&
                 compSrc0BoundCrs->hubCRS()->_isEquivalentTo(
-                    compDst0BoundCrs->hubCRS().get())) {
+                    compDst0BoundCrs->hubCRS().get(),
+                    util::IComparable::Criterion::EQUIVALENT)) {
                 interpolationCRS =
                     NN_NO_CHECK(util::nn_dynamic_pointer_cast<crs::SingleCRS>(
                         compSrc0BoundCrs->hubCRS()));
@@ -7155,7 +7161,8 @@ void CoordinateOperationFactory::Private::createOperationsBoundToCompound(
                 const auto compDst0BoundCrsHubAsGeogCRSDatum =
                     compDst0BoundCrsHubAsGeogCRS->datumNonNull(dbContext);
                 if (boundSrcHubAsGeogCRSDatum->_isEquivalentTo(
-                        compDst0BoundCrsHubAsGeogCRSDatum.get())) {
+                        compDst0BoundCrsHubAsGeogCRSDatum.get(),
+                        util::IComparable::Criterion::EQUIVALENT)) {
                     auto cs = cs::EllipsoidalCS::
                         createLatitudeLongitudeEllipsoidalHeight(
                             common::UnitOfMeasure::DEGREE,
@@ -7181,7 +7188,8 @@ void CoordinateOperationFactory::Private::createOperationsBoundToCompound(
                         for (const auto &opDst : geog3DToTargetOps) {
                             if (opSrc->targetCRS() && opDst->sourceCRS() &&
                                 !opSrc->targetCRS()->_isEquivalentTo(
-                                    opDst->sourceCRS().get())) {
+                                    opDst->sourceCRS().get(),
+                                    util::IComparable::Criterion::EQUIVALENT)) {
                                 // Shouldn't happen normally, but typically
                                 // one of them can be 2D and the other 3D
                                 // due to above createOperations() not


Test patch:
diff --git a/test/unit/test_operationfactory.cpp b/test/unit/test_operationfactory.cpp
index 0c828e737a..f7897590b6 100644
--- a/test/unit/test_operationfactory.cpp
+++ b/test/unit/test_operationfactory.cpp
@@ -6037,6 +6037,128 @@ TEST(operation, compoundCRS_to_compoundCRS_GDA94_AHD_to_GDA2020_AVWS) {
 
 // ---------------------------------------------------------------------------
 
+TEST(operation,
+     compoundCRS_with_horizontal_boundCRS_to_compoundCRS_and_same_vertical) {
+
+    auto dbContext = DatabaseContext::create();
+    auto objSrc = WKTParser().attachDatabaseContext(dbContext).createFromWKT(
+        "COMPOUNDCRS[\"AGD66 / AMG zone 55 + AHD height\",\n"
+        "    BOUNDCRS[\n"
+        "        SOURCECRS[\n"
+        "            PROJCRS[\"AGD66 / AMG zone 55 + AHD height\",\n"
+        "                BASEGEOGCRS[\"AGD66\",\n"
+        "                    DATUM[\"User datum (no grid)\",\n"
+        "                        ELLIPSOID[\"Australian National "
+        "Spheroid\",6378160,298.25,\n"
+        "                            LENGTHUNIT[\"metre\",1]]],\n"
+        "                    PRIMEM[\"Greenwich\",0,\n"
+        "                        ANGLEUNIT[\"degree\",0.0174532925199433]]],\n"
+        "                CONVERSION[\"Australian Map Grid zone 55\",\n"
+        "                    METHOD[\"Transverse Mercator\"],\n"
+        "                    PARAMETER[\"Latitude of natural origin\",0,\n"
+        "                        ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+        "                    PARAMETER[\"Longitude of natural origin\",147,\n"
+        "                        ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+        "                    PARAMETER[\"Scale factor at natural "
+        "origin\",0.9996,\n"
+        "                        SCALEUNIT[\"unity\",1]],\n"
+        "                    PARAMETER[\"False easting\",500000,\n"
+        "                        LENGTHUNIT[\"metre\",1]],\n"
+        "                    PARAMETER[\"False northing\",10000000,\n"
+        "                        LENGTHUNIT[\"metre\",1]]],\n"
+        "                CS[Cartesian,2],\n"
+        "                    AXIS[\"(E)\",east,\n"
+        "                        ORDER[1],\n"
+        "                        LENGTHUNIT[\"metre\",1]],\n"
+        "                    AXIS[\"(N)\",north,\n"
+        "                        ORDER[2],\n"
+        "                        LENGTHUNIT[\"metre\",1]],\n"
+        "                USAGE[\n"
+        "                    SCOPE[\"Engineering survey, topographic "
+        "mapping.\"],\n"
+        "                    AREA[\"Australia - onshore and offshore between "
+        "144°E and 150°E. Papua New Guinea (PNG) - onshore between 144°E and "
+        "150°E.\"],\n"
+        "                    BBOX[-47.2,144,-1.3,150.01]]]],\n"
+        "        TARGETCRS[\n"
+        "            GEOGCRS[\"GDA2020\",\n"
+        "                DATUM[\"Geocentric Datum of Australia 2020\",\n"
+        "                    ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n"
+        "                        LENGTHUNIT[\"metre\",1]]],\n"
+        "                PRIMEM[\"Greenwich\",0,\n"
+        "                    ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+        "                CS[ellipsoidal,2],\n"
+        "                    AXIS[\"geodetic latitude (Lat)\",north,\n"
+        "                        ORDER[1],\n"
+        "                        ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+        "                    AXIS[\"geodetic longitude (Lon)\",east,\n"
+        "                        ORDER[2],\n"
+        "                        ANGLEUNIT[\"degree\",0.0174532925199433]]]],\n"
+        "        ABRIDGEDTRANSFORMATION[\"User-defined Bursa-Wolf "
+        "Transform\",\n"
+        "            METHOD[\"Position Vector transformation (geog2D "
+        "domain)\"],\n"
+        "            PARAMETER[\"X-axis translation\",-153.501992013804,\n"
+        "                ID[\"EPSG\",8605]],\n"
+        "            PARAMETER[\"Y-axis translation\",91.8979603422544,\n"
+        "                ID[\"EPSG\",8606]],\n"
+        "            PARAMETER[\"Z-axis translation\",-76.7203604254192,\n"
+        "                ID[\"EPSG\",8607]],\n"
+        "            PARAMETER[\"X-axis rotation\",-11.9539464931016,\n"
+        "                ID[\"EPSG\",8608]],\n"
+        "            PARAMETER[\"Y-axis rotation\",13.9315768664084,\n"
+        "                ID[\"EPSG\",8609]],\n"
+        "            PARAMETER[\"Z-axis rotation\",-3.45993996519333,\n"
+        "                ID[\"EPSG\",8610]],\n"
+        "            PARAMETER[\"Scale difference\",0.999965937122937,\n"
+        "                ID[\"EPSG\",8611]]]],\n"
+        "    VERTCRS[\"AHD height\",\n"
+        "        VDATUM[\"Australian Height Datum\"],\n"
+        "        CS[vertical,1],\n"
+        "            AXIS[\"gravity-related height (H)\",up,\n"
+        "                LENGTHUNIT[\"metre\",1]],\n"
+        "        USAGE[\n"
+        "            SCOPE[\"Cadastre, engineering surveying applications over "
+        "distances up to 10km.\"],\n"
+        "            AREA[\"Australia - Australian Capital Territory, New "
+        "South Wales, Northern Territory, Queensland, South Australia, "
+        "Tasmania, Western Australia and Victoria - onshore. Christmas Island "
+        "- onshore. Cocos and Keeling Islands - onshore.\"],\n"
+        "            BBOX[-43.7,96.76,-9.86,153.69]],\n"
+        "        ID[\"EPSG\",5711]]]");
+    auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+    ASSERT_TRUE(src != nullptr);
+
+    // GDA2020 / MGA zone 55 + AHD height
+    auto authFactoryEPSG = AuthorityFactory::create(dbContext, "EPSG");
+    auto dstObj = createFromUserInput("EPSG:7855+5711", dbContext, false);
+    auto dst = nn_dynamic_pointer_cast<CRS>(dstObj);
+    ASSERT_TRUE(dst != nullptr);
+
+    auto ctxt = CoordinateOperationContext::create(
+        AuthorityFactory::create(dbContext, std::string()), nullptr, 0.0);
+    ctxt->setSpatialCriterion(
+        CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+    auto list = CoordinateOperationFactory::create()->createOperations(
+        NN_NO_CHECK(src), NN_NO_CHECK(dst), ctxt);
+    ASSERT_GE(list.size(), 1U);
+
+    EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
+              "+proj=pipeline "
+              "+step +inv +proj=utm +zone=55 +south +ellps=aust_SA "
+              "+step +proj=push +v_3 "
+              "+step +proj=cart +ellps=aust_SA "
+              "+step +proj=helmert +x=-153.501992013804 +y=91.8979603422544 "
+              "+z=-76.7203604254192 +rx=-11.9539464931016 +ry=13.9315768664084 "
+              "+rz=-3.45993996519333 +s=-34.0628770629792 "
+              "+convention=position_vector "
+              "+step +inv +proj=cart +ellps=GRS80 "
+              "+step +proj=pop +v_3 "
+              "+step +proj=utm +zone=55 +south +ellps=GRS80");
+}
+
+// ---------------------------------------------------------------------------
+
 TEST(
     operation,
     compoundCRS_to_compoundCRS_concatenated_operation_with_two_vert_transformation) {