diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 183 | ||||
| -rw-r--r-- | src/iso19111/factory.cpp | 35 |
2 files changed, 121 insertions, 97 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 6a05bbe8..881a16fd 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -4710,6 +4710,64 @@ Conversion::createGeographicGeocentric(const util::PropertyMap &properties) { //! @cond Doxygen_Suppress +static const char *getCRSQualifierStr(const crs::CRSPtr &crs) { + auto geod = dynamic_cast<crs::GeodeticCRS *>(crs.get()); + if (geod) { + if (geod->isGeocentric()) { + return " (geocentric)"; + } + auto geog = dynamic_cast<crs::GeographicCRS *>(geod); + if (geog) { + if (geog->coordinateSystem()->axisList().size() == 2) { + return " (geog2D)"; + } else { + return " (geog3D)"; + } + } + } + return ""; +} + +// --------------------------------------------------------------------------- + +static std::string buildOpName(const char *opType, const crs::CRSPtr &source, + const crs::CRSPtr &target) { + std::string res(opType); + const auto &srcName = source->nameStr(); + const auto &targetName = target->nameStr(); + const char *srcQualifier = ""; + const char *targetQualifier = ""; + if (srcName == targetName) { + srcQualifier = getCRSQualifierStr(source); + targetQualifier = getCRSQualifierStr(target); + if (strcmp(srcQualifier, targetQualifier) == 0) { + srcQualifier = ""; + targetQualifier = ""; + } + } + res += " from "; + res += srcName; + res += srcQualifier; + res += " to "; + res += targetName; + res += targetQualifier; + return res; +} + +// --------------------------------------------------------------------------- + +ConversionNNPtr +Conversion::createGeographicGeocentric(const crs::CRSNNPtr &sourceCRS, + const crs::CRSNNPtr &targetCRS) { + auto properties = util::PropertyMap().set( + common::IdentifiedObject::NAME_KEY, + buildOpName("Conversion", sourceCRS, targetCRS)); + auto conv = createGeographicGeocentric(properties); + conv->setCRSs(sourceCRS, targetCRS, nullptr); + return conv; +} +// --------------------------------------------------------------------------- + static util::PropertyMap &addDomains(util::PropertyMap &map, const common::ObjectUsage *obj) { @@ -7403,52 +7461,6 @@ TransformationNNPtr Transformation::createChangeVerticalUnit( // --------------------------------------------------------------------------- -static const char *getCRSQualifierStr(const crs::CRSPtr &crs) { - auto geod = dynamic_cast<crs::GeodeticCRS *>(crs.get()); - if (geod) { - if (geod->isGeocentric()) { - return " (geocentric)"; - } - auto geog = dynamic_cast<crs::GeographicCRS *>(geod); - if (geog) { - if (geog->coordinateSystem()->axisList().size() == 2) { - return " (geog2D)"; - } else { - return " (geog3D)"; - } - } - } - return ""; -} - -// --------------------------------------------------------------------------- - -static std::string buildOpName(const char *opType, const crs::CRSPtr &source, - const crs::CRSPtr &target) { - std::string res(opType); - const auto &srcName = source->nameStr(); - const auto &targetName = target->nameStr(); - const char *srcQualifier = ""; - const char *targetQualifier = ""; - if (srcName == targetName) { - srcQualifier = getCRSQualifierStr(source); - targetQualifier = getCRSQualifierStr(target); - if (strcmp(srcQualifier, targetQualifier) == 0) { - srcQualifier = ""; - targetQualifier = ""; - } - } - res += " from "; - res += srcName; - res += srcQualifier; - res += " to "; - res += targetName; - res += targetQualifier; - return res; -} - -// --------------------------------------------------------------------------- - static util::PropertyMap createPropertiesForInverse(const CoordinateOperation *op, bool derivedFrom, bool approximateInversion) { @@ -9524,6 +9536,9 @@ ConcatenatedOperationNNPtr ConcatenatedOperation::create( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress + +// --------------------------------------------------------------------------- + void ConcatenatedOperation::fixStepsDirection( const crs::CRSNNPtr &concatOpSourceCRS, const crs::CRSNNPtr &concatOpTargetCRS, @@ -9620,14 +9635,47 @@ void ConcatenatedOperation::fixStepsDirection( nullptr); } } else if (!conv && l_sourceCRS && l_targetCRS) { + + const auto isGeographic = [](const crs::CRS *crs) -> bool { + return dynamic_cast<const crs::GeographicCRS *>(crs) != nullptr; + }; + + const auto isGeocentric = [](const crs::CRS *crs) -> bool { + auto geodCRS = dynamic_cast<const crs::GeodeticCRS *>(crs); + if (geodCRS && + geodCRS->coordinateSystem()->axisList().size() == 3) + return true; + return false; + }; + // Transformations might be mentioned in their forward directions, // whereas we should instead use the reverse path. auto prevOpTarget = (i == 0) ? concatOpSourceCRS.as_nullable() : operationsInOut[i - 1]->targetCRS(); - if (!compareStepCRS(l_sourceCRS.get(), prevOpTarget.get()) && - compareStepCRS(l_targetCRS.get(), prevOpTarget.get())) { + if (compareStepCRS(l_sourceCRS.get(), prevOpTarget.get())) { + // do nothing + } else if (compareStepCRS(l_targetCRS.get(), prevOpTarget.get())) { op = op->inverse(); } + // Below is needed for EPSG:9103 which chains NAD83(2011) geographic + // 2D with NAD83(2011) geocentric + else if (l_sourceCRS->nameStr() == prevOpTarget->nameStr() && + ((isGeographic(l_sourceCRS.get()) && + isGeocentric(prevOpTarget.get())) || + (isGeocentric(l_sourceCRS.get()) && + isGeographic(prevOpTarget.get())))) { + auto newOp(Conversion::createGeographicGeocentric( + NN_NO_CHECK(prevOpTarget), NN_NO_CHECK(l_sourceCRS))); + operationsInOut.insert(operationsInOut.begin() + i, newOp); + } else if (l_targetCRS->nameStr() == prevOpTarget->nameStr() && + ((isGeographic(l_targetCRS.get()) && + isGeocentric(prevOpTarget.get())) || + (isGeocentric(l_targetCRS.get()) && + isGeographic(prevOpTarget.get())))) { + auto newOp(Conversion::createGeographicGeocentric( + NN_NO_CHECK(prevOpTarget), NN_NO_CHECK(l_targetCRS))); + operationsInOut.insert(operationsInOut.begin() + i, newOp); + } } } @@ -10290,10 +10338,6 @@ struct CoordinateOperationFactory::Private { hasPerfectAccuracyResult(const std::vector<CoordinateOperationNNPtr> &res, const Context &context); - static ConversionNNPtr - createGeographicGeocentric(const crs::CRSNNPtr &sourceCRS, - const crs::CRSNNPtr &targetCRS); - static void setCRSs(CoordinateOperation *co, const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS); }; @@ -11659,18 +11703,6 @@ static CoordinateOperationNNPtr createHorizVerticalHorizPROJBased( //! @cond Doxygen_Suppress -ConversionNNPtr CoordinateOperationFactory::Private::createGeographicGeocentric( - const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS) { - auto properties = util::PropertyMap().set( - common::IdentifiedObject::NAME_KEY, - buildOpName("Conversion", sourceCRS, targetCRS)); - auto conv = Conversion::createGeographicGeocentric(properties); - conv->setCRSs(sourceCRS, targetCRS, nullptr); - return conv; -} - -// --------------------------------------------------------------------------- - std::vector<CoordinateOperationNNPtr> CoordinateOperationFactory::Private::createOperationsGeogToGeog( std::vector<CoordinateOperationNNPtr> &res, const crs::CRSNNPtr &sourceCRS, @@ -12712,8 +12744,8 @@ CoordinateOperationFactory::Private::createOperations( if (geodSrc->datum()->_isEquivalentTo( geodDst->datum().get(), util::IComparable::Criterion::EQUIVALENT)) { - res.emplace_back( - createGeographicGeocentric(sourceCRS, targetCRS)); + res.emplace_back(Conversion::createGeographicGeocentric( + sourceCRS, targetCRS)); } else if (isSrcGeocentric) { std::string interm_crs_name(geogDst->nameStr()); interm_crs_name += " (geocentric)"; @@ -12729,8 +12761,8 @@ CoordinateOperationFactory::Private::createOperations( geodSrc->coordinateSystem())))); auto opFirst = createBallparkGeocentricTranslation(sourceCRS, interm_crs); - auto opSecond = - createGeographicGeocentric(interm_crs, targetCRS); + auto opSecond = Conversion::createGeographicGeocentric( + interm_crs, targetCRS); res.emplace_back(ConcatenatedOperation::createComputeMetadata( {opFirst, opSecond}, !allowEmptyIntersection)); } else { @@ -13364,9 +13396,7 @@ CoordinateOperationFactory::Private::createOperations( verticalTransform, interpToTarget, interpolationGeogCRS, true); res.emplace_back(op); - } catch ( - const InvalidOperationEmptyIntersection &) { - continue; + } catch (const std::exception &) { } } } @@ -13377,10 +13407,13 @@ CoordinateOperationFactory::Private::createOperations( // involve a grid, because of the rather arbitrary order // horizontal then vertical applied for (const auto &horizTransform : horizTransforms) { - auto op = createHorizVerticalPROJBased( - sourceCRS, targetCRS, horizTransform, - verticalTransform); - res.emplace_back(op); + try { + auto op = createHorizVerticalPROJBased( + sourceCRS, targetCRS, horizTransform, + verticalTransform); + res.emplace_back(op); + } catch (const std::exception &) { + } } } } diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 9be04580..6fef6366 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -3141,8 +3141,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation( "source_crs_auth_name, source_crs_code, " "target_crs_auth_name, target_crs_code, " "area_of_use_auth_name, area_of_use_code, accuracy, " - "step1_auth_name, step1_code, step2_auth_name, step2_code, " - "step3_auth_name, step3_code, operation_version, deprecated FROM " + "operation_version, deprecated FROM " "concatenated_operation WHERE auth_name = ? AND code = ?", code); if (res.empty()) { @@ -3150,6 +3149,13 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation( throw NoSuchAuthorityCodeException( "concatenated_operation not found", d->authority(), code); } + + auto resSteps = d->runWithCodeParam( + "SELECT step_auth_name, step_code FROM " + "concatenated_operation_step WHERE operation_auth_name = ? " + "AND operation_code = ? ORDER BY step_number", + code); + try { const auto &row = res.front(); size_t idx = 0; @@ -3163,32 +3169,17 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation( const auto &area_of_use_auth_name = row[idx++]; const auto &area_of_use_code = row[idx++]; const auto &accuracy = row[idx++]; - const auto &step1_auth_name = row[idx++]; - const auto &step1_code = row[idx++]; - const auto &step2_auth_name = row[idx++]; - const auto &step2_code = row[idx++]; - const auto &step3_auth_name = row[idx++]; - const auto &step3_code = row[idx++]; const auto &operation_version = row[idx++]; const auto &deprecated_str = row[idx++]; const bool deprecated = deprecated_str == "1"; std::vector<operation::CoordinateOperationNNPtr> operations; - operations.push_back( - d->createFactory(step1_auth_name) - ->createCoordinateOperation(step1_code, false, - usePROJAlternativeGridNames, - std::string())); - operations.push_back( - d->createFactory(step2_auth_name) - ->createCoordinateOperation(step2_code, false, - usePROJAlternativeGridNames, - std::string())); - - if (!step3_auth_name.empty()) { + for (const auto &rowStep : resSteps) { + const auto &step_auth_name = rowStep[0]; + const auto &step_code = rowStep[1]; operations.push_back( - d->createFactory(step3_auth_name) - ->createCoordinateOperation(step3_code, false, + d->createFactory(step_auth_name) + ->createCoordinateOperation(step_code, false, usePROJAlternativeGridNames, std::string())); } |
