aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-01-25 02:23:18 +0100
committerEven Rouault <even.rouault@spatialys.com>2020-01-25 02:23:18 +0100
commit680d1eb93bfd0ffa274da2a28dc7fce704a059b9 (patch)
tree3e4e4fa40d594c4311bffcc9216409d985148f0f /src
parent1039889c424af9fd89a637e610c4243839d3cb86 (diff)
downloadPROJ-680d1eb93bfd0ffa274da2a28dc7fce704a059b9.tar.gz
PROJ-680d1eb93bfd0ffa274da2a28dc7fce704a059b9.zip
Implement RFC 5
Diffstat (limited to 'src')
-rw-r--r--src/filemanager.cpp146
-rw-r--r--src/iso19111/coordinateoperation.cpp74
-rw-r--r--src/iso19111/factory.cpp27
-rw-r--r--src/proj_constants.h2
4 files changed, 186 insertions, 63 deletions
diff --git a/src/filemanager.cpp b/src/filemanager.cpp
index 005e734b..4218fde1 100644
--- a/src/filemanager.cpp
+++ b/src/filemanager.cpp
@@ -40,6 +40,8 @@
#include "filemanager.hpp"
#include "proj.h"
#include "proj/internal/internal.hpp"
+#include "proj/internal/io_internal.hpp"
+#include "proj/io.hpp"
#include "proj_internal.h"
#include <sys/stat.h>
@@ -1411,6 +1413,20 @@ static void *pj_open_file_with_manager(projCtx ctx, const char *name,
.release();
}
+// ---------------------------------------------------------------------------
+
+static NS_PROJ::io::DatabaseContextPtr getDBcontext(PJ_CONTEXT *ctx) {
+ try {
+ if (ctx->cpp_context == nullptr) {
+ ctx->cpp_context = new projCppContext(ctx);
+ }
+ return ctx->cpp_context->getDatabaseContext().as_nullable();
+ } catch (const std::exception &e) {
+ pj_log(ctx, PJ_LOG_DEBUG, "%s", e.what());
+ return nullptr;
+ }
+}
+
/************************************************************************/
/* FileManager::open_resource_file() */
/************************************************************************/
@@ -1426,27 +1442,54 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
reinterpret_cast<NS_PROJ::File *>(pj_open_lib_internal(
ctx, name, "rb", pj_open_file_with_manager, nullptr, 0)));
- // Retry with a .tif extension if the file name doesn't end with .tif
+ // Retry with the new proj grid name if the file name doesn't end with .tif
if (file == nullptr && !is_tilde_slash(name) &&
!is_rel_or_absolute_filename(name) && !starts_with(name, "http://") &&
!starts_with(name, "https://") && strcmp(name, "proj.db") != 0 &&
strstr(name, ".tif") == nullptr) {
- std::string filename(name);
- auto pos = filename.rfind('.');
- if (pos + 4 == filename.size()) {
- filename = filename.substr(0, pos) + ".tif";
- file.reset(reinterpret_cast<NS_PROJ::File *>(
- pj_open_lib_internal(ctx, filename.c_str(), "rb",
- pj_open_file_with_manager, nullptr, 0)));
- } else {
- // For example for resource files like 'alaska'
- filename += ".tif";
- file.reset(reinterpret_cast<NS_PROJ::File *>(
- pj_open_lib_internal(ctx, filename.c_str(), "rb",
- pj_open_file_with_manager, nullptr, 0)));
+
+ auto dbContext = getDBcontext(ctx);
+ if (dbContext) {
+ try {
+ auto filename = dbContext->getProjGridName(name);
+ if (!filename.empty()) {
+ file.reset(reinterpret_cast<NS_PROJ::File *>(
+ pj_open_lib_internal(ctx, filename.c_str(), "rb",
+ pj_open_file_with_manager, nullptr,
+ 0)));
+ if (file) {
+ pj_ctx_set_errno(ctx, 0);
+ }
+ }
+ } catch (const std::exception &e) {
+ pj_log(ctx, PJ_LOG_DEBUG, "%s", e.what());
+ return nullptr;
+ }
}
- if (file) {
- pj_ctx_set_errno(ctx, 0);
+ }
+ // Retry with the old proj grid name if the file name ends with .tif
+ else if (file == nullptr && !is_tilde_slash(name) &&
+ !is_rel_or_absolute_filename(name) &&
+ !starts_with(name, "http://") && !starts_with(name, "https://") &&
+ strstr(name, ".tif") != nullptr) {
+
+ auto dbContext = getDBcontext(ctx);
+ if (dbContext) {
+ try {
+ auto filename = dbContext->getOldProjGridName(name);
+ if (!filename.empty()) {
+ file.reset(reinterpret_cast<NS_PROJ::File *>(
+ pj_open_lib_internal(ctx, filename.c_str(), "rb",
+ pj_open_file_with_manager, nullptr,
+ 0)));
+ if (file) {
+ pj_ctx_set_errno(ctx, 0);
+ }
+ }
+ } catch (const std::exception &e) {
+ pj_log(ctx, PJ_LOG_DEBUG, "%s", e.what());
+ return nullptr;
+ }
}
}
@@ -1459,35 +1502,12 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
remote_file += '/';
}
remote_file += name;
- auto pos = remote_file.rfind('.');
- if (pos + 4 == remote_file.size()) {
- remote_file = remote_file.substr(0, pos) + ".tif";
- file = open(ctx, remote_file.c_str(),
- NS_PROJ::FileAccess::READ_ONLY);
- if (file) {
- pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s",
- remote_file.c_str());
- pj_ctx_set_errno(ctx, 0);
- }
- } else {
- // For example for resource files like 'alaska'
- auto remote_file_tif = remote_file + ".tif";
- file = open(ctx, remote_file_tif.c_str(),
- NS_PROJ::FileAccess::READ_ONLY);
- if (file) {
- pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s",
- remote_file_tif.c_str());
- pj_ctx_set_errno(ctx, 0);
- } else {
- // Init files
- file = open(ctx, remote_file.c_str(),
- NS_PROJ::FileAccess::READ_ONLY);
- if (file) {
- pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s",
- remote_file.c_str());
- pj_ctx_set_errno(ctx, 0);
- }
- }
+ file =
+ open(ctx, remote_file.c_str(), NS_PROJ::FileAccess::READ_ONLY);
+ if (file) {
+ pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s",
+ remote_file.c_str());
+ pj_ctx_set_errno(ctx, 0);
}
}
}
@@ -1522,7 +1542,8 @@ PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) {
* as a short filename.
*
* @param ctx context.
- * @param short_filename short filename (e.g. egm96_15.gtx). Must not be NULL.
+ * @param short_filename short filename (e.g. us_nga_egm96_15.tif).
+ * Must not be NULL.
* @param out_full_filename output buffer, of size out_full_filename_size, that
* will receive the full filename on success.
* Will be zero-terminated.
@@ -1531,14 +1552,33 @@ PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) {
*/
int pj_find_file(projCtx ctx, const char *short_filename,
char *out_full_filename, size_t out_full_filename_size) {
- auto f = reinterpret_cast<NS_PROJ::File *>(pj_open_lib_internal(
- ctx, short_filename, "rb", pj_open_file_with_manager, out_full_filename,
- out_full_filename_size));
- if (f != nullptr) {
- delete f;
- return 1;
+ auto file = std::unique_ptr<NS_PROJ::File>(
+ reinterpret_cast<NS_PROJ::File *>(pj_open_lib_internal(
+ ctx, short_filename, "rb", pj_open_file_with_manager,
+ out_full_filename, out_full_filename_size)));
+
+ // Retry with the old proj grid name if the file name ends with .tif
+ if (file == nullptr && strstr(short_filename, ".tif") != nullptr) {
+
+ auto dbContext = getDBcontext(ctx);
+ if (dbContext) {
+ try {
+ auto filename = dbContext->getOldProjGridName(short_filename);
+ if (!filename.empty()) {
+ file.reset(reinterpret_cast<NS_PROJ::File *>(
+ pj_open_lib_internal(ctx, filename.c_str(), "rb",
+ pj_open_file_with_manager,
+ out_full_filename,
+ out_full_filename_size)));
+ }
+ } catch (const std::exception &e) {
+ pj_log(ctx, PJ_LOG_DEBUG, "%s", e.what());
+ return false;
+ }
+ }
}
- return 0;
+
+ return file != nullptr;
}
/************************************************************************/
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index a8c7c902..6d97adc3 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -8448,6 +8448,29 @@ static const std::string &_getCTABLE2Filename(const Transformation *op,
//! @cond Doxygen_Suppress
static const std::string &
+_getHorizontalShiftGTIFFFilename(const Transformation *op, bool allowInverse) {
+ const auto &l_method = op->method();
+ const auto &methodName = l_method->nameStr();
+ if (ci_equal(methodName, PROJ_WKT2_NAME_METHOD_HORIZONTAL_SHIFT_GTIFF) ||
+ (allowInverse &&
+ ci_equal(methodName,
+ INVERSE_OF + PROJ_WKT2_NAME_METHOD_HORIZONTAL_SHIFT_GTIFF))) {
+ const auto &fileParameter = op->parameterValue(
+ EPSG_NAME_PARAMETER_LATITUDE_LONGITUDE_DIFFERENCE_FILE,
+ EPSG_CODE_PARAMETER_LATITUDE_LONGITUDE_DIFFERENCE_FILE);
+ if (fileParameter &&
+ fileParameter->type() == ParameterValue::Type::FILENAME) {
+ return fileParameter->valueFile();
+ }
+ }
+ return nullString;
+}
+//! @endcond
+
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+static const std::string &
_getHeightToGeographic3DFilename(const Transformation *op, bool allowInverse) {
const auto &methodName = op->method()->nameStr();
@@ -8658,7 +8681,30 @@ TransformationNNPtr Transformation::substitutePROJAlternativeGridNames(
const auto &l_sourceCRS = sourceCRS();
const auto &l_targetCRS = targetCRS();
const auto &l_accuracies = coordinateOperationAccuracies();
- if (projGridFormat == "NTv1") {
+ if (projGridFormat == "GTiff") {
+ auto parameters =
+ std::vector<OperationParameterNNPtr>{createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_LATITUDE_LONGITUDE_DIFFERENCE_FILE)};
+ auto methodProperties = util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ PROJ_WKT2_NAME_METHOD_HORIZONTAL_SHIFT_GTIFF);
+ auto values = std::vector<ParameterValueNNPtr>{
+ ParameterValue::createFilename(projFilename)};
+ if (inverseDirection) {
+ return create(createPropertiesForInverse(
+ self.as_nullable().get(), true, false),
+ l_targetCRS, l_sourceCRS, nullptr,
+ methodProperties, parameters, values,
+ l_accuracies)
+ ->inverseAsTransformation();
+
+ } else {
+ return create(createSimilarPropertiesTransformation(self),
+ l_sourceCRS, l_targetCRS, nullptr,
+ methodProperties, parameters, values,
+ l_accuracies);
+ }
+ } else if (projGridFormat == "NTv1") {
if (inverseDirection) {
return createNTv1(createPropertiesForInverse(
self.as_nullable().get(), true, false),
@@ -9336,10 +9382,14 @@ void Transformation::_exportToPROJString(
const auto &NTv1Filename = _getNTv1Filename(this, true);
const auto &NTv2Filename = _getNTv2Filename(this, true);
const auto &CTABLE2Filename = _getCTABLE2Filename(this, true);
+ const auto &HorizontalShiftGTIFFFilename =
+ _getHorizontalShiftGTIFFFilename(this, true);
const auto &hGridShiftFilename =
- !NTv1Filename.empty() ? NTv1Filename : !NTv2Filename.empty()
- ? NTv2Filename
- : CTABLE2Filename;
+ !HorizontalShiftGTIFFFilename.empty()
+ ? HorizontalShiftGTIFFFilename
+ : !NTv1Filename.empty() ? NTv1Filename : !NTv2Filename.empty()
+ ? NTv2Filename
+ : CTABLE2Filename;
if (!hGridShiftFilename.empty()) {
auto sourceCRSGeog =
dynamic_cast<const crs::GeographicCRS *>(sourceCRS().get());
@@ -9417,11 +9467,15 @@ void Transformation::_exportToPROJString(
if (fileParameter &&
fileParameter->type() == ParameterValue::Type::FILENAME) {
formatter->addStep("vgridshift");
- // The vertcon grids go from NGVD 29 to NAVD 88, with units
- // in millimeter (see
- // https://github.com/OSGeo/proj.4/issues/1071)
formatter->addParam("grids", fileParameter->valueFile());
- formatter->addParam("multiplier", 0.001);
+ if (fileParameter->valueFile().find(".tif") != std::string::npos) {
+ formatter->addParam("multiplier", 1.0);
+ } else {
+ // The vertcon grids go from NGVD 29 to NAVD 88, with units
+ // in millimeter (see
+ // https://github.com/OSGeo/proj.4/issues/1071), for gtx files
+ formatter->addParam("multiplier", 0.001);
+ }
return;
}
}
@@ -11155,7 +11209,9 @@ struct FilterResults {
!gridDesc.available) {
gridsAvailable = false;
}
- if (gridDesc.packageName.empty() && !gridDesc.available) {
+ if (gridDesc.packageName.empty() &&
+ !(!gridDesc.url.empty() && gridDesc.openLicense) &&
+ !gridDesc.available) {
gridsKnown = false;
}
}
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 7e680d31..54aa993f 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -987,7 +987,8 @@ bool DatabaseContext::lookForGridInfo(
openLicense = (row[3].empty() ? row[4] : row[3]) == "1";
directDownload = (row[5].empty() ? row[6] : row[5]) == "1";
- if (considerKnownGridsAsAvailable && !packageName.empty()) {
+ if (considerKnownGridsAsAvailable &&
+ (!packageName.empty() || (!url.empty() && openLicense))) {
gridAvailable = true;
}
@@ -1012,6 +1013,30 @@ bool DatabaseContext::isKnownName(const std::string &name,
sql += "\" WHERE name = ? LIMIT 1";
return !d->run(sql, {name}).empty();
}
+// ---------------------------------------------------------------------------
+
+std::string
+DatabaseContext::getProjGridName(const std::string &oldProjGridName) {
+ auto res = d->run("SELECT proj_grid_name FROM grid_alternatives WHERE "
+ "old_proj_grid_name = ?",
+ {oldProjGridName});
+ if (res.empty()) {
+ return std::string();
+ }
+ return res.front()[0];
+}
+
+// ---------------------------------------------------------------------------
+
+std::string DatabaseContext::getOldProjGridName(const std::string &gridName) {
+ auto res = d->run("SELECT old_proj_grid_name FROM grid_alternatives WHERE "
+ "proj_grid_name = ?",
+ {gridName});
+ if (res.empty()) {
+ return std::string();
+ }
+ return res.front()[0];
+}
// ---------------------------------------------------------------------------
diff --git a/src/proj_constants.h b/src/proj_constants.h
index d5b484c6..54dc7873 100644
--- a/src/proj_constants.h
+++ b/src/proj_constants.h
@@ -508,6 +508,8 @@
#define PROJ_WKT2_NAME_METHOD_CTABLE2 "CTABLE2"
+#define PROJ_WKT2_NAME_METHOD_HORIZONTAL_SHIFT_GTIFF "HORIZONTAL_SHIFT_GTIFF"
+
/* ------------------------------------------------------------------------ */
#define EPSG_CODE_METHOD_VERTCON 9658