From a7f696c0772c558c41c7050496bc658706902af2 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 22 Nov 2018 23:12:54 +0100 Subject: Rename cs2cs.c to cs2cs.cpp with minimal changes to make it compile --- src/cs2cs.cpp | 466 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 src/cs2cs.cpp (limited to 'src/cs2cs.cpp') diff --git a/src/cs2cs.cpp b/src/cs2cs.cpp new file mode 100644 index 00000000..439b172c --- /dev/null +++ b/src/cs2cs.cpp @@ -0,0 +1,466 @@ +/****************************************************************************** + * Project: PROJ.4 + * Purpose: Mainline program sort of like ``proj'' for converting between + * two coordinate systems. + * Author: Frank Warmerdam, warmerda@home.com + * + ****************************************************************************** + * Copyright (c) 2000, Frank Warmerdam + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "proj.h" +#include "projects.h" +#include "emess.h" + +#define MAX_LINE 1000 +#define MAX_PARGS 100 + +static projPJ fromProj, toProj; + +static int +reversein = 0, /* != 0 reverse input arguments */ +reverseout = 0, /* != 0 reverse output arguments */ +echoin = 0, /* echo input data to output line */ +tag = '#'; /* beginning of line tag character */ + +static const char *oform = nullptr; /* output format for x-y or decimal degrees */ +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] ] [ +opts[=arg] ]\n" +" [+to [+opts[=arg] [ files ]\n"; + +static double (*informat)(const char *, + char **); /* input data deformatter function */ + + +/************************************************************************/ +/* process() */ +/* */ +/* File processing function. */ +/************************************************************************/ +static void process(FILE *fid) + +{ + char line[MAX_LINE+3], *s, pline[40]; + projUV data; + + for (;;) { + double z; + + ++emess_dat.File_line; + if (!(s = fgets(line, MAX_LINE, fid))) + break; + if (!strchr(s, '\n')) { /* overlong line */ + int c; + (void)strcat(s, "\n"); + /* gobble up to newline */ + while ((c = fgetc(fid)) != EOF && c != '\n') ; + } + if (*s == tag) { + fputs(line, stdout); + continue; + } + + if (reversein) { + data.v = (*informat)(s, &s); + data.u = (*informat)(s, &s); + } else { + data.u = (*informat)(s, &s); + data.v = (*informat)(s, &s); + } + + z = strtod( s, &s ); + + if (data.v == HUGE_VAL) + data.u = HUGE_VAL; + + if (!*s && (s > line)) --s; /* assumed we gobbled \n */ + + if ( echoin) { + char t; + t = *s; + *s = '\0'; + (void)fputs(line, stdout); + *s = t; + putchar('\t'); + } + + if (data.u != HUGE_VAL) { + if( pj_transform( fromProj, toProj, 1, 0, + &(data.u), &(data.v), &z ) != 0 ) + { + data.u = HUGE_VAL; + data.v = HUGE_VAL; + emess(-3,"pj_transform(): %s", pj_strerrno(pj_errno)); + } + } + + if (data.u == HUGE_VAL) /* error output */ + fputs(oterr, stdout); + + else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */ + if (reverseout) { + fputs(rtodms(pline, data.v, 'N', 'S'), stdout); + putchar('\t'); + fputs(rtodms(pline, data.u, 'E', 'W'), stdout); + } else { + fputs(rtodms(pline, data.u, 'E', 'W'), stdout); + putchar('\t'); + fputs(rtodms(pline, data.v, 'N', 'S'), stdout); + } + + } else { /* x-y or decimal degree ascii output */ + if ( proj_angular_output(toProj, PJ_FWD) ) { + data.v *= RAD_TO_DEG; + data.u *= RAD_TO_DEG; + } + if (reverseout) { + printf(oform,data.v); putchar('\t'); + printf(oform,data.u); + } else { + printf(oform,data.u); putchar('\t'); + printf(oform,data.v); + } + } + + putchar(' '); + if( oform != nullptr ) + printf( oform, z ); + else + printf( "%.3f", z ); + if( s ) + printf( "%s", s ); + else + printf( "\n" ); + } +} + +/************************************************************************/ +/* main() */ +/************************************************************************/ + +int main(int argc, char **argv) +{ + char *arg; + char **eargv = argv; + char *from_argv[MAX_PARGS]; + char *to_argv[MAX_PARGS]; + FILE *fid; + int from_argc=0, to_argc=0, eargc = 0, mon = 0; + int have_to_flag = 0, inverse = 0, i; + int use_env_locale = 0; + + /* This is just to check that pj_init() is locale-safe */ + /* Used by nad/testvarious */ + if( getenv("PROJ_USE_ENV_LOCALE") != nullptr ) + use_env_locale = 1; + + if ((emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr) + ++emess_dat.Prog_name; + else emess_dat.Prog_name = *argv; + inverse = ! strncmp(emess_dat.Prog_name, "inv", 3); + if (argc <= 1 ) { + (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name); + exit (0); + } + /* process run line arguments */ + while (--argc > 0) { /* collect run line arguments */ + if(**++argv == '-') for(arg = *argv;;) { + switch(*++arg) { + case '\0': /* position of "stdin" */ + if (arg[-1] == '-') eargv[eargc++] = const_cast("-"); + break; + case 'v': /* monitor dump of initialization */ + mon = 1; + continue; + case 'I': /* alt. method to spec inverse */ + inverse = 1; + continue; + case 'E': /* echo ascii input to ascii output */ + echoin = 1; + continue; + case 't': /* set col. one char */ + if (arg[1]) tag = *++arg; + else emess(1,"missing -t col. 1 tag"); + continue; + case 'l': /* list projections, ellipses or units */ + if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') { + /* list projections */ + const struct PJ_LIST *lp; + int do_long = arg[1] == 'P', c; + const char *str; + + for (lp = proj_list_operations() ; lp->id ; ++lp) { + (void)printf("%s : ", lp->id); + if (do_long) /* possibly multiline description */ + (void)puts(*lp->descr); + else { /* first line, only */ + str = *lp->descr; + while ((c = *str++) && c != '\n') + putchar(c); + putchar('\n'); + } + } + } else if (arg[1] == '=') { /* list projection 'descr' */ + const struct PJ_LIST *lp; + + arg += 2; + for (lp = proj_list_operations() ; lp->id ; ++lp) + if (!strcmp(lp->id, arg)) { + (void)printf("%9s : %s\n", lp->id, *lp->descr); + break; + } + } else if (arg[1] == 'e') { /* list ellipses */ + const struct PJ_ELLPS *le; + + for (le = proj_list_ellps(); le->id ; ++le) + (void)printf("%9s %-16s %-16s %s\n", + le->id, le->major, le->ell, le->name); + } else if (arg[1] == 'u') { /* list units */ + const struct PJ_UNITS *lu; + + for (lu = proj_list_units(); lu->id ; ++lu) + (void)printf("%12s %-20s %s\n", + lu->id, lu->to_meter, lu->name); + } else if (arg[1] == 'd') { /* list datums */ + const struct PJ_DATUMS *ld; + + printf("__datum_id__ __ellipse___ __definition/comments______________________________\n" ); + for (ld = pj_get_datums_ref(); ld->id ; ++ld) + { + printf("%12s %-12s %-30s\n", + ld->id, ld->ellipse_id, ld->defn); + if( ld->comments != nullptr && strlen(ld->comments) > 0 ) + printf( "%25s %s\n", " ", ld->comments ); + } + } else if( arg[1] == 'm') { /* list prime meridians */ + const struct PJ_PRIME_MERIDIANS *lpm; + + for (lpm = proj_list_prime_meridians(); lpm->id ; ++lpm) + (void)printf("%12s %-30s\n", + lpm->id, lpm->defn); + } else + emess(1,"invalid list option: l%c",arg[1]); + exit(0); + /* cppcheck-suppress duplicateBreak */ + continue; /* artificial */ + case 'e': /* error line alternative */ + if (--argc <= 0) + noargument: + emess(1,"missing argument for -%c",*arg); + oterr = *++argv; + continue; + case 'W': /* specify seconds precision */ + case 'w': /* -W for constant field width */ + { + char c = arg[1]; + if (c != 0 && isdigit(c)) { + set_rtodms(c - '0', *arg == 'W'); + ++arg; + } else + emess(1,"-W argument missing or non-digit"); + continue; + } + case 'f': /* alternate output format degrees or xy */ + if (--argc <= 0) goto noargument; + oform = *++argv; + continue; + case 'r': /* reverse input */ + reversein = 1; + continue; + case 's': /* reverse output */ + reverseout = 1; + continue; + case 'D': /* set debug level */ + if (--argc <= 0) goto noargument; + pj_ctx_set_debug( pj_get_default_ctx(), atoi(*++argv)); + continue; + case 'd': + if (--argc <= 0) goto noargument; + sprintf(oform_buffer, "%%.%df", atoi(*++argv)); + oform = oform_buffer; + break; + default: + emess(1, "invalid option: -%c",*arg); + break; + } + break; + + } else if (strcmp(*argv,"+to") == 0 ) { + have_to_flag = 1; + + } else if (**argv == '+') { /* + argument */ + if( have_to_flag ) + { + if( to_argc < MAX_PARGS ) + to_argv[to_argc++] = *argv + 1; + else + emess(1,"overflowed + argument table"); + } + else + { + if (from_argc < MAX_PARGS) + from_argv[from_argc++] = *argv + 1; + else + emess(1,"overflowed + argument table"); + } + } else /* assumed to be input file name(s) */ + eargv[eargc++] = *argv; + } + if (eargc == 0 ) /* if no specific files force sysin */ + eargv[eargc++] = const_cast("-"); + + /* + * If the user has requested inverse, then just reverse the + * coordinate systems. + */ + if( inverse ) + { + int argcount; + + for( i = 0; i < MAX_PARGS; i++ ) + { + arg = from_argv[i]; + from_argv[i] = to_argv[i]; + to_argv[i] = arg; + } + + argcount = from_argc; + from_argc = to_argc; + to_argc = argcount; + } + + if( use_env_locale ) + { + /* Set locale from environment */ + setlocale(LC_ALL, ""); + } + + if( from_argc == 0 && to_argc != 0 ) + { + /* we will generate the from proj as the latlong of the +to in a bit */ + } + else if (!(fromProj = pj_init(from_argc, from_argv))) + { + printf( "Using from definition: " ); + for( i = 0; i < from_argc; i++ ) + printf( "%s ", from_argv[i] ); + printf( "\n" ); + + emess(3,"projection initialization failure\ncause: %s", + pj_strerrno(pj_errno)); + } + + if( to_argc == 0 ) + { + if (!(toProj = pj_latlong_from_proj( fromProj ))) + { + printf( "Using to definition: " ); + for( i = 0; i < to_argc; i++ ) + printf( "%s ", to_argv[i] ); + printf( "\n" ); + + emess(3,"projection initialization failure\ncause: %s", + pj_strerrno(pj_errno)); + } + } + else if (!(toProj = pj_init(to_argc, to_argv))) + { + printf( "Using to definition: " ); + for( i = 0; i < to_argc; i++ ) + printf( "%s ", to_argv[i] ); + printf( "\n" ); + + emess(3,"projection initialization failure\ncause: %s", + pj_strerrno(pj_errno)); + } + + if( from_argc == 0 && toProj != nullptr) + { + if (!(fromProj = pj_latlong_from_proj( toProj ))) + { + printf( "Using to definition: " ); + for( i = 0; i < to_argc; i++ ) + printf( "%s ", to_argv[i] ); + printf( "\n" ); + + emess(3,"projection initialization failure\ncause: %s", + pj_strerrno(pj_errno)); + } + } + + if( use_env_locale ) + { + /* Restore C locale to avoid issues in parsing/outputting numbers*/ + setlocale(LC_ALL, "C"); + } + + if (mon) { + printf( "%c ---- From Coordinate System ----\n", tag ); + pj_pr_list(fromProj); + printf( "%c ---- To Coordinate System ----\n", tag ); + pj_pr_list(toProj); + } + + /* set input formatting control */ + if( !fromProj->is_latlong ) + informat = strtod; + else { + informat = dmstor; + } + + if( !toProj->is_latlong && !oform ) + oform = "%.2f"; + + /* process input file list */ + for ( ; eargc-- ; ++eargv) { + if (**eargv == '-') { + fid = stdin; + emess_dat.File_name = const_cast(""); + + } else { + if ((fid = fopen(*eargv, "rt")) == nullptr) { + emess(-2, *eargv, "input file"); + continue; + } + emess_dat.File_name = *eargv; + } + emess_dat.File_line = 0; + process(fid); + fclose(fid); + emess_dat.File_name = nullptr; + } + + pj_free( fromProj ); + pj_free( toProj ); + + pj_deallocate_grids(); + + exit(0); /* normal completion */ +} -- cgit v1.2.3 From d48f97180dacceb6d03c79d69044e19ba0af3fbc Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 22 Nov 2018 23:26:32 +0100 Subject: Run reformat_cpp.sh on cs2cs.cpp --- src/cs2cs.cpp | 461 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 229 insertions(+), 232 deletions(-) (limited to 'src/cs2cs.cpp') diff --git a/src/cs2cs.cpp b/src/cs2cs.cpp index 439b172c..6f302ae3 100644 --- a/src/cs2cs.cpp +++ b/src/cs2cs.cpp @@ -33,41 +33,43 @@ #include #include +// PROJ include order is sensitive +// clang-format off #include "proj.h" #include "projects.h" #include "emess.h" +// clang-format on #define MAX_LINE 1000 #define MAX_PARGS 100 -static projPJ fromProj, toProj; +static projPJ fromProj, toProj; -static int -reversein = 0, /* != 0 reverse input arguments */ -reverseout = 0, /* != 0 reverse output arguments */ -echoin = 0, /* echo input data to output line */ -tag = '#'; /* beginning of line tag character */ +static int reversein = 0, /* != 0 reverse input arguments */ + reverseout = 0, /* != 0 reverse output arguments */ + echoin = 0, /* echo input data to output line */ + tag = '#'; /* beginning of line tag character */ -static const char *oform = nullptr; /* output format for x-y or decimal degrees */ +static const char *oform = + nullptr; /* output format for x-y or decimal degrees */ 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] ] [ +opts[=arg] ]\n" -" [+to [+opts[=arg] [ files ]\n"; + "%s\nusage: %s [ -dDeEfIlrstvwW [args] ] [ +opts[=arg] ]\n" + " [+to [+opts[=arg] [ files ]\n"; -static double (*informat)(const char *, +static double (*informat)(const char *, char **); /* input data deformatter function */ - /************************************************************************/ /* process() */ /* */ /* File processing function. */ /************************************************************************/ -static void process(FILE *fid) +static void process(FILE *fid) { - char line[MAX_LINE+3], *s, pline[40]; + char line[MAX_LINE + 3], *s, pline[40]; projUV data; for (;;) { @@ -79,8 +81,9 @@ static void process(FILE *fid) if (!strchr(s, '\n')) { /* overlong line */ int c; (void)strcat(s, "\n"); - /* gobble up to newline */ - while ((c = fgetc(fid)) != EOF && c != '\n') ; + /* gobble up to newline */ + while ((c = fgetc(fid)) != EOF && c != '\n') + ; } if (*s == tag) { fputs(line, stdout); @@ -95,14 +98,15 @@ static void process(FILE *fid) data.v = (*informat)(s, &s); } - z = strtod( s, &s ); + z = strtod(s, &s); if (data.v == HUGE_VAL) data.u = HUGE_VAL; - if (!*s && (s > line)) --s; /* assumed we gobbled \n */ + if (!*s && (s > line)) + --s; /* assumed we gobbled \n */ - if ( echoin) { + if (echoin) { char t; t = *s; *s = '\0'; @@ -112,19 +116,18 @@ static void process(FILE *fid) } if (data.u != HUGE_VAL) { - if( pj_transform( fromProj, toProj, 1, 0, - &(data.u), &(data.v), &z ) != 0 ) - { + if (pj_transform(fromProj, toProj, 1, 0, &(data.u), &(data.v), + &z) != 0) { data.u = HUGE_VAL; data.v = HUGE_VAL; - emess(-3,"pj_transform(): %s", pj_strerrno(pj_errno)); + emess(-3, "pj_transform(): %s", pj_strerrno(pj_errno)); } } if (data.u == HUGE_VAL) /* error output */ fputs(oterr, stdout); - else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */ + else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */ if (reverseout) { fputs(rtodms(pline, data.v, 'N', 'S'), stdout); putchar('\t'); @@ -136,28 +139,30 @@ static void process(FILE *fid) } } else { /* x-y or decimal degree ascii output */ - if ( proj_angular_output(toProj, PJ_FWD) ) { + if (proj_angular_output(toProj, PJ_FWD)) { data.v *= RAD_TO_DEG; data.u *= RAD_TO_DEG; } if (reverseout) { - printf(oform,data.v); putchar('\t'); - printf(oform,data.u); + printf(oform, data.v); + putchar('\t'); + printf(oform, data.u); } else { - printf(oform,data.u); putchar('\t'); - printf(oform,data.v); + printf(oform, data.u); + putchar('\t'); + printf(oform, data.v); } } putchar(' '); - if( oform != nullptr ) - printf( oform, z ); + if (oform != nullptr) + printf(oform, z); else - printf( "%.3f", z ); - if( s ) - printf( "%s", s ); + printf("%.3f", z); + if (s) + printf("%s", s); else - printf( "\n" ); + printf("\n"); } } @@ -165,187 +170,190 @@ static void process(FILE *fid) /* main() */ /************************************************************************/ -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { char *arg; char **eargv = argv; char *from_argv[MAX_PARGS]; char *to_argv[MAX_PARGS]; FILE *fid; - int from_argc=0, to_argc=0, eargc = 0, mon = 0; + int from_argc = 0, to_argc = 0, eargc = 0, mon = 0; int have_to_flag = 0, inverse = 0, i; int use_env_locale = 0; /* This is just to check that pj_init() is locale-safe */ /* Used by nad/testvarious */ - if( getenv("PROJ_USE_ENV_LOCALE") != nullptr ) + if (getenv("PROJ_USE_ENV_LOCALE") != nullptr) use_env_locale = 1; - if ((emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr) + if ((emess_dat.Prog_name = strrchr(*argv, DIR_CHAR)) != nullptr) ++emess_dat.Prog_name; - else emess_dat.Prog_name = *argv; - inverse = ! strncmp(emess_dat.Prog_name, "inv", 3); - if (argc <= 1 ) { + else + emess_dat.Prog_name = *argv; + inverse = !strncmp(emess_dat.Prog_name, "inv", 3); + if (argc <= 1) { (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name); - exit (0); + exit(0); } /* process run line arguments */ while (--argc > 0) { /* collect run line arguments */ - if(**++argv == '-') for(arg = *argv;;) { - switch(*++arg) { - case '\0': /* position of "stdin" */ - if (arg[-1] == '-') eargv[eargc++] = const_cast("-"); - break; - case 'v': /* monitor dump of initialization */ - mon = 1; - continue; - case 'I': /* alt. method to spec inverse */ - inverse = 1; - continue; - case 'E': /* echo ascii input to ascii output */ - echoin = 1; - continue; - case 't': /* set col. one char */ - if (arg[1]) tag = *++arg; - else emess(1,"missing -t col. 1 tag"); - continue; - case 'l': /* list projections, ellipses or units */ - if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') { - /* list projections */ - const struct PJ_LIST *lp; - int do_long = arg[1] == 'P', c; - const char *str; - - for (lp = proj_list_operations() ; lp->id ; ++lp) { - (void)printf("%s : ", lp->id); - if (do_long) /* possibly multiline description */ - (void)puts(*lp->descr); - else { /* first line, only */ - str = *lp->descr; - while ((c = *str++) && c != '\n') - putchar(c); - putchar('\n'); + if (**++argv == '-') + for (arg = *argv;;) { + switch (*++arg) { + case '\0': /* position of "stdin" */ + if (arg[-1] == '-') + eargv[eargc++] = const_cast("-"); + break; + case 'v': /* monitor dump of initialization */ + mon = 1; + continue; + case 'I': /* alt. method to spec inverse */ + inverse = 1; + continue; + case 'E': /* echo ascii input to ascii output */ + echoin = 1; + continue; + case 't': /* set col. one char */ + if (arg[1]) + tag = *++arg; + else + emess(1, "missing -t col. 1 tag"); + continue; + case 'l': /* list projections, ellipses or units */ + if (!arg[1] || arg[1] == 'p' || arg[1] == 'P') { + /* list projections */ + const struct PJ_LIST *lp; + int do_long = arg[1] == 'P', c; + const char *str; + + for (lp = proj_list_operations(); lp->id; ++lp) { + (void)printf("%s : ", lp->id); + if (do_long) /* possibly multiline description */ + (void)puts(*lp->descr); + else { /* first line, only */ + str = *lp->descr; + while ((c = *str++) && c != '\n') + putchar(c); + putchar('\n'); + } } - } - } else if (arg[1] == '=') { /* list projection 'descr' */ - const struct PJ_LIST *lp; - - arg += 2; - for (lp = proj_list_operations() ; lp->id ; ++lp) - if (!strcmp(lp->id, arg)) { - (void)printf("%9s : %s\n", lp->id, *lp->descr); - break; + } else if (arg[1] == '=') { /* list projection 'descr' */ + const struct PJ_LIST *lp; + + arg += 2; + for (lp = proj_list_operations(); lp->id; ++lp) + if (!strcmp(lp->id, arg)) { + (void)printf("%9s : %s\n", lp->id, *lp->descr); + break; + } + } else if (arg[1] == 'e') { /* list ellipses */ + const struct PJ_ELLPS *le; + + for (le = proj_list_ellps(); le->id; ++le) + (void)printf("%9s %-16s %-16s %s\n", le->id, + le->major, le->ell, le->name); + } else if (arg[1] == 'u') { /* list units */ + const struct PJ_UNITS *lu; + + for (lu = proj_list_units(); lu->id; ++lu) + (void)printf("%12s %-20s %s\n", lu->id, + lu->to_meter, lu->name); + } else if (arg[1] == 'd') { /* list datums */ + const struct PJ_DATUMS *ld; + + printf("__datum_id__ __ellipse___ " + "__definition/" + "comments______________________________\n"); + for (ld = pj_get_datums_ref(); ld->id; ++ld) { + printf("%12s %-12s %-30s\n", ld->id, ld->ellipse_id, + ld->defn); + if (ld->comments != nullptr && + strlen(ld->comments) > 0) + printf("%25s %s\n", " ", ld->comments); } - } else if (arg[1] == 'e') { /* list ellipses */ - const struct PJ_ELLPS *le; - - for (le = proj_list_ellps(); le->id ; ++le) - (void)printf("%9s %-16s %-16s %s\n", - le->id, le->major, le->ell, le->name); - } else if (arg[1] == 'u') { /* list units */ - const struct PJ_UNITS *lu; - - for (lu = proj_list_units(); lu->id ; ++lu) - (void)printf("%12s %-20s %s\n", - lu->id, lu->to_meter, lu->name); - } else if (arg[1] == 'd') { /* list datums */ - const struct PJ_DATUMS *ld; - - printf("__datum_id__ __ellipse___ __definition/comments______________________________\n" ); - for (ld = pj_get_datums_ref(); ld->id ; ++ld) - { - printf("%12s %-12s %-30s\n", - ld->id, ld->ellipse_id, ld->defn); - if( ld->comments != nullptr && strlen(ld->comments) > 0 ) - printf( "%25s %s\n", " ", ld->comments ); - } - } else if( arg[1] == 'm') { /* list prime meridians */ - const struct PJ_PRIME_MERIDIANS *lpm; - - for (lpm = proj_list_prime_meridians(); lpm->id ; ++lpm) - (void)printf("%12s %-30s\n", - lpm->id, lpm->defn); - } else - emess(1,"invalid list option: l%c",arg[1]); - exit(0); - /* cppcheck-suppress duplicateBreak */ - continue; /* artificial */ - case 'e': /* error line alternative */ - if (--argc <= 0) - noargument: - emess(1,"missing argument for -%c",*arg); - oterr = *++argv; - continue; - case 'W': /* specify seconds precision */ - case 'w': /* -W for constant field width */ - { - char c = arg[1]; - if (c != 0 && isdigit(c)) { - set_rtodms(c - '0', *arg == 'W'); - ++arg; - } else - emess(1,"-W argument missing or non-digit"); - continue; - } - case 'f': /* alternate output format degrees or xy */ - if (--argc <= 0) goto noargument; - oform = *++argv; - continue; - case 'r': /* reverse input */ - reversein = 1; - continue; - case 's': /* reverse output */ - reverseout = 1; - continue; - case 'D': /* set debug level */ - if (--argc <= 0) goto noargument; - pj_ctx_set_debug( pj_get_default_ctx(), atoi(*++argv)); - continue; - case 'd': - if (--argc <= 0) goto noargument; - sprintf(oform_buffer, "%%.%df", atoi(*++argv)); - oform = oform_buffer; - break; - default: - emess(1, "invalid option: -%c",*arg); + } else if (arg[1] == 'm') { /* list prime meridians */ + const struct PJ_PRIME_MERIDIANS *lpm; + + for (lpm = proj_list_prime_meridians(); lpm->id; ++lpm) + (void)printf("%12s %-30s\n", lpm->id, lpm->defn); + } else + emess(1, "invalid list option: l%c", arg[1]); + exit(0); + /* cppcheck-suppress duplicateBreak */ + continue; /* artificial */ + case 'e': /* error line alternative */ + if (--argc <= 0) + noargument: + emess(1, "missing argument for -%c", *arg); + oterr = *++argv; + continue; + case 'W': /* specify seconds precision */ + case 'w': /* -W for constant field width */ + { + char c = arg[1]; + if (c != 0 && isdigit(c)) { + set_rtodms(c - '0', *arg == 'W'); + ++arg; + } else + emess(1, "-W argument missing or non-digit"); + continue; + } + case 'f': /* alternate output format degrees or xy */ + if (--argc <= 0) + goto noargument; + oform = *++argv; + continue; + case 'r': /* reverse input */ + reversein = 1; + continue; + case 's': /* reverse output */ + reverseout = 1; + continue; + case 'D': /* set debug level */ + if (--argc <= 0) + goto noargument; + pj_ctx_set_debug(pj_get_default_ctx(), atoi(*++argv)); + continue; + case 'd': + if (--argc <= 0) + goto noargument; + sprintf(oform_buffer, "%%.%df", atoi(*++argv)); + oform = oform_buffer; + break; + default: + emess(1, "invalid option: -%c", *arg); + break; + } break; } - break; - - } else if (strcmp(*argv,"+to") == 0 ) { + else if (strcmp(*argv, "+to") == 0) { have_to_flag = 1; } else if (**argv == '+') { /* + argument */ - if( have_to_flag ) - { - if( to_argc < MAX_PARGS ) + if (have_to_flag) { + if (to_argc < MAX_PARGS) to_argv[to_argc++] = *argv + 1; else - emess(1,"overflowed + argument table"); - } - else - { + emess(1, "overflowed + argument table"); + } else { if (from_argc < MAX_PARGS) from_argv[from_argc++] = *argv + 1; else - emess(1,"overflowed + argument table"); + emess(1, "overflowed + argument table"); } } else /* assumed to be input file name(s) */ eargv[eargc++] = *argv; } - if (eargc == 0 ) /* if no specific files force sysin */ - eargv[eargc++] = const_cast("-"); + if (eargc == 0) /* if no specific files force sysin */ + eargv[eargc++] = const_cast("-"); - /* + /* * If the user has requested inverse, then just reverse the * coordinate systems. */ - if( inverse ) - { - int argcount; - - for( i = 0; i < MAX_PARGS; i++ ) - { + if (inverse) { + int argcount; + + for (i = 0; i < MAX_PARGS; i++) { arg = from_argv[i]; from_argv[i] = to_argv[i]; to_argv[i] = arg; @@ -356,93 +364,82 @@ int main(int argc, char **argv) to_argc = argcount; } - if( use_env_locale ) - { + if (use_env_locale) { /* Set locale from environment */ setlocale(LC_ALL, ""); } - if( from_argc == 0 && to_argc != 0 ) - { + if (from_argc == 0 && to_argc != 0) { /* we will generate the from proj as the latlong of the +to in a bit */ - } - else if (!(fromProj = pj_init(from_argc, from_argv))) - { - printf( "Using from definition: " ); - for( i = 0; i < from_argc; i++ ) - printf( "%s ", from_argv[i] ); - printf( "\n" ); - - emess(3,"projection initialization failure\ncause: %s", + } else if (!(fromProj = pj_init(from_argc, from_argv))) { + printf("Using from definition: "); + for (i = 0; i < from_argc; i++) + printf("%s ", from_argv[i]); + printf("\n"); + + emess(3, "projection initialization failure\ncause: %s", pj_strerrno(pj_errno)); } - if( to_argc == 0 ) - { - if (!(toProj = pj_latlong_from_proj( fromProj ))) - { - printf( "Using to definition: " ); - for( i = 0; i < to_argc; i++ ) - printf( "%s ", to_argv[i] ); - printf( "\n" ); - - emess(3,"projection initialization failure\ncause: %s", + if (to_argc == 0) { + if (!(toProj = pj_latlong_from_proj(fromProj))) { + printf("Using to definition: "); + for (i = 0; i < to_argc; i++) + printf("%s ", to_argv[i]); + printf("\n"); + + emess(3, "projection initialization failure\ncause: %s", pj_strerrno(pj_errno)); - } - } - else if (!(toProj = pj_init(to_argc, to_argv))) - { - printf( "Using to definition: " ); - for( i = 0; i < to_argc; i++ ) - printf( "%s ", to_argv[i] ); - printf( "\n" ); - - emess(3,"projection initialization failure\ncause: %s", + } + } else if (!(toProj = pj_init(to_argc, to_argv))) { + printf("Using to definition: "); + for (i = 0; i < to_argc; i++) + printf("%s ", to_argv[i]); + printf("\n"); + + emess(3, "projection initialization failure\ncause: %s", pj_strerrno(pj_errno)); } - if( from_argc == 0 && toProj != nullptr) - { - if (!(fromProj = pj_latlong_from_proj( toProj ))) - { - printf( "Using to definition: " ); - for( i = 0; i < to_argc; i++ ) - printf( "%s ", to_argv[i] ); - printf( "\n" ); - - emess(3,"projection initialization failure\ncause: %s", + if (from_argc == 0 && toProj != nullptr) { + if (!(fromProj = pj_latlong_from_proj(toProj))) { + printf("Using to definition: "); + for (i = 0; i < to_argc; i++) + printf("%s ", to_argv[i]); + printf("\n"); + + emess(3, "projection initialization failure\ncause: %s", pj_strerrno(pj_errno)); - } + } } - if( use_env_locale ) - { + if (use_env_locale) { /* Restore C locale to avoid issues in parsing/outputting numbers*/ setlocale(LC_ALL, "C"); } if (mon) { - printf( "%c ---- From Coordinate System ----\n", tag ); + printf("%c ---- From Coordinate System ----\n", tag); pj_pr_list(fromProj); - printf( "%c ---- To Coordinate System ----\n", tag ); + printf("%c ---- To Coordinate System ----\n", tag); pj_pr_list(toProj); } /* set input formatting control */ - if( !fromProj->is_latlong ) + if (!fromProj->is_latlong) informat = strtod; else { informat = dmstor; } - if( !toProj->is_latlong && !oform ) + if (!toProj->is_latlong && !oform) oform = "%.2f"; /* process input file list */ - for ( ; eargc-- ; ++eargv) { + for (; eargc--; ++eargv) { if (**eargv == '-') { fid = stdin; - emess_dat.File_name = const_cast(""); + emess_dat.File_name = const_cast(""); } else { if ((fid = fopen(*eargv, "rt")) == nullptr) { @@ -457,8 +454,8 @@ int main(int argc, char **argv) emess_dat.File_name = nullptr; } - pj_free( fromProj ); - pj_free( toProj ); + pj_free(fromProj); + pj_free(toProj); pj_deallocate_grids(); -- cgit v1.2.3 From a66c12277666489cac74535bad8d2cf565ad542d Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 23 Nov 2018 15:51:33 +0100 Subject: cs2cs: upgrade to use proj_create_crs_to_crs() --- src/cs2cs.cpp | 327 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 250 insertions(+), 77 deletions(-) (limited to 'src/cs2cs.cpp') diff --git a/src/cs2cs.cpp b/src/cs2cs.cpp index 6f302ae3..6f4c4a55 100644 --- a/src/cs2cs.cpp +++ b/src/cs2cs.cpp @@ -26,6 +26,8 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ +#define FROM_PROJ_CPP + #include #include #include @@ -33,6 +35,11 @@ #include #include +#include +#include + +#include + // PROJ include order is sensitive // clang-format off #include "proj.h" @@ -41,9 +48,15 @@ // clang-format on #define MAX_LINE 1000 -#define MAX_PARGS 100 -static projPJ fromProj, toProj; +static PJ *transformation = nullptr; + +static bool srcIsGeog = false; +static double srcToRadians = 0.0; + +static bool destIsGeog = false; +static double destToRadians = 0.0; +static bool destIsLatLong = false; static int reversein = 0, /* != 0 reverse input arguments */ reverseout = 0, /* != 0 reverse output arguments */ @@ -116,19 +129,45 @@ static void process(FILE *fid) } if (data.u != HUGE_VAL) { - if (pj_transform(fromProj, toProj, 1, 0, &(data.u), &(data.v), - &z) != 0) { - data.u = HUGE_VAL; - data.v = HUGE_VAL; - emess(-3, "pj_transform(): %s", pj_strerrno(pj_errno)); + + if (srcIsGeog) { + /* dmstor gives values to radians. Convert now to the SRS unit + */ + data.u /= srcToRadians; + data.v /= srcToRadians; } + + PJ_COORD coord; + coord.xyzt.x = data.u; + coord.xyzt.y = data.v; + coord.xyzt.z = z; + coord.xyzt.t = HUGE_VAL; + coord = proj_trans(transformation, PJ_FWD, coord); + data.u = coord.xyz.x; + data.v = coord.xyz.y; + z = coord.xyz.z; } if (data.u == HUGE_VAL) /* error output */ fputs(oterr, stdout); - else if (pj_is_latlong(toProj) && !oform) { /*ascii DMS output */ - if (reverseout) { + else if (destIsGeog && !oform) { /*ascii DMS output */ + + // rtodms() expect radians: convert from the output SRS unit + data.u *= destToRadians; + data.v *= destToRadians; + + if (destIsLatLong) { + if (reverseout) { + fputs(rtodms(pline, data.v, 'E', 'W'), stdout); + putchar('\t'); + fputs(rtodms(pline, data.u, 'N', 'S'), stdout); + } else { + fputs(rtodms(pline, data.u, 'N', 'S'), stdout); + putchar('\t'); + fputs(rtodms(pline, data.v, 'E', 'W'), stdout); + } + } else if (reverseout) { fputs(rtodms(pline, data.v, 'N', 'S'), stdout); putchar('\t'); fputs(rtodms(pline, data.u, 'E', 'W'), stdout); @@ -139,9 +178,9 @@ static void process(FILE *fid) } } else { /* x-y or decimal degree ascii output */ - if (proj_angular_output(toProj, PJ_FWD)) { - data.v *= RAD_TO_DEG; - data.u *= RAD_TO_DEG; + if (destIsGeog) { + data.v *= destToRadians * RAD_TO_DEG; + data.u *= destToRadians * RAD_TO_DEG; } if (reverseout) { printf(oform, data.v); @@ -166,6 +205,105 @@ static void process(FILE *fid) } } +/************************************************************************/ +/* instanciate_crs() */ +/************************************************************************/ + +static PJ_OBJ *instanciate_crs(const std::string &definition, + const char *const *optionsImportCRS, + bool &isGeog, double &toRadians, + bool &isLatFirst) { + PJ_OBJ *crs = proj_obj_create_from_user_input(nullptr, definition.c_str(), + optionsImportCRS); + if (!crs) { + return nullptr; + } + + isGeog = false; + toRadians = 0.0; + isLatFirst = false; + + auto type = proj_obj_get_type(crs); + if (type == PJ_OBJ_TYPE_BOUND_CRS) { + auto base = proj_obj_get_source_crs(crs); + proj_obj_unref(crs); + crs = base; + type = proj_obj_get_type(crs); + } + if (type == PJ_OBJ_TYPE_GEOGRAPHIC_2D_CRS || + type == PJ_OBJ_TYPE_GEOGRAPHIC_3D_CRS) { + auto cs = proj_obj_crs_get_coordinate_system(crs); + assert(cs); + + isGeog = true; + const char *axisName = ""; + proj_obj_cs_get_axis_info(cs, 0, + &axisName, // name, + nullptr, // abbrev + nullptr, // direction + &toRadians, + nullptr // unit name + ); + isLatFirst = + NS_PROJ::internal::ci_find(std::string(axisName), "latitude") != + std::string::npos; + + proj_obj_unref(cs); + } + + return crs; +} + +/************************************************************************/ +/* get_geog_crs_proj_string_from_proj_crs() */ +/************************************************************************/ + +static std::string get_geog_crs_proj_string_from_proj_crs(PJ_OBJ *src, + double &toRadians, + bool &isLatFirst) { + auto srcType = proj_obj_get_type(src); + if (srcType == PJ_OBJ_TYPE_BOUND_CRS) { + auto base = proj_obj_get_source_crs(src); + assert(base); + proj_obj_unref(src); + src = base; + srcType = proj_obj_get_type(src); + } + if (srcType != PJ_OBJ_TYPE_PROJECTED_CRS) { + return std::string(); + } + + auto base = proj_obj_get_source_crs(src); + assert(base); + auto baseType = proj_obj_get_type(base); + if (baseType != PJ_OBJ_TYPE_GEOGRAPHIC_2D_CRS && + baseType != PJ_OBJ_TYPE_GEOGRAPHIC_3D_CRS) { + proj_obj_unref(base); + return std::string(); + } + + auto cs = proj_obj_crs_get_coordinate_system(base); + assert(cs); + + const char *axisName = ""; + proj_obj_cs_get_axis_info(cs, 0, + &axisName, // name, + nullptr, // abbrev + nullptr, // direction + &toRadians, + nullptr // unit name + ); + isLatFirst = NS_PROJ::internal::ci_find(std::string(axisName), + "latitude") != std::string::npos; + + proj_obj_unref(cs); + + auto retCStr = proj_obj_as_proj_string(base, PJ_PROJ_5, nullptr); + std::string ret(retCStr ? retCStr : ""); + proj_obj_unref(base); + return ret; +} + /************************************************************************/ /* main() */ /************************************************************************/ @@ -173,11 +311,11 @@ static void process(FILE *fid) int main(int argc, char **argv) { char *arg; char **eargv = argv; - char *from_argv[MAX_PARGS]; - char *to_argv[MAX_PARGS]; + std::string fromStr; + std::string toStr; FILE *fid; - int from_argc = 0, to_argc = 0, eargc = 0, mon = 0; - int have_to_flag = 0, inverse = 0, i; + int eargc = 0, mon = 0; + int have_to_flag = 0, inverse = 0; int use_env_locale = 0; /* This is just to check that pj_init() is locale-safe */ @@ -185,6 +323,11 @@ int main(int argc, char **argv) { if (getenv("PROJ_USE_ENV_LOCALE") != nullptr) use_env_locale = 1; + /* Enable compatibility mode for init=epsg:XXXX by default */ + if (getenv("PROJ_USE_PROJ4_INIT_RULES") == nullptr) { + proj_context_use_proj4_init_rules(nullptr, true); + } + if ((emess_dat.Prog_name = strrchr(*argv, DIR_CHAR)) != nullptr) ++emess_dat.Prog_name; else @@ -194,9 +337,27 @@ int main(int argc, char **argv) { (void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name); exit(0); } + + // First pass to check if we have "cs2cs [-bla]* " syntax + int countNonOptionArg = 0; + for (int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (argv[i][1] == '\0') { + countNonOptionArg++; + } + } else { + if (strcmp(argv[i], "+to") == 0) { + countNonOptionArg = -1; + break; + } + countNonOptionArg++; + } + } + const bool isSrcDestSyntax = (countNonOptionArg == 2); + /* process run line arguments */ while (--argc > 0) { /* collect run line arguments */ - if (**++argv == '-') + if (**++argv == '-') { for (arg = *argv;;) { switch (*++arg) { case '\0': /* position of "stdin" */ @@ -325,21 +486,28 @@ int main(int argc, char **argv) { } break; } - else if (strcmp(*argv, "+to") == 0) { + } else if (isSrcDestSyntax) { + if (fromStr.empty()) + fromStr = *argv; + else + toStr = *argv; + } else if (strcmp(*argv, "+to") == 0) { have_to_flag = 1; } else if (**argv == '+') { /* + argument */ if (have_to_flag) { - if (to_argc < MAX_PARGS) - to_argv[to_argc++] = *argv + 1; - else - emess(1, "overflowed + argument table"); + if (!toStr.empty()) + toStr += ' '; + toStr += *argv; } else { - if (from_argc < MAX_PARGS) - from_argv[from_argc++] = *argv + 1; - else - emess(1, "overflowed + argument table"); + if (!fromStr.empty()) + fromStr += ' '; + fromStr += *argv; } + } else if (!have_to_flag) { + fromStr = *argv; + } else if (toStr.empty()) { + toStr = *argv; } else /* assumed to be input file name(s) */ eargv[eargc++] = *argv; } @@ -351,17 +519,7 @@ int main(int argc, char **argv) { * coordinate systems. */ if (inverse) { - int argcount; - - for (i = 0; i < MAX_PARGS; i++) { - arg = from_argv[i]; - from_argv[i] = to_argv[i]; - to_argv[i] = arg; - } - - argcount = from_argc; - from_argc = to_argc; - to_argc = argcount; + std::swap(fromStr, toStr); } if (use_env_locale) { @@ -369,48 +527,64 @@ int main(int argc, char **argv) { setlocale(LC_ALL, ""); } - if (from_argc == 0 && to_argc != 0) { - /* we will generate the from proj as the latlong of the +to in a bit */ - } else if (!(fromProj = pj_init(from_argc, from_argv))) { - printf("Using from definition: "); - for (i = 0; i < from_argc; i++) - printf("%s ", from_argv[i]); - printf("\n"); - - emess(3, "projection initialization failure\ncause: %s", - pj_strerrno(pj_errno)); + if (fromStr.empty() && toStr.empty()) { + emess(3, "missing source and target coordinate systems"); } - if (to_argc == 0) { - if (!(toProj = pj_latlong_from_proj(fromProj))) { - printf("Using to definition: "); - for (i = 0; i < to_argc; i++) - printf("%s ", to_argv[i]); - printf("\n"); + const char *const optionsProj4Mode[] = {"USE_PROJ4_INIT_RULES=YES", + nullptr}; + const char *const *optionsImportCRS = + proj_context_get_use_proj4_init_rules(nullptr) ? optionsProj4Mode + : nullptr; + + PJ_OBJ *src = nullptr; + if (!fromStr.empty()) { + bool ignored; + src = instanciate_crs(fromStr, optionsImportCRS, srcIsGeog, + srcToRadians, ignored); + if (!src) { + emess(3, "cannot instanciate source coordinate system"); + } + } - emess(3, "projection initialization failure\ncause: %s", - pj_strerrno(pj_errno)); + PJ_OBJ *dst = nullptr; + if (!toStr.empty()) { + dst = instanciate_crs(toStr, optionsImportCRS, destIsGeog, + destToRadians, destIsLatLong); + if (!dst) { + emess(3, "cannot instanciate target coordinate system"); } - } else if (!(toProj = pj_init(to_argc, to_argv))) { - printf("Using to definition: "); - for (i = 0; i < to_argc; i++) - printf("%s ", to_argv[i]); - printf("\n"); + } - emess(3, "projection initialization failure\ncause: %s", - pj_strerrno(pj_errno)); + if (toStr.empty()) { + assert(src); + toStr = get_geog_crs_proj_string_from_proj_crs(src, destToRadians, + destIsLatLong); + if (toStr.empty()) { + emess(3, + "missing target CRS and source CRS is not a projected CRS"); + } + destIsGeog = true; + } else if (fromStr.empty()) { + assert(dst); + bool ignored; + fromStr = + get_geog_crs_proj_string_from_proj_crs(dst, srcToRadians, ignored); + if (fromStr.empty()) { + emess(3, + "missing source CRS and target CRS is not a projected CRS"); + } + srcIsGeog = true; } - if (from_argc == 0 && toProj != nullptr) { - if (!(fromProj = pj_latlong_from_proj(toProj))) { - printf("Using to definition: "); - for (i = 0; i < to_argc; i++) - printf("%s ", to_argv[i]); - printf("\n"); + proj_obj_unref(src); + proj_obj_unref(dst); - emess(3, "projection initialization failure\ncause: %s", - pj_strerrno(pj_errno)); - } + transformation = proj_create_crs_to_crs(nullptr, fromStr.c_str(), + toStr.c_str(), nullptr); + if (!transformation) { + emess(3, "cannot initialize transformation\ncause: %s", + pj_strerrno(pj_errno)); } if (use_env_locale) { @@ -420,19 +594,19 @@ int main(int argc, char **argv) { if (mon) { printf("%c ---- From Coordinate System ----\n", tag); - pj_pr_list(fromProj); + printf("%s\n", fromStr.c_str()); printf("%c ---- To Coordinate System ----\n", tag); - pj_pr_list(toProj); + printf("%s\n", toStr.c_str()); } /* set input formatting control */ - if (!fromProj->is_latlong) + if (!srcIsGeog) informat = strtod; else { informat = dmstor; } - if (!toProj->is_latlong && !oform) + if (!destIsGeog && !oform) oform = "%.2f"; /* process input file list */ @@ -454,8 +628,7 @@ int main(int argc, char **argv) { emess_dat.File_name = nullptr; } - pj_free(fromProj); - pj_free(toProj); + proj_destroy(transformation); pj_deallocate_grids(); -- cgit v1.2.3 From 67758b2c67ea329116b59818c038797667c4e1d1 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 26 Nov 2018 15:47:57 +0100 Subject: Redirect epsg:XXXX and IGNF:XXXX CRS expansions to the database, and remove the data/epsg and data/IGNF files --- src/cs2cs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/cs2cs.cpp') diff --git a/src/cs2cs.cpp b/src/cs2cs.cpp index 6f4c4a55..8dc23ac5 100644 --- a/src/cs2cs.cpp +++ b/src/cs2cs.cpp @@ -534,8 +534,8 @@ int main(int argc, char **argv) { const char *const optionsProj4Mode[] = {"USE_PROJ4_INIT_RULES=YES", nullptr}; const char *const *optionsImportCRS = - proj_context_get_use_proj4_init_rules(nullptr) ? optionsProj4Mode - : nullptr; + proj_context_get_use_proj4_init_rules(nullptr, TRUE) ? optionsProj4Mode + : nullptr; PJ_OBJ *src = nullptr; if (!fromStr.empty()) { -- cgit v1.2.3 From 664bd689bf8dd3ca38a5071459902b89114e88eb Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Fri, 30 Nov 2018 02:36:00 +0100 Subject: C API: do not 'cache' PROJ context in PJ_OBJ objects We store the PJ_CONTEXT* in the PJ_OBJ objects, but this might cause issues in multi-threaded uses. For example, before this change, let's imagie: - a PJ_OBJ is created in thread A with a PJ_CONTEXT that is specific to this thread A - PJ_OBJ is transfered to another thread that operates on it. It might thus use the PJ_CONTEXT that was TLS(A) - in the meantime thread A does completely different things, but still operate on its PJ_CONTEXT. We might get a concurrent use of the PJ_CONTEXT despite working on different PJ_OBJ Another situation is when using constructor functions that take two PJ_OBJ. Up to now, we arbitrarily selected the context of one of the arguments to attach it to the new object. So better be explicit on which context is used. For reference, in those wrappers of the C++ API, the context is mostly used for two things: - reporting C++ exceptions as PROJ errors with the error handler attached to the PJ_CONTEXT - using the database handle that is associated with the PJ_CONTEXT. --- src/cs2cs.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/cs2cs.cpp') diff --git a/src/cs2cs.cpp b/src/cs2cs.cpp index 8dc23ac5..a8d126cf 100644 --- a/src/cs2cs.cpp +++ b/src/cs2cs.cpp @@ -225,19 +225,19 @@ static PJ_OBJ *instanciate_crs(const std::string &definition, auto type = proj_obj_get_type(crs); if (type == PJ_OBJ_TYPE_BOUND_CRS) { - auto base = proj_obj_get_source_crs(crs); + auto base = proj_obj_get_source_crs(nullptr, crs); proj_obj_unref(crs); crs = base; type = proj_obj_get_type(crs); } if (type == PJ_OBJ_TYPE_GEOGRAPHIC_2D_CRS || type == PJ_OBJ_TYPE_GEOGRAPHIC_3D_CRS) { - auto cs = proj_obj_crs_get_coordinate_system(crs); + auto cs = proj_obj_crs_get_coordinate_system(nullptr, crs); assert(cs); isGeog = true; const char *axisName = ""; - proj_obj_cs_get_axis_info(cs, 0, + proj_obj_cs_get_axis_info(nullptr, cs, 0, &axisName, // name, nullptr, // abbrev nullptr, // direction @@ -263,7 +263,7 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ_OBJ *src, bool &isLatFirst) { auto srcType = proj_obj_get_type(src); if (srcType == PJ_OBJ_TYPE_BOUND_CRS) { - auto base = proj_obj_get_source_crs(src); + auto base = proj_obj_get_source_crs(nullptr, src); assert(base); proj_obj_unref(src); src = base; @@ -273,7 +273,7 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ_OBJ *src, return std::string(); } - auto base = proj_obj_get_source_crs(src); + auto base = proj_obj_get_source_crs(nullptr, src); assert(base); auto baseType = proj_obj_get_type(base); if (baseType != PJ_OBJ_TYPE_GEOGRAPHIC_2D_CRS && @@ -282,11 +282,11 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ_OBJ *src, return std::string(); } - auto cs = proj_obj_crs_get_coordinate_system(base); + auto cs = proj_obj_crs_get_coordinate_system(nullptr, base); assert(cs); const char *axisName = ""; - proj_obj_cs_get_axis_info(cs, 0, + proj_obj_cs_get_axis_info(nullptr, cs, 0, &axisName, // name, nullptr, // abbrev nullptr, // direction @@ -298,7 +298,7 @@ static std::string get_geog_crs_proj_string_from_proj_crs(PJ_OBJ *src, proj_obj_unref(cs); - auto retCStr = proj_obj_as_proj_string(base, PJ_PROJ_5, nullptr); + auto retCStr = proj_obj_as_proj_string(nullptr, base, PJ_PROJ_5, nullptr); std::string ret(retCStr ? retCStr : ""); proj_obj_unref(base); return ret; -- cgit v1.2.3