diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-03-16 15:14:55 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-03-16 15:22:57 +0100 |
| commit | d95b0cb8b317d0a8142b664c42928083145194ed (patch) | |
| tree | 3829861a7c03da12179e4d7cf4458748583acfbc | |
| parent | a9886a5e4a64610aa605e98afeb467d1c44ed925 (diff) | |
| download | PROJ-d95b0cb8b317d0a8142b664c42928083145194ed.tar.gz PROJ-d95b0cb8b317d0a8142b664c42928083145194ed.zip | |
createOperation(): fix geocent <--> nadgrids+geoidgrids case (fixes #1323)
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 31 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 20 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 45 |
3 files changed, 93 insertions, 3 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 575eae39..240833df 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -11914,11 +11914,40 @@ CoordinateOperationFactory::Private::createOperations( return horizTransforms; } } + } else if (compoundSrc && geodDst) { + auto datum = geodDst->datum(); + if (datum) { + auto cs = + cs::EllipsoidalCS::createLatitudeLongitudeEllipsoidalHeight( + common::UnitOfMeasure::DEGREE, + common::UnitOfMeasure::METRE); + auto intermGeog3DCRS = util::nn_static_pointer_cast<crs::CRS>( + crs::GeographicCRS::create( + util::PropertyMap() + .set(common::IdentifiedObject::NAME_KEY, + geodDst->nameStr()) + .set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY, + metadata::Extent::WORLD), + NN_NO_CHECK(datum), cs)); + auto sourceToGeog3DOps = + createOperations(sourceCRS, intermGeog3DCRS, context); + auto geog3DToTargetOps = + createOperations(intermGeog3DCRS, targetCRS, context); + if (!geog3DToTargetOps.empty()) { + for (const auto &op : sourceToGeog3DOps) { + res.emplace_back( + ConcatenatedOperation::createComputeMetadata( + {op, geog3DToTargetOps.front()}, + !allowEmptyIntersection)); + } + return res; + } + } } // reverse of previous case auto compoundDst = dynamic_cast<const crs::CompoundCRS *>(targetCRS.get()); - if (geogSrc && compoundDst) { + if (geodSrc && compoundDst) { return applyInverse(createOperations(targetCRS, sourceCRS, context)); } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 51f93e2f..d5f38fd5 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -5049,7 +5049,7 @@ const std::string &PROJStringFormatter::toString() const { first.paramValues[1].keyEquals("z_in") && first.paramValues[2].keyEquals("xy_out") && first.paramValues[3].keyEquals("z_out") && - second.paramValues[0].keyEquals("xy_in=") && + second.paramValues[0].keyEquals("xy_in") && second.paramValues[1].keyEquals("xy_out") && first.paramValues[0].value == second.paramValues[1].value && first.paramValues[2].value == second.paramValues[0].value) { @@ -5074,6 +5074,22 @@ const std::string &PROJStringFormatter::toString() const { break; } + // unitconvert (1), axisswap order=2,1, unitconvert(2) ==> + // axisswap order=2,1, unitconvert (1), unitconvert(2) which + // will get further optimized by previous case + if (i + 1 < d->steps_.size() && prevStep.name == "unitconvert" && + curStep.name == "axisswap" && curStepParamCount == 1 && + curStep.paramValues[0].equals("order", "2,1")) { + auto iterNext = iterCur; + ++iterNext; + auto &nextStep = *iterNext; + if (nextStep.name == "unitconvert") { + std::swap(*iterPrev, *iterCur); + changeDone = true; + break; + } + } + // axisswap order=2,1 followed by itself is a no-op if (curStep.name == "axisswap" && prevStep.name == "axisswap" && curStepParamCount == 1 && prevStepParamCount == 1 && @@ -6707,7 +6723,7 @@ PROJStringParser::Private::buildGeocentricCRS(int iStep, int iUnitConvert) { auto datum = buildDatum(step, title); - UnitOfMeasure unit = UnitOfMeasure::METRE; + UnitOfMeasure unit = buildUnit(step, "units", ""); if (iUnitConvert >= 0) { auto &stepUnitConvert = steps_[iUnitConvert]; const std::string *xy_in = &getParamValue(stepUnitConvert, "xy_in"); diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index e71ac716..615cbd67 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -6026,6 +6026,51 @@ TEST(operation, compoundCRS_with_boundProjCRS_and_boundVerticalCRS_to_geogCRS) { // --------------------------------------------------------------------------- +TEST(operation, geocent_to_compoundCRS) { + auto objSrc = PROJStringParser().createFromPROJString( + "+proj=geocent +datum=WGS84 +units=m +type=crs"); + auto src = nn_dynamic_pointer_cast<CRS>(objSrc); + ASSERT_TRUE(src != nullptr); + auto objDst = PROJStringParser().createFromPROJString( + "+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx " + "+type=crs"); + auto dst = nn_dynamic_pointer_cast<CRS>(objDst); + ASSERT_TRUE(dst != nullptr); + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +inv +proj=cart +ellps=WGS84 +step +inv " + "+proj=vgridshift +grids=@foo.gtx +multiplier=1 +step +inv " + "+proj=hgridshift +grids=@foo.gsb +step +proj=unitconvert " + "+xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + +TEST(operation, geocent_to_compoundCRS_context) { + auto authFactory = + AuthorityFactory::create(DatabaseContext::create(), "EPSG"); + // WGS84 geocentric + auto src = authFactory->createCoordinateReferenceSystem("4978"); + auto objDst = PROJStringParser().createFromPROJString( + "+proj=longlat +ellps=GRS67 +nadgrids=@foo.gsb +geoidgrids=@foo.gtx " + "+type=crs"); + auto dst = nn_dynamic_pointer_cast<CRS>(objDst); + ASSERT_TRUE(dst != nullptr); + auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0); + auto list = CoordinateOperationFactory::create()->createOperations( + src, NN_CHECK_ASSERT(dst), ctxt); + ASSERT_EQ(list.size(), 1U); + EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +inv +proj=cart +ellps=WGS84 +step +inv " + "+proj=vgridshift +grids=@foo.gtx +multiplier=1 +step +inv " + "+proj=hgridshift +grids=@foo.gsb +step +proj=unitconvert " + "+xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + TEST(operation, compoundCRS_to_compoundCRS) { auto compound1 = CompoundCRS::create( PropertyMap(), |
