aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-10-16 00:10:05 +0200
committerEven Rouault <even.rouault@spatialys.com>2020-10-16 18:49:58 +0200
commit149366116ad0ffb936eaa042823211731e9dcdee (patch)
tree1258ceb40af7d348f12ed30c2eb4de1c80c2ace5 /src
parent82b496fb32df0b6705159cd5c626aab20c8e9d39 (diff)
downloadPROJ-149366116ad0ffb936eaa042823211731e9dcdee.tar.gz
PROJ-149366116ad0ffb936eaa042823211731e9dcdee.zip
Add multi-line PROJ string export capability, and use it by default in projinfo (unless --single-line is specified) (fixes #1543)
Diffstat (limited to 'src')
-rw-r--r--src/apps/projinfo.cpp13
-rw-r--r--src/iso19111/c_api.cpp31
-rw-r--r--src/iso19111/io.cpp78
3 files changed, 100 insertions, 22 deletions
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 966de03d..f36674fd 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -350,11 +350,10 @@ static void outputObject(
objToExport = projStringExportable;
}
- std::cout << objToExport->exportToPROJString(
- PROJStringFormatter::create(
- PROJStringFormatter::Convention::PROJ_5,
- dbContext)
- .get())
+ auto formatter = PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5, dbContext);
+ formatter->setMultiLine(!outputOpt.singleLine);
+ std::cout << objToExport->exportToPROJString(formatter.get())
<< std::endl;
} catch (const std::exception &e) {
std::cerr << "Error when exporting to PROJ string: " << e.what()
@@ -376,9 +375,7 @@ static void outputObject(
}
auto formatter =
WKTFormatter::create(WKTFormatter::Convention::WKT2_2015);
- if (outputOpt.singleLine) {
- formatter->setMultiLine(false);
- }
+ formatter->setMultiLine(!outputOpt.singleLine);
formatter->setStrict(outputOpt.strict);
auto wkt = wktExportable->exportToWKT(formatter.get());
if (outputOpt.c_ify) {
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index cad76431..8d77437a 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -1504,9 +1504,16 @@ const char *proj_as_wkt(PJ_CONTEXT *ctx, const PJ *obj, PJ_WKT_TYPE type,
* @param obj Object (must not be NULL)
* @param type PROJ String version.
* @param options NULL-terminated list of strings with "KEY=VALUE" format. or
- * NULL.
- * The currently recognized option is USE_APPROX_TMERC=YES to add the +approx
- * flag to +proj=tmerc or +proj=utm
+ * NULL. Currently supported options are:
+ * <ul>
+ * <li>USE_APPROX_TMERC=YES to add the +approx flag to +proj=tmerc or
+ * +proj=utm.</li>
+ * <li>MULTILINE=YES/NO. Defaults to NO</li>
+ * <li>INDENTATION_WIDTH=number. Defaults to 2 (when multiline output is
+ * on).</li>
+ * <li>MAX_LINE_LENGTH=number. Defaults to 80 (when multiline output is
+ * on).</li>
+ * </ul>
* @return a string, or NULL in case of error.
*/
const char *proj_as_proj_string(PJ_CONTEXT *ctx, const PJ *obj,
@@ -1542,9 +1549,21 @@ const char *proj_as_proj_string(PJ_CONTEXT *ctx, const PJ *obj,
auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
try {
auto formatter = PROJStringFormatter::create(convention, dbContext);
- if (options != nullptr && options[0] != nullptr) {
- if (ci_equal(options[0], "USE_APPROX_TMERC=YES")) {
- formatter->setUseApproxTMerc(true);
+ for (auto iter = options; iter && iter[0]; ++iter) {
+ const char *value;
+ if ((value = getOptionValue(*iter, "MULTILINE="))) {
+ formatter->setMultiLine(ci_equal(value, "YES"));
+ } else if ((value = getOptionValue(*iter, "INDENTATION_WIDTH="))) {
+ formatter->setIndentationWidth(std::atoi(value));
+ } else if ((value = getOptionValue(*iter, "MAX_LINE_LENGTH="))) {
+ formatter->setMaxLineLength(std::atoi(value));
+ } else if ((value = getOptionValue(*iter, "USE_APPROX_TMERC="))) {
+ formatter->setUseApproxTMerc(ci_equal(value, "YES"));
+ } else {
+ std::string msg("Unknown option :");
+ msg += *iter;
+ proj_log_error(ctx, __FUNCTION__, msg.c_str());
+ return nullptr;
}
}
obj->lastPROJString = exportable->exportToPROJString(formatter.get());
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index c464b724..7a107f96 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -6722,6 +6722,10 @@ struct PROJStringFormatter::Private {
bool coordOperationOptimizations_ = false;
bool crsExport_ = false;
bool legacyCRSToCRSContext_ = false;
+ bool multiLine_ = false;
+ int indentWidth_ = 2;
+ int indentLevel_ = 0;
+ int maxLineLength_ = 80;
std::string result_{};
@@ -6780,6 +6784,36 @@ void PROJStringFormatter::setUseApproxTMerc(bool flag) {
// ---------------------------------------------------------------------------
+/** \brief Whether to use multi line output or not. */
+PROJStringFormatter &
+PROJStringFormatter::setMultiLine(bool multiLine) noexcept {
+ d->multiLine_ = multiLine;
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Set number of spaces for each indentation level (defaults to 2).
+ */
+PROJStringFormatter &
+PROJStringFormatter::setIndentationWidth(int width) noexcept {
+ d->indentWidth_ = width;
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Set the maximum size of a line (when multiline output is enable).
+ * Can be set to 0 for unlimited length.
+ */
+PROJStringFormatter &
+PROJStringFormatter::setMaxLineLength(int maxLineLength) noexcept {
+ d->maxLineLength_ = maxLineLength;
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Returns the PROJ string. */
const std::string &PROJStringFormatter::toString() const {
@@ -7308,28 +7342,56 @@ const std::string &PROJStringFormatter::toString() const {
pj_double_quote_string_param_if_needed(paramValue.value);
}
}
+
+ if (d->multiLine_) {
+ d->indentLevel_++;
+ }
}
for (const auto &step : d->steps_) {
+ std::string curLine;
if (!d->result_.empty()) {
- d->appendToResult("+step");
+ if (d->multiLine_) {
+ curLine = std::string(d->indentLevel_ * d->indentWidth_, ' ');
+ curLine += "+step";
+ } else {
+ curLine = " +step";
+ }
}
if (step.inverted) {
- d->appendToResult("+inv");
+ curLine += " +inv";
}
if (!step.name.empty()) {
- d->appendToResult(step.isInit ? "+init=" : "+proj=");
- d->result_ += step.name;
+ if (!curLine.empty())
+ curLine += ' ';
+ curLine += step.isInit ? "+init=" : "+proj=";
+ curLine += step.name;
}
for (const auto &paramValue : step.paramValues) {
- d->appendToResult("+");
- d->result_ += paramValue.key;
+ std::string newKV = "+";
+ newKV += paramValue.key;
if (!paramValue.value.empty()) {
- d->result_ += '=';
- d->result_ +=
+ newKV += '=';
+ newKV +=
pj_double_quote_string_param_if_needed(paramValue.value);
}
+ if (d->maxLineLength_ > 0 && d->multiLine_ &&
+ curLine.size() + newKV.size() >
+ static_cast<size_t>(d->maxLineLength_)) {
+ if (d->multiLine_ && !d->result_.empty())
+ d->result_ += '\n';
+ d->result_ += curLine;
+ curLine = std::string(
+ d->indentLevel_ * d->indentWidth_ + strlen("+step "), ' ');
+ } else {
+ if (!curLine.empty())
+ curLine += ' ';
+ }
+ curLine += newKV;
}
+ if (d->multiLine_ && !d->result_.empty())
+ d->result_ += '\n';
+ d->result_ += curLine;
}
if (d->result_.empty()) {