aboutsummaryrefslogtreecommitdiff
path: root/src/apps
diff options
context:
space:
mode:
Diffstat (limited to 'src/apps')
-rw-r--r--src/apps/cct.cpp97
-rw-r--r--src/apps/cs2cs.cpp190
-rw-r--r--src/apps/emess.cpp6
-rw-r--r--src/apps/geod.cpp1
-rw-r--r--src/apps/geod_set.cpp2
-rw-r--r--src/apps/gie.cpp10
-rw-r--r--src/apps/proj.cpp31
-rw-r--r--src/apps/projinfo.cpp43
8 files changed, 330 insertions, 50 deletions
diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp
index f7413872..4f21f10a 100644
--- a/src/apps/cct.cpp
+++ b/src/apps/cct.cpp
@@ -78,6 +78,9 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26
#include <string.h>
#include <stdarg.h>
+#include <fstream> // std::ifstream
+#include <iostream>
+
#include "proj.h"
#include "proj_internal.h"
#include "proj_strtod.h"
@@ -193,9 +196,8 @@ static void print(PJ_LOG_LEVEL log_level, const char *fmt, ...) {
free( msg_buf );
}
-
int main(int argc, char **argv) {
- PJ *P;
+ PJ *P = nullptr;
PJ_COORD point;
PJ_PROJ_INFO info;
OPTARGS *o;
@@ -292,10 +294,73 @@ int main(int argc, char **argv) {
}
/* Setup transformation */
- P = proj_create_argv (nullptr, o->pargc, o->pargv);
- if ((nullptr==P) || (0==o->pargc)) {
+ if (o-> pargc == 0 && o->fargc > 0) {
+ std::string input(o->fargv[0]);
+
+ if (!input.empty() && input[0] == '@') {
+ std::ifstream fs;
+ auto filename = input.substr(1);
+ fs.open(filename, std::fstream::in | std::fstream::binary);
+ if (!fs.is_open()) {
+ std::cerr << "cannot open " << filename << std::endl;
+ std::exit(1);
+ }
+ input.clear();
+ while (!fs.eof()) {
+ char buffer[256];
+ fs.read(buffer, sizeof(buffer));
+ input.append(buffer, static_cast<size_t>(fs.gcount()));
+ if (input.size() > 100 * 1000) {
+ fs.close();
+ std::cerr << "too big file " << filename << std::endl;
+ std::exit(1);
+ }
+ }
+ fs.close();
+ }
+
+ /* Assume we got a auth:code combination */
+ auto n = input.find(":");
+ if (n > 0) {
+ std::string auth = input.substr(0,n);
+ std::string code = input.substr(n+1, input.length());
+ // Check that the authority matches one of the known ones
+ auto authorityList = proj_get_authorities_from_database(nullptr);
+ if( authorityList )
+ {
+ for( auto iter = authorityList; *iter; iter++ )
+ {
+ if( *iter == auth ) {
+ P = proj_create_from_database(
+ nullptr, auth.c_str(), code.c_str(),
+ PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr);
+ break;
+ }
+ }
+ proj_string_list_destroy(authorityList);
+ }
+ }
+ if( P == nullptr ) {
+ /* if we didn't get a auth:code combo we try to see if the input matches */
+ /* anything else */
+ P = proj_create(nullptr, input.c_str());
+ }
+
+ /* If instantiating operation without +-options optargpm thinks the input is */
+ /* a file, hence we move all o->fargv entries one place closer to the start */
+ /* of the array. This effectively overwrites the input and only leaves a list */
+ /* of files in o->fargv. */
+ o->fargc = o->fargc-1;
+ for (int j=0; j < o->fargc; j++) {
+ o->fargv[j] = o->fargv[j+1];
+ }
+ } else {
+ P = proj_create_argv (nullptr, o->pargc, o->pargv);
+ }
+
+ if (nullptr==P) {
print (PJ_LOG_ERROR, "%s: Bad transformation arguments - (%s)\n '%s -h' for help",
- o->progname, pj_strerrno (proj_errno(P)), o->progname);
+ o->progname, proj_errno_string (proj_errno(P)), o->progname);
free (o);
if (stdout != fout)
fclose (fout);
@@ -322,7 +387,7 @@ int main(int argc, char **argv) {
buf = static_cast<char*>(calloc (1, 10000));
if (nullptr==buf) {
print (PJ_LOG_ERROR, "%s: Out of memory", o->progname);
- pj_free (P);
+ proj_destroy (P);
free (o);
if (stdout != fout)
fclose (fout);
@@ -370,7 +435,7 @@ int main(int argc, char **argv) {
if (HUGE_VAL==point.xyzt.x) {
/* transformation error */
print (PJ_LOG_NONE, "# Record %d TRANSFORMATION ERROR: %s (%s)",
- (int) o->record_index, buf, pj_strerrno (proj_errno(P)));
+ (int) o->record_index, buf, proj_errno_string (proj_errno(P)));
proj_errno_restore (P, err);
continue;
}
@@ -385,12 +450,22 @@ int main(int argc, char **argv) {
colmax = MAX(colmax, columns_xyzt[i]);
comment = column(buf, colmax+1);
}
+ /* remove the line feed from comment, as logger() above, invoked
+ by print() below (output), will add one */
+ size_t len = strlen(comment);
+ if (len >= 1)
+ comment[len - 1] = '\0';
comment_delimiter = (comment && *comment) ? whitespace : blank_comment;
/* Time to print the result */
- if (proj_angular_output (P, direction)) {
- point.lpzt.lam = proj_todeg (point.lpzt.lam);
- point.lpzt.phi = proj_todeg (point.lpzt.phi);
+ /* use same arguments to printf format string for both radians and
+ degrees; convert radians to degrees before printing */
+ if (proj_angular_output (P, direction) ||
+ proj_degree_output (P, direction)) {
+ if (proj_angular_output (P, direction)) {
+ point.lpzt.lam = proj_todeg (point.lpzt.lam);
+ point.lpzt.phi = proj_todeg (point.lpzt.phi);
+ }
print (PJ_LOG_NONE, "%14.*f %14.*f %12.*f %12.4f%s%s",
decimals_angles, point.xyzt.x,
decimals_angles, point.xyzt.y,
@@ -405,6 +480,8 @@ int main(int argc, char **argv) {
decimals_distances, point.xyzt.z,
point.xyzt.t, comment_delimiter, comment
);
+ if( fout == stdout )
+ fflush(stdout);
}
proj_destroy(P);
diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp
index 58c164c9..409a5ef3 100644
--- a/src/apps/cs2cs.cpp
+++ b/src/apps/cs2cs.cpp
@@ -36,8 +36,13 @@
#include <string.h>
#include <cassert>
+#include <iostream>
#include <string>
+#include <proj/io.hpp>
+#include <proj/metadata.hpp>
+#include <proj/util.hpp>
+
#include <proj/internal/internal.hpp>
// PROJ include order is sensitive
@@ -70,12 +75,19 @@ static const char *oform =
static char oform_buffer[16]; /* buffer for oform when using -d */
static const char *oterr = "*\t*"; /* output line for unprojectable input */
static const char *usage =
- "%s\nusage: %s [-dDeEfIlrstvwW [args]] [+opt[=arg] ...]\n"
- " [+to +opt[=arg] ...] [file ...]\n";
+ "%s\nusage: %s [-dDeEfIlrstvwW [args]]\n"
+ " [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]\n"
+ " [--authority {name}]\n"
+ " [+opt[=arg] ...] [+to +opt[=arg] ...] [file ...]\n";
static double (*informat)(const char *,
char **); /* input data deformatter function */
+using namespace NS_PROJ::io;
+using namespace NS_PROJ::metadata;
+using namespace NS_PROJ::util;
+using namespace NS_PROJ::internal;
+
/************************************************************************/
/* process() */
/* */
@@ -217,6 +229,7 @@ static void process(FILE *fid)
printf("%s", s);
else
printf("\n");
+ fflush(stdout);
}
}
@@ -358,9 +371,57 @@ int main(int argc, char **argv) {
}
}
+ ExtentPtr bboxFilter;
+ std::string area;
+ const char* authority = nullptr;
+
/* process run line arguments */
while (--argc > 0) { /* collect run line arguments */
- if (**++argv == '-') {
+ ++argv;
+ if (strcmp(*argv, "--area") == 0 ) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --area");
+ std::exit(1);
+ }
+ area = *argv;
+ }
+ else if (strcmp(*argv, "--bbox") == 0) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --bbox");
+ std::exit(1);
+ }
+ auto bboxStr(*argv);
+ auto bbox(split(bboxStr, ','));
+ if (bbox.size() != 4) {
+ std::cerr << "Incorrect number of values for option --bbox: "
+ << bboxStr << std::endl;
+ std::exit(1);
+ }
+ try {
+ bboxFilter = Extent::createFromBBOX(
+ c_locale_stod(bbox[0]), c_locale_stod(bbox[1]),
+ c_locale_stod(bbox[2]), c_locale_stod(bbox[3]))
+ .as_nullable();
+ } catch (const std::exception &e) {
+ std::cerr << "Invalid value for option --bbox: " << bboxStr
+ << ", " << e.what() << std::endl;
+ std::exit(1);
+ }
+ }
+ else if (strcmp(*argv, "--authority") == 0 ) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --authority");
+ std::exit(1);
+ }
+ authority = *argv;
+ }
+ else if (**argv == '-') {
for (arg = *argv;;) {
switch (*++arg) {
case '\0': /* position of "stdin" */
@@ -467,10 +528,23 @@ int main(int argc, char **argv) {
reverseout = 1;
continue;
case 'D': /* set debug level */
+ {
if (--argc <= 0)
goto noargument;
- pj_ctx_set_debug(pj_get_default_ctx(), atoi(*++argv));
+ int log_level = atoi(*++argv);
+ if (log_level <= 0) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_NONE);
+ } else if (log_level == 1) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_ERROR);
+ } else if (log_level == 2) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_DEBUG);
+ } else if (log_level == 3) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_TRACE);
+ } else {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_TELL);
+ }
continue;
+ }
case 'd':
if (--argc <= 0)
goto noargument;
@@ -522,6 +596,102 @@ int main(int argc, char **argv) {
}
}
+ if (bboxFilter && !area.empty()) {
+ std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl;
+ std::exit(1);
+ }
+
+ PJ_AREA* pj_area = nullptr;
+ if (!area.empty()) {
+
+ DatabaseContextPtr dbContext;
+ try {
+ dbContext =
+ DatabaseContext::create().as_nullable();
+ } catch (const std::exception &e) {
+ std::cerr << "ERROR: Cannot create database connection: "
+ << e.what() << std::endl;
+ std::exit(1);
+ }
+
+ // Process area of use
+ try {
+ if (area.find(' ') == std::string::npos &&
+ area.find(':') != std::string::npos) {
+ auto tokens = split(area, ':');
+ if (tokens.size() == 2) {
+ const std::string &areaAuth = tokens[0];
+ const std::string &areaCode = tokens[1];
+ bboxFilter = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), areaAuth)
+ ->createExtent(areaCode)
+ .as_nullable();
+ }
+ }
+ if (!bboxFilter) {
+ auto authFactory = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), std::string());
+ auto res = authFactory->listAreaOfUseFromName(area, false);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else {
+ res = authFactory->listAreaOfUseFromName(area, true);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else if (res.empty()) {
+ std::cerr << "No area of use matching provided name"
+ << std::endl;
+ std::exit(1);
+ } else {
+ std::cerr << "Several candidates area of use "
+ "matching provided name :"
+ << std::endl;
+ for (const auto &candidate : res) {
+ auto obj =
+ AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), candidate.first)
+ ->createExtent(candidate.second);
+ std::cerr << " " << candidate.first << ":"
+ << candidate.second << " : "
+ << *obj->description() << std::endl;
+ }
+ std::exit(1);
+ }
+ }
+ }
+ } catch (const std::exception &e) {
+ std::cerr << "Area of use retrieval failed: " << e.what()
+ << std::endl;
+ std::exit(1);
+ }
+ }
+
+ if (bboxFilter) {
+ auto geogElts = bboxFilter->geographicElements();
+ if (geogElts.size() == 1)
+ {
+ auto bbox = std::dynamic_pointer_cast<GeographicBoundingBox>(
+ geogElts[0].as_nullable());
+ if (bbox)
+ {
+ pj_area = proj_area_create();
+ proj_area_set_bbox(pj_area,
+ bbox->westBoundLongitude(),
+ bbox->southBoundLatitude(),
+ bbox->eastBoundLongitude(),
+ bbox->northBoundLatitude());
+ }
+ }
+ }
+
/*
* If the user has requested inverse, then just reverse the
* coordinate systems.
@@ -602,15 +772,23 @@ int main(int argc, char **argv) {
}
}
+ std::string authorityOption; /* keep this variable in this outer scope ! */
+ const char* options[2] = { nullptr, nullptr };
+ if( authority ) {
+ authorityOption = "AUTHORITY=";
+ authorityOption += authority;
+ options[0] = authorityOption.data();
+ }
transformation = proj_create_crs_to_crs_from_pj(nullptr, src, dst,
- nullptr, nullptr);
+ pj_area, options);
proj_destroy(src);
proj_destroy(dst);
+ proj_area_destroy(pj_area);
if (!transformation) {
emess(3, "cannot initialize transformation\ncause: %s",
- pj_strerrno(pj_errno));
+ proj_errno_string(proj_context_errno(nullptr)));
}
if (use_env_locale) {
diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp
index 53018ba8..5a50cd25 100644
--- a/src/apps/emess.cpp
+++ b/src/apps/emess.cpp
@@ -9,17 +9,13 @@
# endif
#endif
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "proj_api.h"
+#include "proj_internal.h"
#include "proj_config.h"
#define EMESS_ROUTINE
#include "emess.h"
diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp
index 919430ca..35a8e826 100644
--- a/src/apps/geod.cpp
+++ b/src/apps/geod.cpp
@@ -124,6 +124,7 @@ process(FILE *fid) {
(void)fputs(rtodms(pline, al21, 0, 0), stdout);
}
(void)fputs(s, stdout);
+ fflush(stdout);
}
}
diff --git a/src/apps/geod_set.cpp b/src/apps/geod_set.cpp
index 603f0d95..d6516f22 100644
--- a/src/apps/geod_set.cpp
+++ b/src/apps/geod_set.cpp
@@ -75,6 +75,6 @@ geod_set(int argc, char **argv) {
/* free up linked list */
for ( ; start; start = curr) {
curr = start->next;
- pj_dalloc(start);
+ free(start);
}
}
diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp
index 8940afde..b504b922 100644
--- a/src/apps/gie.cpp
+++ b/src/apps/gie.cpp
@@ -880,8 +880,8 @@ static int expect_failure_with_errno_message (int expected, int got) {
banner (T.operation);
fprintf (T.fout, "%s", T.op_ko? " -----\n": delim);
fprintf (T.fout, " FAILURE in %s(%d):\n", opt_strip_path (T.curr_file), (int) F->lineno);
- fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, pj_strerrno (got));
- fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, pj_strerrno (expected));
+ fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, proj_errno_string (got));
+ fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, proj_errno_string (expected));
fprintf (T.fout, "\n");
return 1;
}
@@ -934,7 +934,7 @@ Tell GIE what to expect, when transforming the ACCEPTed input
/* Otherwise, it's a true failure */
banner (T.operation);
errmsg (3, "%sInvalid operation definition in line no. %d:\n %s (errno=%s/%d)\n",
- delim, (int) T.operation_lineno, pj_strerrno(proj_errno(T.P)),
+ delim, (int) T.operation_lineno, proj_errno_string (proj_errno(T.P)),
err_const_from_errno (proj_errno(T.P)), proj_errno(T.P)
);
return another_failing_failure ();
@@ -1124,7 +1124,7 @@ static const struct errno_vs_err_const lookup[] = {
{"pjd_err_invalid_x_or_y" , -15},
{"pjd_err_wrong_format_dms_value" , -16},
{"pjd_err_non_conv_inv_meri_dist" , -17},
- {"pjd_err_non_con_inv_phi2" , -18},
+ {"pjd_err_non_conv_sinhpsi2tanphi" , -18},
{"pjd_err_acos_asin_arg_too_large" , -19},
{"pjd_err_tolerance_condition" , -20},
{"pjd_err_conic_lat_equal" , -21},
@@ -1186,7 +1186,7 @@ static int list_err_codes (void) {
if (9999==lookup[i].the_errno)
break;
fprintf (T.fout, "%25s (%2.2d): %s\n", lookup[i].the_err_const + 8,
- lookup[i].the_errno, pj_strerrno(lookup[i].the_errno));
+ lookup[i].the_errno, proj_errno_string (lookup[i].the_errno));
}
return 0;
}
diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp
index 0bf98b3a..0108cb74 100644
--- a/src/apps/proj.cpp
+++ b/src/apps/proj.cpp
@@ -9,6 +9,8 @@
#include "emess.h"
#include "utils.h"
+#include <vector>
+
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__)
# include <fcntl.h>
# include <io.h>
@@ -171,6 +173,7 @@ static void process(FILE *fid) {
(void)fputs("\t<* * * * * *>", stdout);
}
(void)fputs(bin_in ? "\n" : s, stdout);
+ fflush(stdout);
}
}
@@ -249,10 +252,8 @@ static void vprocess(FILE *fid) {
if (postscale) { dat_xy.x *= fscale; dat_xy.y *= fscale; }
}
- /* For some reason pj_errno does not work as expected in some */
- /* versions of Visual Studio, so using pj_get_errno_ref instead */
- if (*pj_get_errno_ref()) {
- emess(-1, pj_strerrno(*pj_get_errno_ref()));
+ if (proj_context_errno(nullptr)) {
+ emess(-1, proj_errno_string(proj_context_errno(nullptr)));
continue;
}
@@ -286,15 +287,17 @@ static void vprocess(FILE *fid) {
(void)fputs(proj_rtodms(pline, facs.meridian_convergence, 0, 0), stdout);
(void)printf(" [ %.8f ]\n", facs.meridian_convergence * RAD_TO_DEG);
(void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", facs.tissot_semimajor, facs.tissot_semiminor);
+
+ fflush(stdout);
}
}
int main(int argc, char **argv) {
char *arg;
- char *pargv[MAX_PARGS] = {};
+ std::vector<char*> argvVector;
char **eargv = argv;
FILE *fid;
- int pargc = 0, eargc = 0, mon = 0;
+ int eargc = 0, mon = 0;
if ( (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr)
++emess_dat.Prog_name;
@@ -449,10 +452,7 @@ int main(int argc, char **argv) {
}
break;
} else if (**argv == '+') { /* + argument */
- if (pargc < MAX_PARGS)
- pargv[pargc++] = *argv + 1;
- else
- emess(1,"overflowed + argument table");
+ argvVector.push_back(*argv + 1);
} else /* assumed to be input file name(s) */
eargv[eargc++] = *argv;
}
@@ -472,9 +472,14 @@ int main(int argc, char **argv) {
postscale = 0;
fscale = 1./fscale;
}
- if (!(Proj = pj_init(pargc, pargv)))
+ proj_context_use_proj4_init_rules(nullptr, true);
+
+ // proj historically ignores any datum shift specifier, like nadgrids, towgs84, etc
+ argvVector.push_back(const_cast<char*>("break_cs2cs_recursion"));
+
+ if (!(Proj = proj_create_argv(nullptr, static_cast<int>(argvVector.size()), argvVector.data())))
emess(3,"projection initialization failure\ncause: %s",
- pj_strerrno(pj_errno));
+ proj_errno_string(proj_context_errno(nullptr)));
if (!proj_angular_input(Proj, PJ_FWD)) {
emess(3, "can't initialize operations that take non-angular input coordinates");
@@ -559,7 +564,7 @@ int main(int argc, char **argv) {
}
if( Proj )
- pj_free(Proj);
+ proj_destroy(Proj);
exit(0); /* normal completion */
}
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 37b76346..da885fbb 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -72,6 +72,7 @@ struct OutputOptions {
bool singleLine = false;
bool strict = true;
bool ballparkAllowed = true;
+ bool allowEllipsoidalHeightAsVerticalCRS = false;
};
} // anonymous namespace
@@ -79,7 +80,8 @@ struct OutputOptions {
static void usage() {
std::cerr
- << "usage: projinfo [-o formats] [-k crs|operation|datum|ellipsoid] "
+ << "usage: projinfo [-o formats] "
+ "[-k crs|operation|datum|ensemble|ellipsoid] "
"[--summary] [-q]"
<< std::endl
<< " ([--area name_or_code] | "
@@ -94,6 +96,8 @@ static void usage() {
<< " [--pivot-crs always|if_no_direct_transformation|"
<< "never|{auth:code[,auth:code]*}]" << std::endl
<< " [--show-superseded] [--hide-ballpark]" << std::endl
+ << " [--allow-ellipsoidal-height-as-vertical-crs]"
+ << std::endl
<< " [--boundcrs-to-wgs84]" << std::endl
<< " [--main-db-path path] [--aux-db-path path]*"
<< std::endl
@@ -184,11 +188,11 @@ static BaseObjectNNPtr buildObject(
auto urn = "urn:ogc:def:coordinateOperation:" + tokens[0] + "::" +
tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
- } else if (kind == "ellipsoid" && tokens.size() == 2) {
- auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + tokens[1];
- obj = createFromUserInput(urn, dbContext).as_nullable();
- } else if (kind == "datum" && tokens.size() == 2) {
- auto urn = "urn:ogc:def:datum:" + tokens[0] + "::" + tokens[1];
+ } else if ((kind == "ellipsoid" || kind == "datum" ||
+ kind == "ensemble") &&
+ tokens.size() == 2) {
+ auto urn =
+ "urn:ogc:def:" + kind + ":" + tokens[0] + "::" + tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
} else {
// Convenience to be able to use C escaped strings...
@@ -222,6 +226,9 @@ static BaseObjectNNPtr buildObject(
AuthorityFactory::ObjectType::ELLIPSOID);
else if (kind == "datum")
allowedTypes.push_back(AuthorityFactory::ObjectType::DATUM);
+ else if (kind == "ensemble")
+ allowedTypes.push_back(
+ AuthorityFactory::ObjectType::DATUM_ENSEMBLE);
constexpr size_t limitResultCount = 10;
auto factory = AuthorityFactory::create(NN_NO_CHECK(dbContext),
std::string());
@@ -483,6 +490,8 @@ static void outputObject(
formatter->setMultiLine(false);
}
formatter->setStrict(outputOpt.strict);
+ formatter->setAllowEllipsoidalHeightAsVerticalCRS(
+ outputOpt.allowEllipsoidalHeightAsVerticalCRS);
auto wkt = wktExportable->exportToWKT(formatter.get());
if (outputOpt.c_ify) {
wkt = c_ify_string(wkt);
@@ -689,6 +698,7 @@ static void outputOperations(
std::vector<CoordinateOperationNNPtr> list;
size_t spatialCriterionPartialIntersectionResultCount = 0;
+ bool spatialCriterionPartialIntersectionMoreRelevant = false;
try {
auto authFactory =
dbContext
@@ -714,10 +724,15 @@ static void outputOperations(
ctxt->setSpatialCriterion(
CoordinateOperationContext::SpatialCriterion::
PARTIAL_INTERSECTION);
- spatialCriterionPartialIntersectionResultCount =
- CoordinateOperationFactory::create()
- ->createOperations(nnSourceCRS, nnTargetCRS, ctxt)
- .size();
+ auto list2 =
+ CoordinateOperationFactory::create()->createOperations(
+ nnSourceCRS, nnTargetCRS, ctxt);
+ spatialCriterionPartialIntersectionResultCount = list2.size();
+ if (spatialCriterionPartialIntersectionResultCount == 1 &&
+ list.size() == 1 &&
+ list2[0]->nameStr() != list[0]->nameStr()) {
+ spatialCriterionPartialIntersectionMoreRelevant = true;
+ }
} catch (const std::exception &) {
}
}
@@ -736,6 +751,10 @@ static void outputOperations(
"more results ("
<< spatialCriterionPartialIntersectionResultCount << ")"
<< std::endl;
+ } else if (spatialCriterionPartialIntersectionMoreRelevant) {
+ std::cout << "Note: using '--spatial-test intersects' would bring "
+ "more relevant results."
+ << std::endl;
}
if (summary) {
for (const auto &op : list) {
@@ -929,6 +948,8 @@ int main(int argc, char **argv) {
objectKind = "ellipsoid";
} else if (ci_equal(kind, "datum")) {
objectKind = "datum";
+ } else if (ci_equal(kind, "ensemble")) {
+ objectKind = "ensemble";
} else {
std::cerr << "Unrecognized value for option -k: " << kind
<< std::endl;
@@ -1054,6 +1075,8 @@ int main(int argc, char **argv) {
showSuperseded = true;
} else if (arg == "--lax") {
outputOpt.strict = false;
+ } else if (arg == "--allow-ellipsoidal-height-as-vertical-crs") {
+ outputOpt.allowEllipsoidalHeightAsVerticalCRS = true;
} else if (arg == "--hide-ballpark") {
outputOpt.ballparkAllowed = false;
} else if (ci_equal(arg, "--3d")) {