aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111/factory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/iso19111/factory.cpp')
-rw-r--r--src/iso19111/factory.cpp109
1 files changed, 80 insertions, 29 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 81abcdf1..4515188a 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Project: PROJ
- * Purpose: ISO19111:2018 implementation
+ * Purpose: ISO19111:2019 implementation
* Author: Even Rouault <even dot rouault at spatialys dot com>
*
******************************************************************************
@@ -259,7 +259,7 @@ struct DatabaseContext::Private {
static void getFromCache(LRUCacheOfObjects &cache, const std::string &code,
util::BaseObjectPtr &obj);
- void closeDB();
+ void closeDB() noexcept;
// cppcheck-suppress functionStatic
void registerFunctions();
@@ -295,7 +295,7 @@ DatabaseContext::Private::~Private() {
// ---------------------------------------------------------------------------
-void DatabaseContext::Private::closeDB() {
+void DatabaseContext::Private::closeDB() noexcept {
if (detach_) {
// Workaround a bug visible in SQLite 3.8.1 and 3.8.2 that causes
@@ -309,7 +309,10 @@ void DatabaseContext::Private::closeDB() {
// https://github.com/mackyle/sqlite/commit/ccf328c4318eacedab9ed08c404bc4f402dcad19
// also seemed to hide the issue.
// Detaching a database hides the issue, not sure if it is by chance...
- run("DETACH DATABASE db_0");
+ try {
+ run("DETACH DATABASE db_0");
+ } catch (...) {
+ }
detach_ = false;
}
@@ -611,11 +614,16 @@ void DatabaseContext::Private::setHandle(sqlite3 *sqlite_handle) {
// ---------------------------------------------------------------------------
std::vector<std::string> DatabaseContext::Private::getDatabaseStructure() {
- auto sqlRes = run("SELECT sql FROM sqlite_master WHERE type "
- "IN ('table', 'trigger', 'view') ORDER BY type");
+ const char *sqls[] = {
+ "SELECT sql FROM sqlite_master WHERE type = 'table'",
+ "SELECT sql FROM sqlite_master WHERE type = 'view'",
+ "SELECT sql FROM sqlite_master WHERE type = 'trigger'"};
std::vector<std::string> res;
- for (const auto &row : sqlRes) {
- res.emplace_back(row[0]);
+ for (const auto &sql : sqls) {
+ auto sqlRes = run(sql);
+ for (const auto &row : sqlRes) {
+ res.emplace_back(row[0]);
+ }
}
return res;
}
@@ -1024,8 +1032,8 @@ bool DatabaseContext::lookForGridInfo(const std::string &projFilename,
info.url = url;
info.directDownload = directDownload;
info.openLicense = openLicense;
- info.gridAvailable = gridAvailable;
}
+ info.gridAvailable = gridAvailable;
info.found = ret;
d->cache(projFilename, info);
return ret;
@@ -1359,6 +1367,15 @@ const DatabaseContextNNPtr &AuthorityFactory::databaseContext() const {
// ---------------------------------------------------------------------------
+//! @cond Doxygen_Suppress
+AuthorityFactory::CRSInfo::CRSInfo()
+ : authName{}, code{}, name{}, type{ObjectType::CRS}, deprecated{},
+ bbox_valid{}, west_lon_degree{}, south_lat_degree{}, east_lon_degree{},
+ north_lat_degree{}, areaName{}, projectionMethodName{} {}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
/** \brief Returns an arbitrary object from a code.
*
* The returned object will typically be an instance of Datum,
@@ -1606,10 +1623,12 @@ static double normalizeMeasure(const std::string &uom_code,
assert(seconds.size() == precision - 2);
normalized_value =
(normalized_value < 0 ? -1.0 : 1.0) *
- (int(std::fabs(normalized_value)) + c_locale_stod(minutes) / 60. +
+ (std::floor(std::fabs(normalized_value)) +
+ c_locale_stod(minutes) / 60. +
(c_locale_stod(seconds) / std::pow(10, seconds.size() - 2)) /
3600.);
normalized_uom_code = common::UnitOfMeasure::DEGREE.code();
+ /* coverity[overflow_sink] */
return normalized_value;
} else {
normalized_uom_code = uom_code;
@@ -2394,6 +2413,11 @@ AuthorityFactory::createProjectedCRS(const std::string &code) const {
auto conv = d->createFactory(conversion_auth_name)
->createConversion(conversion_code);
+ if (conv->nameStr() == "unnamed") {
+ conv = conv->shallowClone();
+ conv->setProperties(util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY, name));
+ }
auto cartesianCS = util::nn_dynamic_pointer_cast<cs::CartesianCS>(cs);
if (cartesianCS) {
@@ -2470,6 +2494,8 @@ crs::CRSNNPtr AuthorityFactory::createCoordinateReferenceSystem(
return createCoordinateReferenceSystem(code, true);
}
+//! @cond Doxygen_Suppress
+
crs::CRSNNPtr
AuthorityFactory::createCoordinateReferenceSystem(const std::string &code,
bool allowCompound) const {
@@ -2499,6 +2525,9 @@ AuthorityFactory::createCoordinateReferenceSystem(const std::string &code,
}
throw FactoryException("unhandled CRS type: " + type);
}
+
+//! @endcond
+
// ---------------------------------------------------------------------------
//! @cond Doxygen_Suppress
@@ -2588,7 +2617,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"rate_scale_difference, rate_scale_difference_uom_auth_name, "
"rate_scale_difference_uom_code, epoch, epoch_uom_auth_name, "
"epoch_uom_code, px, py, pz, pivot_uom_auth_name, pivot_uom_code, "
- "deprecated FROM "
+ "operation_version, deprecated FROM "
"helmert_transformation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -2649,6 +2678,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
const auto &pivot_uom_auth_name = row[idx++];
const auto &pivot_uom_code = row[idx++];
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -2789,6 +2819,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
auto propsMethod =
util::PropertyMap()
@@ -2819,8 +2853,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"grid_name, "
"grid2_param_auth_name, grid2_param_code, grid2_param_name, "
"grid2_name, "
- "interpolation_crs_auth_name, interpolation_crs_code, deprecated "
- "FROM "
+ "interpolation_crs_auth_name, interpolation_crs_code, "
+ "operation_version, deprecated FROM "
"grid_transformation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -2852,7 +2886,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
const auto &grid2_name = row[idx++];
const auto &interpolation_crs_auth_name = row[idx++];
const auto &interpolation_crs_code = row[idx++];
-
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -2898,6 +2932,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
auto propsMethod =
util::PropertyMap()
.set(metadata::Identifier::CODESPACE_KEY, method_auth_name)
@@ -2939,8 +2977,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
buffer << ", param" << i << "_uom_auth_name";
buffer << ", param" << i << "_uom_code";
}
- buffer << ", deprecated FROM other_transformation WHERE auth_name = ? "
- "AND code = ?";
+ buffer << ", operation_version, deprecated FROM other_transformation "
+ "WHERE auth_name = ? AND code = ?";
auto res = d->runWithCodeParam(buffer.str(), code);
if (res.empty()) {
@@ -2993,6 +3031,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
}
idx = base_param_idx + 6 * N_MAX_PARAMS;
+ const auto &operation_version = row[idx++];
const auto &deprecated_str = row[idx++];
const bool deprecated = deprecated_str == "1";
assert(idx == row.size());
@@ -3007,6 +3046,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
if (!accuracy.empty()) {
@@ -3060,7 +3103,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
"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, deprecated FROM "
+ "step3_auth_name, step3_code, operation_version, deprecated FROM "
"concatenated_operation WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -3085,6 +3128,7 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
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";
@@ -3118,6 +3162,10 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
auto props =
d->createProperties(code, name, deprecated,
area_of_use_auth_name, area_of_use_code);
+ if (!operation_version.empty()) {
+ props.set(operation::CoordinateOperation::OPERATION_VERSION_KEY,
+ operation_version);
+ }
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
if (!accuracy.empty()) {
@@ -3873,7 +3921,7 @@ AuthorityFactory::getDescriptionText(const std::string &code) const {
/** \brief Return a list of information on CRS objects
*
* This is functionnaly equivalent of listing the codes from an authority,
- * instanciating
+ * instantiating
* a CRS object for each of them and getting the information from this CRS
* object, but this implementation has much less overhead.
*
@@ -3896,13 +3944,16 @@ std::list<AuthorityFactory::CRSInfo> AuthorityFactory::getCRSInfoList() const {
sql += "SELECT c.auth_name, c.code, c.name, 'projected', "
"c.deprecated, "
"a.west_lon, a.south_lat, a.east_lon, a.north_lat, "
- "a.name, conv.method_name FROM projected_crs c "
+ "a.name, cm.name AS conversion_method_name FROM projected_crs c "
"JOIN area a ON "
"c.area_of_use_auth_name = a.auth_name AND "
"c.area_of_use_code = a.code "
- "LEFT JOIN conversion conv ON "
+ "LEFT JOIN conversion_table conv ON "
"c.conversion_auth_name = conv.auth_name AND "
- "c.conversion_code = conv.code";
+ "c.conversion_code = conv.code "
+ "LEFT JOIN conversion_method cm ON "
+ "conv.method_auth_name = cm.auth_name AND "
+ "conv.method_code = cm.code";
if (d->hasAuthorityRestriction()) {
sql += " WHERE c.auth_name = ?";
params.emplace_back(d->authority());
@@ -4625,9 +4676,9 @@ AuthorityFactory::createProjectedCRSFromExisting(
std::string sql(
"SELECT projected_crs.auth_name, projected_crs.code FROM projected_crs "
- "JOIN conversion ON "
- "projected_crs.conversion_auth_name = conversion.auth_name AND "
- "projected_crs.conversion_code = conversion.code WHERE "
+ "JOIN conversion_table conv ON "
+ "projected_crs.conversion_auth_name = conv.auth_name AND "
+ "projected_crs.conversion_code = conv.code WHERE "
"projected_crs.deprecated = 0 AND ");
ListOfParams params;
if (!candidatesGeodCRS.empty()) {
@@ -4635,8 +4686,8 @@ AuthorityFactory::createProjectedCRSFromExisting(
"projected_crs.geodetic_crs_");
sql += " AND ";
}
- sql += "conversion.method_auth_name = 'EPSG' AND "
- "conversion.method_code = ?";
+ sql += "conv.method_auth_name = 'EPSG' AND "
+ "conv.method_code = ?";
params.emplace_back(toString(methodEPSGCode));
if (d->hasAuthorityRestriction()) {
sql += " AND projected_crs.auth_name = ?";
@@ -4663,11 +4714,11 @@ AuthorityFactory::createProjectedCRSFromExisting(
if (unit == common::UnitOfMeasure::DEGREE &&
geogCRS->coordinateSystem()->axisList()[0]->unit() == unit) {
const auto iParamAsStr(toString(iParam));
- sql += " AND conversion.param";
+ sql += " AND conv.param";
sql += iParamAsStr;
- sql += "_code = ? AND conversion.param";
+ sql += "_code = ? AND conv.param";
sql += iParamAsStr;
- sql += "_auth_name = 'EPSG' AND conversion.param";
+ sql += "_auth_name = 'EPSG' AND conv.param";
sql += iParamAsStr;
sql += "_value BETWEEN ? AND ?";
// As angles might be expressed with the odd unit EPSG:9110