From 93dc8422c4cddf5fa52824222143effa6bb4d67f Mon Sep 17 00:00:00 2001 From: Javier Jimenez Shaw Date: Sat, 24 Apr 2021 10:37:19 +0200 Subject: Add proj_get_geoid_models_from_database() (#2681) to list all geoid model names that apply to a vertical CRS --- src/iso19111/factory.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'src/iso19111/factory.cpp') diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index fabf57e1..d95ccbf4 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -5765,6 +5765,88 @@ AuthorityFactory::createFromCoordinateReferenceSystemCodes( // --------------------------------------------------------------------------- +/** \brief Returns a list of geoid models available for that crs + * + * The list includes the geoid models connected directly with the crs, + * or via "Height Depth Reversal" or "Change of Vertical Unit" transformations + * + * @param code crs code allocated by authority. + * @return list of geoid model names + * @throw FactoryException + */ + +std::list +AuthorityFactory::getGeoidModels(const std::string &code) const { + + ListOfParams params; + std::string sql; + sql += "SELECT DISTINCT GM0.name " + " FROM geoid_model GM0 " + "INNER JOIN grid_transformation GT0 " + " ON GT0.code = GM0.operation_code " + " AND GT0.auth_name = GM0.operation_auth_name " + " AND GT0.target_crs_code = ? "; + params.emplace_back(code); + if (d->hasAuthorityRestriction()) { + sql += " AND GT0.target_crs_auth_name = ? "; + params.emplace_back(d->authority()); + } + + /// The second part of the query is for CRSs that use that geoid model via + /// Height Depth Reversal (EPSG:1068) or Change of Vertical Unit (EPSG:1069) + sql += "UNION " + "SELECT DISTINCT GM0.name " + " FROM geoid_model GM0 " + "INNER JOIN grid_transformation GT1 " + " ON GT1.code = GM0.operation_code " + " AND GT1.auth_name = GM0.operation_auth_name " + "INNER JOIN other_transformation OT1 " + " ON OT1.source_crs_code = GT1.target_crs_code " + " AND OT1.source_crs_auth_name = GT1.target_crs_auth_name " + " AND OT1.method_auth_name = 'EPSG' " + " AND OT1.method_code IN (1068, 1069, 1104) " + " AND OT1.target_crs_code = ? "; + params.emplace_back(code); + if (d->hasAuthorityRestriction()) { + sql += " AND OT1.target_crs_auth_name = ? "; + params.emplace_back(d->authority()); + } + + /// The third part of the query is for CRSs that use that geoid model via + /// other_transformation table twice, like transforming depth and feet + sql += "UNION " + "SELECT DISTINCT GM0.name " + " FROM geoid_model GM0 " + "INNER JOIN grid_transformation GT1 " + " ON GT1.code = GM0.operation_code " + " AND GT1.auth_name = GM0.operation_auth_name " + "INNER JOIN other_transformation OT1 " + " ON OT1.source_crs_code = GT1.target_crs_code " + " AND OT1.source_crs_auth_name = GT1.target_crs_auth_name " + " AND OT1.method_auth_name = 'EPSG' " + " AND OT1.method_code IN (1068, 1069, 1104) " + "INNER JOIN other_transformation OT2 " + " ON OT2.source_crs_code = OT1.target_crs_code " + " AND OT2.source_crs_auth_name = OT1.target_crs_auth_name " + " AND OT2.method_code IN (1068, 1069, 1104) " + " AND OT2.target_crs_code = ? "; + params.emplace_back(code); + if (d->hasAuthorityRestriction()) { + sql += " AND OT2.target_crs_auth_name = ? "; + params.emplace_back(d->authority()); + } + sql += " ORDER BY 1 "; + + auto sqlRes = d->run(sql, params); + std::list res; + for (const auto &row : sqlRes) { + res.push_back(row[0]); + } + return res; +} + +// --------------------------------------------------------------------------- + /** \brief Returns a list operation::CoordinateOperation between two CRS. * * The list is ordered with preferred operations first. No attempt is made -- cgit v1.2.3