From c560b7957664c32e2465e8425abaccc5a6b2607d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 17 Nov 2020 12:39:48 +0100 Subject: cs2cs, cct, proj and geod: fflush(stdout) after each line to emit each result as soon as it is produced This is needed when working with pipes, when stdout is not an interactive terminal, and thus the behaviour is to have it buffered as a regular file, whereas with an interactive terminal, each newline character causes an implicit flush. --- src/apps/cs2cs.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/apps/cs2cs.cpp') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 58c164c9..1a33d444 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -217,6 +217,7 @@ static void process(FILE *fid) printf("%s", s); else printf("\n"); + fflush(stdout); } } -- cgit v1.2.3 From a74b985b5006c2d279353a245cfcb850cf7fcc94 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 17 Nov 2020 12:54:24 +0100 Subject: Remove pj_ctx_* functions and use their proj_context counterparts --- src/apps/cs2cs.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/apps/cs2cs.cpp') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 1a33d444..92e4441e 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -468,10 +468,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; -- cgit v1.2.3 From 56f0ad70054eea15e9671cd67aafd14bf7c11c74 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Wed, 18 Nov 2020 10:43:16 +0100 Subject: Remove pj_errno and related functions --- src/apps/cs2cs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/apps/cs2cs.cpp') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 92e4441e..12e045bb 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -624,7 +624,7 @@ int main(int argc, char **argv) { if (!transformation) { emess(3, "cannot initialize transformation\ncause: %s", - pj_strerrno(pj_errno)); + proj_errno_string(proj_context_errno(nullptr))); } if (use_env_locale) { -- cgit v1.2.3 From 0b4c8b0a76c65d8b1146224bf314cad53e9f6607 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Nov 2020 15:51:27 +0100 Subject: cs2cs: add --area and --bbox options to restrict candidate coordinate operations (fixes #2423) --- src/apps/cs2cs.cpp | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 4 deletions(-) (limited to 'src/apps/cs2cs.cpp') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index 12e045bb..dd65baf4 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -36,8 +36,13 @@ #include #include +#include #include +#include +#include +#include + #include // PROJ include order is sensitive @@ -70,12 +75,18 @@ 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" + " [+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() */ /* */ @@ -359,9 +370,47 @@ int main(int argc, char **argv) { } } + ExtentPtr bboxFilter; + std::string area; + /* 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 (**argv == '-') { for (arg = *argv;;) { switch (*++arg) { case '\0': /* position of "stdin" */ @@ -536,6 +585,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( + 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. @@ -617,10 +762,11 @@ int main(int argc, char **argv) { } transformation = proj_create_crs_to_crs_from_pj(nullptr, src, dst, - nullptr, nullptr); + pj_area, nullptr); proj_destroy(src); proj_destroy(dst); + proj_area_destroy(pj_area); if (!transformation) { emess(3, "cannot initialize transformation\ncause: %s", -- cgit v1.2.3 From 18ab7ef2e357e0c01464848a6911e754ebca471f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 2 Dec 2020 17:12:54 +0100 Subject: cs2cs / proj_create_crs_to_crs_from_pj(): add a --authority switch to control where coordinate operations are looked for (fixes #2442) --- src/apps/cs2cs.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/apps/cs2cs.cpp') diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp index dd65baf4..409a5ef3 100644 --- a/src/apps/cs2cs.cpp +++ b/src/apps/cs2cs.cpp @@ -77,6 +77,7 @@ static const char *oterr = "*\t*"; /* output line for unprojectable input */ static const char *usage = "%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 *, @@ -372,6 +373,7 @@ 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 */ @@ -410,6 +412,15 @@ int main(int argc, char **argv) { 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) { @@ -761,8 +772,15 @@ 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, - pj_area, nullptr); + pj_area, options); proj_destroy(src); proj_destroy(dst); -- cgit v1.2.3