From 6be4e25c66e805218c851d67157e4d1ddc0a761e Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 10 Nov 2020 14:40:17 +0100 Subject: cct: allow @filename syntax Similarly as for projinfo, allow "cct @filename" to mean read filename and use its content as if it was provided inline. Useful for WKT or PROJJSON And a tiny improvements, when the object definition contains ':', only try proj_create_from_database() if the left part (authority name) matches a known authority, to avoid a warning. --- docs/source/apps/cct.rst | 27 +++++++++++++- src/apps/cct.cpp | 47 +++++++++++++++++++++--- test/cli/testcct | 93 +++++++++++++++++++++++++++++++++++++++++++++++ test/cli/testcct_out.dist | 2 + 4 files changed, 162 insertions(+), 7 deletions(-) diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst index 8f138d92..b8504b8d 100644 --- a/docs/source/apps/cct.rst +++ b/docs/source/apps/cct.rst @@ -17,9 +17,9 @@ Synopsis or - **cct** [**-cIostvz** [args]] {operation_reference} file ... + **cct** [**-cIostvz** [args]] {object_definition} file ... -Where {operation_reference} is one of the possibilities accepted +Where {object_definition} is one of the possibilities accepted by :c:func:`proj_create`, provided it expresses a coordinate operation - a proj-string, @@ -39,6 +39,15 @@ by :c:func:`proj_create`, provided it expresses a coordinate operation operations in :program:`cct`. +or + + **cct** [**-cIostvz** [args]] {object_reference} file ... + +where {object_reference} is a filename preceded by the '@' character. The +file referenced by the {object_reference} must contain a valid +{object_definition}. + + .. versionadded:: 8.0.0 @@ -185,6 +194,20 @@ Should give results comparable to the classic :program:`proj` command $ echo 12 56 100 2018.0 auxiliary data | cct +proj=merc 1335833.8895 7522963.2411 100.0000 2018.0000 auxiliary data +7. Coordinate operation referenced through its code + +.. code-block:: console + + $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct EPSG:8366 + 3541657.9112 948983.7503 5201383.2482 2020.5000 + +8. Coordinate operation referenced through its name + +.. code-block:: console + + $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct "ITRF2014 to ETRF2014 (1)" + 3541657.9112 948983.7503 5201383.2482 2020.5000 + Background ********** diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp index 4de3cf8e..c482efc2 100644 --- a/src/apps/cct.cpp +++ b/src/apps/cct.cpp @@ -77,6 +77,8 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26 #include #include #include + +#include // std::ifstream #include #include "proj.h" @@ -293,20 +295,55 @@ int main(int argc, char **argv) { /* Setup transformation */ if (o-> pargc == 0 && o->fargc > 0) { - /* Assume we got a auth:code combination */ 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(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()); - P = proj_create_from_database( - nullptr, auth.c_str(), code.c_str(), PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr - ); + // 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, o->fargv[0]); + P = proj_create(nullptr, input.c_str()); } /* If instantiating operation without +-options optargpm thinks the input is */ diff --git a/test/cli/testcct b/test/cli/testcct index bbe698bd..db7c70a9 100755 --- a/test/cli/testcct +++ b/test/cli/testcct @@ -44,6 +44,99 @@ echo "3541658.0000 948985.0000 5201384.0000 2020.5" >> b $EXE EPSG:8366 a b >>${OUT} /bin/rm a b +cat > in.wkt <> ${OUT} +echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE @in.wkt >>${OUT} +rm in.wkt + # do 'diff' with distribution results echo "diff ${OUT} with testcct_out.dist" diff -u ${OUT} ${TEST_CLI_DIR}/testcct_out.dist diff --git a/test/cli/testcct_out.dist b/test/cli/testcct_out.dist index 7788f0bb..353deb17 100644 --- a/test/cli/testcct_out.dist +++ b/test/cli/testcct_out.dist @@ -8,3 +8,5 @@ Test cct with object name initialization Test cct with object code initialization and file input 3541657.9112 948983.7503 5201383.2482 2020.5000 3541658.5334 948984.5160 5201383.7251 2020.5000 +Test cct with WKT in a file + 3541657.9112 948983.7503 5201383.2482 2020.5000 -- cgit v1.2.3