diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2018-12-06 14:26:56 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2018-12-06 14:26:56 +0100 |
| commit | 706fac8bc70312f5729e2f3aeeb4f67ecb211b1d (patch) | |
| tree | 8f229d8ecdc05cd15537c20c94181656cdcc7eec /src | |
| parent | 892f2eb80ace522c841afeb435671ca048215b66 (diff) | |
| parent | 25fa18055f43d0881a1a2bf9990c99fecfcbdbb7 (diff) | |
| download | PROJ-706fac8bc70312f5729e2f3aeeb4f67ecb211b1d.tar.gz PROJ-706fac8bc70312f5729e2f3aeeb4f67ecb211b1d.zip | |
Merge remote-tracking branch 'rouault/gdalbarn'
Diffstat (limited to 'src')
| -rw-r--r-- | src/coordinateoperation.cpp | 28 | ||||
| -rw-r--r-- | src/factory.cpp | 179 | ||||
| -rw-r--r-- | src/projinfo.cpp | 17 |
3 files changed, 194 insertions, 30 deletions
diff --git a/src/coordinateoperation.cpp b/src/coordinateoperation.cpp index a58cfdbe..04f9bc9a 100644 --- a/src/coordinateoperation.cpp +++ b/src/coordinateoperation.cpp @@ -8683,6 +8683,7 @@ struct CoordinateOperationContext::Private { bool allowUseIntermediateCRS_ = true; std::vector<std::pair<std::string, std::string>> intermediateCRSAuthCodes_{}; + bool discardSuperseded_ = true; }; //! @endcond @@ -8823,6 +8824,29 @@ bool CoordinateOperationContext::getUsePROJAlternativeGridNames() const { // --------------------------------------------------------------------------- +/** \brief Return whether transformations that are superseded (but not + * deprecated) + * should be discarded. + * + * The default is true. + */ +bool CoordinateOperationContext::getDiscardSuperseded() const { + return d->discardSuperseded_; +} + +// --------------------------------------------------------------------------- + +/** \brief Set whether transformations that are superseded (but not deprecated) + * should be discarded. + * + * The default is true. + */ +void CoordinateOperationContext::setDiscardSuperseded(bool discard) { + d->discardSuperseded_ = discard; +} + +// --------------------------------------------------------------------------- + /** \brief Set how grid availability is used. * * The default is USE_FOR_SORTING. @@ -9654,7 +9678,8 @@ findOpsInRegistryDirect(const crs::CRSNNPtr &sourceCRS, context->getGridAvailabilityUse() == CoordinateOperationContext:: GridAvailabilityUse:: - DISCARD_OPERATION_IF_MISSING_GRID); + DISCARD_OPERATION_IF_MISSING_GRID, + context->getDiscardSuperseded()); if (!res.empty()) { return res; } @@ -9695,6 +9720,7 @@ static std::vector<CoordinateOperationNNPtr> findsOpsInRegistryWithIntermediate( context->getGridAvailabilityUse() == CoordinateOperationContext::GridAvailabilityUse:: DISCARD_OPERATION_IF_MISSING_GRID, + context->getDiscardSuperseded(), context->getIntermediateCRS()); if (!res.empty()) { return res; diff --git a/src/factory.cpp b/src/factory.cpp index 96cf9bec..e24cee58 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -3046,7 +3046,7 @@ AuthorityFactory::createFromCoordinateReferenceSystemCodes( const std::string &sourceCRSCode, const std::string &targetCRSCode) const { return createFromCoordinateReferenceSystemCodes( getAuthority(), sourceCRSCode, getAuthority(), targetCRSCode, false, - false); + false, false); } // --------------------------------------------------------------------------- @@ -3075,6 +3075,8 @@ AuthorityFactory::createFromCoordinateReferenceSystemCodes( * should be substituted to the official grid names. * @param discardIfMissingGrid Whether coordinate operations that reference * missing grids should be removed from the result set. + * @param discardSuperseded Whether cordinate operations that are superseded + * (but not deprecated) should be removed from the result set. * @return list of coordinate operations * @throw NoSuchAuthorityCodeException * @throw FactoryException @@ -3084,7 +3086,8 @@ std::vector<operation::CoordinateOperationNNPtr> AuthorityFactory::createFromCoordinateReferenceSystemCodes( const std::string &sourceCRSAuthName, const std::string &sourceCRSCode, const std::string &targetCRSAuthName, const std::string &targetCRSCode, - bool usePROJAlternativeGridNames, bool discardIfMissingGrid) const { + bool usePROJAlternativeGridNames, bool discardIfMissingGrid, + bool discardSuperseded) const { std::vector<operation::CoordinateOperationNNPtr> list; // Look-up first for conversion which is the most precise. @@ -3106,13 +3109,29 @@ AuthorityFactory::createFromCoordinateReferenceSystemCodes( list.emplace_back(conv); return list; } - sql = - "SELECT cov.auth_name, cov.code FROM " - "coordinate_operation_view cov JOIN area ON cov.area_of_use_auth_name " - "= area.auth_name AND cov.area_of_use_code = area.code WHERE " - "source_crs_auth_name = ? AND source_crs_code = ? AND " - "target_crs_auth_name = ? AND target_crs_code = ? AND " - "cov.deprecated != 1"; + if (discardSuperseded) { + sql = "SELECT cov.auth_name, cov.code, " + "ss.replacement_auth_name, ss.replacement_code FROM " + "coordinate_operation_view cov JOIN area " + "ON cov.area_of_use_auth_name = area.auth_name AND " + "cov.area_of_use_code = area.code " + "LEFT JOIN supersession ss ON " + "ss.superseded_table_name = cov.table_name AND " + "ss.superseded_auth_name = cov.auth_name AND " + "ss.superseded_code = cov.code AND " + "ss.superseded_table_name = ss.replacement_table_name " + "WHERE source_crs_auth_name = ? AND source_crs_code = ? AND " + "target_crs_auth_name = ? AND target_crs_code = ? AND " + "cov.deprecated != 1"; + } else { + sql = "SELECT cov.auth_name, cov.code FROM " + "coordinate_operation_view cov JOIN area " + "ON cov.area_of_use_auth_name = area.auth_name AND " + "cov.area_of_use_code = area.code " + "WHERE source_crs_auth_name = ? AND source_crs_code = ? AND " + "target_crs_auth_name = ? AND target_crs_code = ? AND " + "cov.deprecated != 1"; + } params = {sourceCRSAuthName, sourceCRSCode, targetCRSAuthName, targetCRSCode}; if (!getAuthority().empty()) { @@ -3123,7 +3142,29 @@ AuthorityFactory::createFromCoordinateReferenceSystemCodes( "east_lon) DESC, " "(CASE WHEN accuracy is NULL THEN 1 ELSE 0 END), accuracy"; res = d->run(sql, params); + std::set<std::pair<std::string, std::string>> setTransf; + if (discardSuperseded) { + for (const auto &row : res) { + const auto &auth_name = row[0]; + const auto &code = row[1]; + setTransf.insert( + std::pair<std::string, std::string>(auth_name, code)); + } + } for (const auto &row : res) { + if (discardSuperseded) { + const auto &replacement_auth_name = row[2]; + const auto &replacement_code = row[3]; + if (!replacement_auth_name.empty() && + setTransf.find(std::pair<std::string, std::string>( + replacement_auth_name, replacement_code)) != + setTransf.end()) { + // Skip transformations that are superseded by others that got + // returned in the result set. + continue; + } + } + const auto &auth_name = row[0]; const auto &code = row[1]; auto op = d->createFactory(auth_name)->createCoordinateOperation( @@ -3218,6 +3259,8 @@ static bool useIrrelevantPivot(const operation::CoordinateOperationNNPtr &op, * should be substituted to the official grid names. * @param discardIfMissingGrid Whether coordinate operations that reference * missing grids should be removed from the result set. + * @param discardSuperseded Whether cordinate operations that are superseded + * (but not deprecated) should be removed from the result set. * @param intermediateCRSAuthCodes List of (auth_name, code) of CRS that can be * used as potential intermediate CRS. If the list is empty, the database will * be used to find common CRS in operations involving both the source and @@ -3232,6 +3275,7 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( const std::string &sourceCRSAuthName, const std::string &sourceCRSCode, const std::string &targetCRSAuthName, const std::string &targetCRSCode, bool usePROJAlternativeGridNames, bool discardIfMissingGrid, + bool discardSuperseded, const std::vector<std::pair<std::string, std::string>> &intermediateCRSAuthCodes) const { @@ -3243,21 +3287,57 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( } const std::string sqlProlog( - "SELECT v1.auth_name AS auth_name1, v1.code AS code1, " - "v1.accuracy AS accuracy1, " - "v2.auth_name AS auth_name2, v2.code AS code2, " - "v2.accuracy as accuracy2, " - "a1.south_lat AS south_lat1, " - "a1.west_lon AS west_lon1, " - "a1.north_lat AS north_lat1, " - "a1.east_lon AS east_lon1, " - "a2.south_lat AS south_lat2, " - "a2.west_lon AS west_lon2, " - "a2.north_lat AS north_lat2, " - "a2.east_lon AS east_lon2 " - "FROM coordinate_operation_view v1 " - "JOIN coordinate_operation_view v2 "); + discardSuperseded + ? + + "SELECT v1.auth_name AS auth_name1, v1.code AS code1, " + "v1.accuracy AS accuracy1, " + "v2.auth_name AS auth_name2, v2.code AS code2, " + "v2.accuracy as accuracy2, " + "a1.south_lat AS south_lat1, " + "a1.west_lon AS west_lon1, " + "a1.north_lat AS north_lat1, " + "a1.east_lon AS east_lon1, " + "a2.south_lat AS south_lat2, " + "a2.west_lon AS west_lon2, " + "a2.north_lat AS north_lat2, " + "a2.east_lon AS east_lon2, " + "ss1.replacement_auth_name AS replacement_auth_name1, " + "ss1.replacement_code AS replacement_code1, " + "ss2.replacement_auth_name AS replacement_auth_name2, " + "ss2.replacement_code AS replacement_code2 " + "FROM coordinate_operation_view v1 " + "JOIN coordinate_operation_view v2 " + : + + "SELECT v1.auth_name AS auth_name1, v1.code AS code1, " + "v1.accuracy AS accuracy1, " + "v2.auth_name AS auth_name2, v2.code AS code2, " + "v2.accuracy as accuracy2, " + "a1.south_lat AS south_lat1, " + "a1.west_lon AS west_lon1, " + "a1.north_lat AS north_lat1, " + "a1.east_lon AS east_lon1, " + "a2.south_lat AS south_lat2, " + "a2.west_lon AS west_lon2, " + "a2.north_lat AS north_lat2, " + "a2.east_lon AS east_lon2 " + "FROM coordinate_operation_view v1 " + "JOIN coordinate_operation_view v2 "); + + const std::string joinSupersession( + "LEFT JOIN supersession ss1 ON " + "ss1.superseded_table_name = v1.table_name AND " + "ss1.superseded_auth_name = v1.auth_name AND " + "ss1.superseded_code = v1.code AND " + "ss1.superseded_table_name = ss1.replacement_table_name " + "LEFT JOIN supersession ss2 ON " + "ss2.superseded_table_name = v2.table_name AND " + "ss2.superseded_auth_name = v2.auth_name AND " + "ss2.superseded_code = v2.code AND " + "ss2.superseded_table_name = ss2.replacement_table_name "); const std::string joinArea( + (discardSuperseded ? joinSupersession : std::string()) + "JOIN area a1 ON v1.area_of_use_auth_name = a1.auth_name " "AND v1.area_of_use_code = a1.code " "JOIN area a2 ON v2.area_of_use_auth_name = a2.auth_name " @@ -3297,6 +3377,50 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( auto res = d->run(sql + additionalWhere + intermediateWhere + orderBy, params); + const auto filterOutSuperseded = [](SQLResultSet &&resultSet) { + std::set<std::pair<std::string, std::string>> setTransf1; + std::set<std::pair<std::string, std::string>> setTransf2; + for (const auto &row : resultSet) { + const auto &auth_name1 = row[0]; + const auto &code1 = row[1]; + // const auto &accuracy1 = row[2]; + const auto &auth_name2 = row[3]; + const auto &code2 = row[4]; + setTransf1.insert( + std::pair<std::string, std::string>(auth_name1, code1)); + setTransf2.insert( + std::pair<std::string, std::string>(auth_name2, code2)); + } + SQLResultSet filteredResultSet; + for (const auto &row : resultSet) { + const auto &replacement_auth_name1 = row[14]; + const auto &replacement_code1 = row[15]; + const auto &replacement_auth_name2 = row[16]; + const auto &replacement_code2 = row[17]; + if (!replacement_auth_name1.empty() && + setTransf1.find(std::pair<std::string, std::string>( + replacement_auth_name1, replacement_code1)) != + setTransf1.end()) { + // Skip transformations that are superseded by others that got + // returned in the result set. + continue; + } + if (!replacement_auth_name2.empty() && + setTransf2.find(std::pair<std::string, std::string>( + replacement_auth_name2, replacement_code2)) != + setTransf2.end()) { + // Skip transformations that are superseded by others that got + // returned in the result set. + continue; + } + filteredResultSet.emplace_back(row); + } + return filteredResultSet; + }; + + if (discardSuperseded) { + res = filterOutSuperseded(std::move(res)); + } for (const auto &row : res) { const auto &auth_name1 = row[0]; const auto &code1 = row[1]; @@ -3333,6 +3457,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( intermediateWhere = buildIntermediateWhere(intermediateCRSAuthCodes, "target", "target"); res = d->run(sql + additionalWhere + intermediateWhere + orderBy, params); + if (discardSuperseded) { + res = filterOutSuperseded(std::move(res)); + } for (const auto &row : res) { const auto &auth_name1 = row[0]; const auto &code1 = row[1]; @@ -3369,6 +3496,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( intermediateWhere = buildIntermediateWhere(intermediateCRSAuthCodes, "source", "source"); res = d->run(sql + additionalWhere + intermediateWhere + orderBy, params); + if (discardSuperseded) { + res = filterOutSuperseded(std::move(res)); + } for (const auto &row : res) { const auto &auth_name1 = row[0]; const auto &code1 = row[1]; @@ -3405,6 +3535,9 @@ AuthorityFactory::createFromCRSCodesWithIntermediates( intermediateWhere = buildIntermediateWhere(intermediateCRSAuthCodes, "source", "target"); res = d->run(sql + additionalWhere + intermediateWhere + orderBy, params); + if (discardSuperseded) { + res = filterOutSuperseded(std::move(res)); + } for (const auto &row : res) { const auto &auth_name1 = row[0]; const auto &code1 = row[1]; diff --git a/src/projinfo.cpp b/src/projinfo.cpp index d13b5ee5..ddcc09da 100644 --- a/src/projinfo.cpp +++ b/src/projinfo.cpp @@ -80,7 +80,8 @@ static void usage() { << " [--spatial-test contains|intersects]" << std::endl << " [--crs-extent-use none|both|intersection|smallest]" << std::endl - << " [--grid-check none|discard_missing|sort]" + << " [--grid-check none|discard_missing|sort] " + "[--show-superseded]" << std::endl << " [--pivot-crs none|{auth:code[,auth:code]*}]" << std::endl @@ -477,7 +478,7 @@ static void outputOperations( bool allowPivots, const std::vector<std::pair<std::string, std::string>> &pivots, const std::string &authority, bool usePROJGridAlternatives, - const OutputOptions &outputOpt, bool summary) { + bool showSuperseded, const OutputOptions &outputOpt, bool summary) { auto sourceObj = buildObject(dbContext, sourceCRSStr, true, "source CRS", false); auto sourceCRS = nn_dynamic_pointer_cast<CRS>(sourceObj); @@ -509,6 +510,7 @@ static void outputOperations( ctxt->setAllowUseIntermediateCRS(allowPivots); ctxt->setIntermediateCRS(pivots); ctxt->setUsePROJAlternativeGridNames(usePROJGridAlternatives); + ctxt->setDiscardSuperseded(!showSuperseded); list = CoordinateOperationFactory::create()->createOperations( NN_NO_CHECK(sourceCRS), NN_NO_CHECK(targetCRS), ctxt); } catch (const std::exception &e) { @@ -582,6 +584,7 @@ int main(int argc, char **argv) { bool guessDialect = false; std::string authority; bool identify = false; + bool showSuperseded = false; for (int i = 1; i < argc; i++) { std::string arg(argv[i]); @@ -807,6 +810,8 @@ int main(int argc, char **argv) { authority = argv[i]; } else if (arg == "--identify") { identify = true; + } else if (arg == "--show-superseded") { + showSuperseded = true; } else if (arg == "-?" || arg == "--help") { usage(); } else if (arg[0] == '-') { @@ -1000,10 +1005,10 @@ int main(int argc, char **argv) { } } - outputOperations(dbContext, sourceCRSStr, targetCRSStr, bboxFilter, - spatialCriterion, crsExtentUse, gridAvailabilityUse, - allowPivots, pivots, authority, - usePROJGridAlternatives, outputOpt, summary); + outputOperations( + dbContext, sourceCRSStr, targetCRSStr, bboxFilter, spatialCriterion, + crsExtentUse, gridAvailabilityUse, allowPivots, pivots, authority, + usePROJGridAlternatives, showSuperseded, outputOpt, summary); } return 0; |
