aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111/io.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/iso19111/io.cpp')
-rw-r--r--src/iso19111/io.cpp61
1 files changed, 40 insertions, 21 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 3517c225..60c28201 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4746,8 +4746,7 @@ struct PROJStringFormatter::Private {
bool omitProjLongLatIfPossible_ = false;
bool omitZUnitConversion_ = false;
DatabaseContextPtr dbContext_{};
- bool useETMercForTMerc_ = false;
- bool useETMercForTMercSet_ = false;
+ bool useApproxTMerc_ = false;
bool addNoDefs_ = true;
bool coordOperationOptimizations_ = false;
bool crsExport_ = false;
@@ -4803,11 +4802,9 @@ PROJStringFormatter::create(Convention conventionIn,
// ---------------------------------------------------------------------------
-/** \brief Set whether Extended Transverse Mercator (etmerc) should be used
- * instead of tmerc */
-void PROJStringFormatter::setUseETMercForTMerc(bool flag) {
- d->useETMercForTMerc_ = flag;
- d->useETMercForTMercSet_ = true;
+/** \brief Set whether approximate Transverse Mercator or UTM should be used */
+void PROJStringFormatter::setUseApproxTMerc(bool flag) {
+ d->useApproxTMerc_ = flag;
}
// ---------------------------------------------------------------------------
@@ -5256,9 +5253,8 @@ PROJStringFormatter::Convention PROJStringFormatter::convention() const {
// ---------------------------------------------------------------------------
-bool PROJStringFormatter::getUseETMercForTMerc(bool &settingSetOut) const {
- settingSetOut = d->useETMercForTMercSet_;
- return d->useETMercForTMerc_;
+bool PROJStringFormatter::getUseApproxTMerc() const {
+ return d->useApproxTMerc_;
}
// ---------------------------------------------------------------------------
@@ -5285,6 +5281,9 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
const char *c_str = projString.c_str();
std::vector<std::string> tokens;
+ bool hasProj = false;
+ bool hasInit = false;
+ bool hasPipeline = false;
{
size_t i = 0;
while (true) {
@@ -5310,24 +5309,29 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
}
token += c_str[i];
}
+ if (in_string) {
+ throw ParsingException("Unbalanced double quote");
+ }
if (token.empty()) {
break;
}
+ if (!hasPipeline &&
+ (token == "proj=pipeline" || token == "+proj=pipeline")) {
+ hasPipeline = true;
+ } else if (!hasProj && (starts_with(token, "proj=") ||
+ starts_with(token, "+proj="))) {
+ hasProj = true;
+ } else if (!hasInit && (starts_with(token, "init=") ||
+ starts_with(token, "+init="))) {
+ hasInit = true;
+ }
tokens.emplace_back(token);
}
}
bool prevWasTitle = false;
- if (projString.find("proj=pipeline") == std::string::npos) {
- const bool hasProj = projString.find("proj=") == 0 ||
- projString.find("+proj=") == 0 ||
- projString.find(" proj=") != std::string::npos ||
- projString.find(" +proj=") != std::string::npos;
- const bool hasInit = projString.find("init=") == 0 ||
- projString.find("+init=") == 0 ||
- projString.find(" init=") != std::string::npos ||
- projString.find(" +init=") != std::string::npos;
+ if (!hasPipeline) {
if (hasProj || hasInit) {
steps.push_back(Step());
}
@@ -7073,8 +7077,10 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
: UnitOfMeasure::NONE)));
}
- if (step.name == "etmerc") {
- methodMap.set("proj_method", "etmerc");
+ if (step.name == "tmerc" && hasParamValue(step, "approx")) {
+ methodMap.set("proj_method", "tmerc approx");
+ } else if (step.name == "utm" && hasParamValue(step, "approx")) {
+ methodMap.set("proj_method", "utm approx");
}
conv = Conversion::create(mapWithUnknownName, methodMap, parameters,
@@ -7447,6 +7453,13 @@ static const metadata::ExtentPtr &getExtent(const crs::CRS *crs) {
*/
BaseObjectNNPtr
PROJStringParser::createFromPROJString(const std::string &projString) {
+
+ // In some abnormal situations involving init=epsg:XXXX syntax, we could
+ // have infinite loop
+ if (d->ctx_ && d->ctx_->curStringInCreateFromPROJString == projString) {
+ throw ParsingException("invalid PROJ string");
+ }
+
d->steps_.clear();
d->title_.clear();
d->globalParamValues_.clear();
@@ -7755,11 +7768,17 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
proj_log_func(pj_context, &logger, Logger::log);
proj_context_use_proj4_init_rules(pj_context, d->usePROJ4InitRules_);
}
+ if (d->ctx_) {
+ d->ctx_->curStringInCreateFromPROJString = projString;
+ }
auto pj = pj_create_internal(
pj_context, (projString.find("type=crs") != std::string::npos
? projString + " +disable_grid_presence_check"
: projString)
.c_str());
+ if (d->ctx_) {
+ d->ctx_->curStringInCreateFromPROJString.clear();
+ }
valid = pj != nullptr;
// Remove parameters not understood by PROJ.