diff options
| author | Kristian Evers <kristianevers@gmail.com> | 2017-11-15 21:00:49 +0100 |
|---|---|---|
| committer | Kristian Evers <kristianevers@gmail.com> | 2017-11-15 21:00:49 +0100 |
| commit | 94771c16596d75c989657447f65d52e8115d3426 (patch) | |
| tree | 0f7e4206ca3b724e9ebc24c065a137490bf0adfb | |
| parent | 91b641e627a028786e56276d18501dd518d6b112 (diff) | |
| parent | f08a7c0cf9dc3ed017a224e196e9d251da8dc97c (diff) | |
| download | PROJ-94771c16596d75c989657447f65d52e8115d3426.tar.gz PROJ-94771c16596d75c989657447f65d52e8115d3426.zip | |
Merge remote-tracking branch 'osgeo/master' into docs-release-4.10.0
169 files changed, 9234 insertions, 9128 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d6bbe8ea..f489f4ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,20 @@ cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR) project(PROJ4 C) set(PROJECT_INTERN_NAME PROJ) +# Set warnings +if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") + set(CMAKE_C_FLAGS "/WX ${CMAKE_C_FLAGS}") +elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_C_FLAGS "-std=c89 -Wall -Wextra -Wswitch -Werror \ + -Wunused-parameter -Wmissing-prototypes -Wmissing-declarations -Wformat \ + -Werror=format-security -Wshadow ${CMAKE_C_FLAGS}") +elseif("${CMAKE_C_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_C_FLAGS "-std=c89 -Wall -Wextra -Wswitch -Werror \ + -Wc99-extensions -Wc11-extensions -Wunused-parameter -Wmissing-prototypes \ + -Wmissing-declarations -Wformat -Werror=format-security -Wshadow \ + -Wfloat-conversion ${CMAKE_C_FLAGS}") +endif() + ################################################################################# # PROJ4 CMake modules ################################################################################# diff --git a/appveyor.yml b/appveyor.yml index d878c73d..9f66b22e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,7 +41,7 @@ build_script: - if "%BUILD_TYPE%" == "cmake" if "%platform%" == "x86" SET VS_FULL=%VS_VERSION% - if "%BUILD_TYPE%" == "cmake" echo "%VS_FULL%" # warning C4706: assignment within conditional expression - - if "%BUILD_TYPE%" == "cmake" cmake -G "%VS_FULL%" . -DSELFTEST=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=../bin -DBUILD_LIBPROJ_SHARED=ON -DCMAKE_C_FLAGS="/W4 /wd4706 /WX /D_CRT_SECURE_NO_WARNINGS" + - if "%BUILD_TYPE%" == "cmake" cmake -G "%VS_FULL%" . -DCMAKE_BUILD_TYPE=Release -DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=../bin -DBUILD_LIBPROJ_SHARED=ON -DCMAKE_C_FLAGS="/W4 /wd4706 /WX /D_CRT_SECURE_NO_WARNINGS" - if "%BUILD_TYPE%" == "cmake" cmake --build . --config Release test_script: @@ -53,10 +53,15 @@ test_script: - curl -O http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx - 7z e -aoa -y proj-datumgrid-1.6.zip - dir - - cd ..\bin + - cd .. + - dir + - cd bin - echo "Contents of current directory:" - dir - - proj.exe -VC + - gie.exe ..\test\gie\builtins.gie + - gie.exe ..\test\gie\more_builtins.gie + - gie.exe ..\test\gie\deformation.gie + - gie.exe ..\test\gie\axisswap.gie deploy: off diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 788273a9..494eef9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,11 +3,12 @@ include(lib_proj.cmake) # configure executable build -option(BUILD_CCT "Build cct (coordinate conversion and transformation tool)" ON) -option(BUILD_CS2CS "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON) -option(BUILD_PROJ "Build proj (cartographic projection tool : latlong <-> projected coordinates" ON) -option(BUILD_GEOD "Build geod (computation of geodesic lines)" ON) -option(BUILD_NAD2BIN "Build nad2bin (format conversion tool) " ON) +option(BUILD_CCT "Build cct (coordinate conversion and transformation tool)" ON) +option(BUILD_CS2CS "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON) +option(BUILD_GEOD "Build geod (computation of geodesic lines)" ON) +option(BUILD_GIE "Build gie (geospatial integrity investigation environment - a PROJ.4 test tool)" ON) +option(BUILD_NAD2BIN "Build nad2bin (format conversion tool)" ON) +option(BUILD_PROJ "Build proj (cartographic projection tool : latlong <-> projected coordinates)" ON) if(NOT MSVC) if (NOT APPLE) @@ -33,11 +34,6 @@ if(BUILD_CS2CS) set(BIN_TARGETS ${BIN_TARGETS} cs2cs) endif(BUILD_CS2CS) -if(BUILD_PROJ) - include(bin_proj.cmake) - set(BIN_TARGETS ${BIN_TARGETS} binproj) -endif(BUILD_PROJ) - if(BUILD_GEOD) include(bin_geod.cmake) include(bin_geodtest.cmake) @@ -49,6 +45,16 @@ if(BUILD_NAD2BIN) set(BIN_TARGETS ${BIN_TARGETS} nad2bin) endif(BUILD_NAD2BIN) +if(BUILD_PROJ) + include(bin_proj.cmake) + set(BIN_TARGETS ${BIN_TARGETS} binproj) +endif(BUILD_PROJ) + +if(BUILD_GIE) + include(bin_gie.cmake) + set(BIN_TARGETS ${BIN_TARGETS} gie) +endif(BUILD_GIE) + if (MSVC OR CMAKE_CONFIGURATION_TYPES) if(BIN_TARGETS) # Add _d suffix for your debug versions of the tools diff --git a/src/Makefile.am b/src/Makefile.am index 25b7456c..58514592 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ AM_CFLAGS = @C_WFLAGS@ -bin_PROGRAMS = proj nad2bin geod cs2cs cct +bin_PROGRAMS = proj nad2bin geod cs2cs gie cct EXTRA_PROGRAMS = multistresstest test228 TESTS = geodtest @@ -12,7 +12,7 @@ AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \ include_HEADERS = proj.h proj_api.h projects.h geodesic.h \ org_proj4_Projections.h org_proj4_PJ.h -EXTRA_DIST = makefile.vc proj.def bin_cct.cmake bin_cs2cs.cmake \ +EXTRA_DIST = makefile.vc proj.def bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \ bin_geod.cmake bin_nad2bin.cmake bin_proj.cmake \ lib_proj.cmake CMakeLists.txt bin_geodtest.cmake geodtest.c @@ -21,15 +21,19 @@ cs2cs_SOURCES = cs2cs.c gen_cheb.c p_series.c cct_SOURCES = cct.c proj_strtod.c optargpm.h nad2bin_SOURCES = nad2bin.c geod_SOURCES = geod.c geod_set.c geod_interface.c geod_interface.h + +gie_SOURCES = gie.c proj_strtod.c optargpm.h multistresstest_SOURCES = multistresstest.c test228_SOURCES = test228.c geodtest_SOURCES = geodtest.c -proj_LDADD = libproj.la -cs2cs_LDADD = libproj.la cct_LDADD = libproj.la -nad2bin_LDADD = libproj.la +cs2cs_LDADD = libproj.la geod_LDADD = libproj.la +proj_LDADD = libproj.la +nad2bin_LDADD = libproj.la + +gie_LDADD = libproj.la multistresstest_LDADD = libproj.la @THREAD_LIB@ test228_LDADD = libproj.la @THREAD_LIB@ geodtest_LDADD = libproj.la @@ -69,7 +73,7 @@ libproj_la_SOURCES = \ pj_factors.c pj_fwd.c pj_init.c pj_inv.c pj_fwd3d.c pj_inv3d.c\ pj_list.c pj_malloc.c pj_mlfn.c pj_msfn.c proj_mdist.c \ pj_open_lib.c pj_param.c pj_phi2.c pj_pr_list.c \ - pj_qsfn.c pj_generic_selftest.c pj_run_selftests.c pj_strerrno.c \ + pj_qsfn.c pj_strerrno.c \ pj_tsfn.c pj_units.c pj_ctx.c pj_log.c pj_zpoly1.c rtodms.c \ vector1.c pj_release.c pj_gauss.c \ PJ_healpix.c PJ_natearth.c PJ_natearth2.c PJ_calcofi.c pj_fileapi.c \ @@ -81,9 +85,9 @@ libproj_la_SOURCES = \ jniproj.c pj_mutex.c pj_initcache.c pj_apply_vgridshift.c geodesic.c \ pj_strtod.c \ \ - pj_obs_api.c PJ_cart.c PJ_pipeline.c PJ_horner.c PJ_helmert.c \ + proj_4D_api.c PJ_cart.c PJ_pipeline.c PJ_horner.c PJ_helmert.c \ PJ_vgridshift.c PJ_hgridshift.c PJ_unitconvert.c PJ_molodensky.c \ - pj_internal.c + PJ_deformation.c pj_internal.c PJ_axisswap.c install-exec-local: rm -f $(DESTDIR)$(bindir)/invproj$(EXEEXT) diff --git a/src/PJ_aea.c b/src/PJ_aea.c index 228d3afd..74628f9a 100644 --- a/src/PJ_aea.c +++ b/src/PJ_aea.c @@ -211,126 +211,10 @@ PJ *PROJECTION(leac) { if (0==Q) return pj_default_destructor (P, ENOMEM); P->opaque = Q; + P->destructor = destructor; Q->phi2 = pj_param(P->ctx, P->params, "rlat_1").f; Q->phi1 = pj_param(P->ctx, P->params, "bsouth").i ? - M_HALFPI: M_HALFPI; return setup(P); } - -#ifndef PJ_SELFTEST -int pj_aea_selftest (void) {return 10000;} -#else - -int pj_aea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2"}; - char s_args[] = {"+proj=aea +R=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222571.60875710563, 110653.32674302977}, - {222706.30650839131, -110484.26714439997}, - {-222571.60875710563, 110653.32674302977}, - {-222706.30650839131, -110484.26714439997}, - }; - - XY s_fwd_expect[] = { - {223334.08517088494, 111780.43188447191}, - {223470.15499168713, -111610.33943099028}, - {-223334.08517088494, 111780.43188447191}, - {-223470.15499168713, -111610.33943099028}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966310597749514, 0.00090436885862202158}, - {0.0017966300767030448, -0.00090437009538581453}, - {-0.0017966310597749514, 0.00090436885862202158}, - {-0.0017966300767030448, -0.00090437009538581453}, - }; - - LP s_inv_expect[] = { - {0.0017904935979658752, 0.00089524594491375306}, - {0.0017904926216016812, -0.00089524716502493225}, - {-0.0017904935979658752, 0.00089524594491375306}, - {-0.0017904926216016812, -0.00089524716502493225}, - }; - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - -#ifndef PJ_SELFTEST -int pj_leac_selftest (void) {return 10000;} -#else - -int pj_leac_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2"}; - char s_args[] = {"+proj=leac +R=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {220685.14054297868, 112983.50088939646}, - {224553.31227982609, -108128.63674487274}, - {-220685.14054297868, 112983.50088939646}, - {-224553.31227982609, -108128.63674487274}, - }; - - XY s_fwd_expect[] = { - {221432.86859285168, 114119.45452653214}, - {225331.72412711097, -109245.82943505641}, - {-221432.86859285168, 114119.45452653214}, - {-225331.72412711097, -109245.82943505641}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966446840328458, 0.00090435171340223211}, - {0.0017966164523713021, -0.00090438724081843625}, - {-0.0017966446840328458, 0.00090435171340223211}, - {-0.0017966164523713021, -0.00090438724081843625}, - }; - - LP s_inv_expect[] = { - {0.0017905070979748127, 0.00089522906964877795}, - {0.001790479121519977, -0.00089526404022281043}, - {-0.0017905070979748127, 0.00089522906964877795}, - {-0.001790479121519977, -0.00089526404022281043}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif diff --git a/src/PJ_aeqd.c b/src/PJ_aeqd.c index c6fa9e06..b627b438 100644 --- a/src/PJ_aeqd.c +++ b/src/PJ_aeqd.c @@ -31,6 +31,13 @@ #include <errno.h> #include "projects.h" +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; + struct pj_opaque { double sinph0; double cosph0; @@ -40,7 +47,7 @@ struct pj_opaque { double Mp; double He; double G; - int mode; + enum Mode mode; struct geod_geodesic g; }; @@ -49,11 +56,6 @@ PROJ_HEAD(aeqd, "Azimuthal Equidistant") "\n\tAzi, Sph&Ell\n\tlat_0 guam"; #define EPS10 1.e-10 #define TOL 1.e-14 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 - static void *destructor (PJ *P, int errlev) { /* Destructor */ if (0==P) @@ -318,61 +320,3 @@ PJ *PROJECTION(aeqd) { } -#ifndef PJ_SELFTEST -int pj_aeqd_selftest (void) {return 0;} -#else - -int pj_aeqd_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=aeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=aeqd +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222616.522190051648, 110596.996549550197}, - { 222616.522190051648, -110596.996549550211}, - {-222616.522190051648, 110596.996549550197}, - {-222616.522190051648, -110596.996549550211}, - }; - - XY s_fwd_expect[] = { - { 223379.456047271, 111723.757570854126}, - { 223379.456047271, -111723.757570854126}, - {-223379.456047271, 111723.757570854126}, - {-223379.456047271, -111723.757570854126}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056838724787, 0.000904369476930248902}, - { 0.00179663056838724787, -0.000904369476930248469}, - {-0.00179663056838724787, 0.000904369476930248902}, - {-0.00179663056838724787, -0.000904369476930248469}, - }; - - LP s_inv_expect[] = { - { 0.00179049310992953335, 0.000895246554746200623}, - { 0.00179049310992953335, -0.000895246554746200623}, - {-0.00179049310992953335, 0.000895246554746200623}, - {-0.00179049310992953335, -0.000895246554746200623}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_airy.c b/src/PJ_airy.c index d832b9b7..c256a07f 100644 --- a/src/PJ_airy.c +++ b/src/PJ_airy.c @@ -34,22 +34,24 @@ PROJ_HEAD(airy, "Airy") "\n\tMisc Sph, no inv.\n\tno_cut lat_b="; +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; + struct pj_opaque { double p_halfpi; double sinph0; double cosph0; double Cb; - int mode; + enum Mode mode; int no_cut; /* do not cut at hemisphere limit */ }; # define EPS 1.e-10 -# define N_POLE 0 -# define S_POLE 1 -# define EQUIT 2 -# define OBLIQ 3 - static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ @@ -147,31 +149,3 @@ PJ *PROJECTION(airy) { } -#ifndef PJ_SELFTEST -int pj_airy_selftest (void) {return 0;} -#else - -int pj_airy_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=airy +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 189109.88690862127, 94583.752387504152}, - { 189109.88690862127, -94583.752387504152}, - {-189109.88690862127, 94583.752387504152}, - {-189109.88690862127, -94583.752387504152}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - -#endif diff --git a/src/PJ_aitoff.c b/src/PJ_aitoff.c index 3455fa71..8927d39c 100644 --- a/src/PJ_aitoff.c +++ b/src/PJ_aitoff.c @@ -34,9 +34,14 @@ #include "projects.h" +enum Mode { + AITOFF = 0, + WINKEL_TRIPEL = 1 +}; + struct pj_opaque { double cosphi1; - int mode; + enum Mode mode; }; @@ -60,7 +65,7 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ xy.y *= d * sin(lp.phi); } else xy.x = xy.y = 0.; - if (Q->mode) { /* Winkel Tripel */ + if (Q->mode == WINKEL_TRIPEL) { xy.x = (xy.x + lp.lam * Q->cosphi1) * 0.5; xy.y = (xy.y + lp.phi) * 0.5; } @@ -112,7 +117,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ f1l = cp * cp * sl * sl / C + D * cp * cl * sp * sp; f2p = sp * sp * cl / C + D * sl * sl * cp; f2l = 0.5 * (sp * cp * sl / C - D * sp * cp * cp * sl * cl); - if (Q->mode) { /* Winkel Tripel */ + if (Q->mode == WINKEL_TRIPEL) { f1 = 0.5 * (f1 + lp.lam * Q->cosphi1); f2 = 0.5 * (f2 + lp.phi); f1p *= 0.5; @@ -128,7 +133,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */ } while ((fabs(dp) > EPSILON || fabs(dl) > EPSILON) && (iter++ < MAXITER)); if (lp.phi > M_PI_2) lp.phi -= 2.*(lp.phi-M_PI_2); /* correct if symmetrical solution for Aitoff */ if (lp.phi < -M_PI_2) lp.phi -= 2.*(lp.phi+M_PI_2); /* correct if symmetrical solution for Aitoff */ - if ((fabs(fabs(lp.phi) - M_PI_2) < EPSILON) && (!Q->mode)) lp.lam = 0.; /* if pole in Aitoff, return longitude of 0 */ + if ((fabs(fabs(lp.phi) - M_PI_2) < EPSILON) && (Q->mode == AITOFF)) lp.lam = 0.; /* if pole in Aitoff, return longitude of 0 */ /* calculate x,y coordinates with solution obtained */ if((D = acos(cos(lp.phi) * cos(C = 0.5 * lp.lam))) != 0.0) {/* Aitoff */ @@ -167,7 +172,7 @@ PJ *PROJECTION(aitoff) { return pj_default_destructor(P, ENOMEM); P->opaque = Q; - Q->mode = 0; + Q->mode = AITOFF; return setup(P); } @@ -178,7 +183,7 @@ PJ *PROJECTION(wintri) { return pj_default_destructor(P, ENOMEM); P->opaque = Q; - Q->mode = 1; + Q->mode = WINKEL_TRIPEL; if (pj_param(P->ctx, P->params, "tlat_1").i) { if ((Q->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.) return pj_default_destructor (P, PJD_ERR_LAT_LARGER_THAN_90); @@ -189,94 +194,3 @@ PJ *PROJECTION(wintri) { } -#ifndef PJ_SELFTEST -int pj_aitoff_selftest (void) {return 0;} -#else - -int pj_aitoff_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=aitoff +R=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - - XY s_fwd_expect[] = { - {223379.45881169615, 111706.74288385305}, - {223379.45881169615, -111706.74288385305}, - {-223379.45881169615, 111706.74288385305}, - {-223379.45881169615, -111706.74288385305}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - - LP s_inv_expect[] = { - {0.0017904931100388164, 0.00089524655491012516}, - {0.0017904931100388164, -0.00089524655491012516}, - {-0.0017904931100388164, 0.00089524655491012516}, - {-0.0017904931100388164, -0.00089524655491012516}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - - -#ifndef PJ_SELFTEST -int pj_wintri_selftest (void) {return 0;} -#else - -int pj_wintri_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wintri +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223390.80153348515, 111703.90750574505}, - {223390.80153348515, -111703.90750574505}, - {-223390.80153348515, 111703.90750574505}, - {-223390.80153348515, -111703.90750574505}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.0017904931099113196, 0.00089524655490101819}, - {0.0017904931099113196, -0.00089524655490101819}, - {-0.0017904931099113196, 0.00089524655490101819}, - {-0.0017904931099113196, -0.00089524655490101819}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_august.c b/src/PJ_august.c index d81644bf..ba9ea5cd 100644 --- a/src/PJ_august.c +++ b/src/PJ_august.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" PROJ_HEAD(august, "August Epicycloidal") "\n\tMisc Sph, no inv."; @@ -31,32 +31,3 @@ PJ *PROJECTION(august) { return P; } -#ifndef PJ_SELFTEST -int pj_august_selftest (void) {return 0;} -#else - -int pj_august_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=august +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223404.97818097242, 111722.34028976287}, - {223404.97818097242, -111722.34028976287}, - {-223404.97818097242, 111722.34028976287}, - {-223404.97818097242, -111722.34028976287}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_axisswap.c b/src/PJ_axisswap.c new file mode 100644 index 00000000..53c93cc9 --- /dev/null +++ b/src/PJ_axisswap.c @@ -0,0 +1,237 @@ +/*********************************************************************** + + Axis order operation for use with transformation pipelines. + + Kristian Evers, kreve@sdfe.dk, 2017-10-31 + +************************************************************************ + +Change the order and sign of 2,3 or 4 axes. Each of the possible four +axes are numbered with 1-4, such that the first input axis is 1, the +second is 2 and so on. The output ordering is controlled by a list of the +input axes re-ordered to the new mapping. Examples: + +Reversing the order of the axes: + + +proj=axisswap +order=4,3,2,1 + +Swapping the first two axes (x and y): + + +proj=axisswap +order=2,1,3,4 + +The direction, or sign, of an axis can be changed by adding a minus in +front of the axis-number: + + +proj=axisswap +order=1,-2,3,4 + +It is only necessary to specify the axes that are affected by the swap +operation: + + +proj=axisswap +order=2,1 + +************************************************************************ +* Copyright (c) 2017, Kristian Evers / SDFE +* +* 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. +* +***********************************************************************/ + +#define PJ_LIB__ +#include <errno.h> +#include "proj_internal.h" +#include "projects.h" + +PROJ_HEAD(axisswap, "Axis ordering"); + +struct pj_opaque { + unsigned int axis[4]; + int sign[4]; +}; + +static int sign(int x) { + return (x > 0) - (x < 0); +} + +static XY forward_2d(LP lp, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD out, in; + + in.lp = lp; + out = proj_coord_error(); + + for (i=0; i<2; i++) + out.v[i] = in.v[Q->axis[i]] * Q->sign[i]; + + return out.xy; +} + + +static LP reverse_2d(XY xy, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD out, in; + + in.xy = xy; + out = proj_coord_error(); + + for (i=0; i<2; i++) + out.v[Q->axis[i]] = in.v[i] * Q->sign[i]; + + return out.lp; +} + + +static XYZ forward_3d(LPZ lpz, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD out, in; + + in.lpz = lpz; + out = proj_coord_error(); + + for (i=0; i<3; i++) + out.v[i] = in.v[Q->axis[i]] * Q->sign[i]; + + return out.xyz; +} + +static LPZ reverse_3d(XYZ xyz, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD in, out; + + out = proj_coord_error(); + in.xyz = xyz; + + for (i=0; i<3; i++) + out.v[Q->axis[i]] = in.v[i] * Q->sign[i]; + + return out.lpz; +} + + +static PJ_COORD forward_4d(PJ_COORD coo, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD out; + + out = proj_coord_error(); + + for (i=0; i<4; i++) + out.v[i] = coo.v[Q->axis[i]] * Q->sign[i]; + + return out; +} + + +static PJ_COORD reverse_4d(PJ_COORD coo, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + unsigned int i; + PJ_COORD out; + + out = proj_coord_error(); + + for (i=0; i<4; i++) + out.v[Q->axis[i]] = coo.v[i] * Q->sign[i]; + + return out; +} + + +/***********************************************************************/ +PJ *CONVERSION(axisswap,0) { +/***********************************************************************/ + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + char *order, *s; + unsigned int i, j, n; + + if (0==Q) + return pj_default_destructor (P, ENOMEM); + P->opaque = (void *) Q; + + /* read axis order */ + if (pj_param (P->ctx, P->params, "torder").i) { + order = pj_param(P->ctx, P->params, "sorder").s; + } else { + return pj_default_destructor(P, PJD_ERR_MISSING_ARGS); + } + + /* fill axis list with indices from 4-7 to simplify duplicate search further down */ + for (i=0; i<4; i++) + Q->axis[i] = i+4; + + /* check that all characters are valid */ + for (i=0; i<strlen(order); i++) + if (strchr("1234-,", order[i]) == 0) { + proj_log_error(P, "axisswap: unknown axis '%c'", order[i]); + return pj_default_destructor(P, PJD_ERR_AXIS); + } + + /* read axes numbers and signs */ + for ( s = order, n = 0; *s != '\0' && n < 4; ) { + Q->axis[n] = abs(atoi(s))-1; + Q->sign[n++] = sign(atoi(s)); + while ( *s != '\0' && *s != ',' ) + s++; + if ( *s == ',' ) + s++; + } + + /* check for duplicate axes */ + for (i=0; i<4; i++) + for (j=0; j<4; j++) { + if (i==j) + continue; + if (Q->axis[i] == Q->axis[j]) { + proj_log_error(P, "swapaxis: duplicate axes specified"); + return pj_default_destructor(P, PJD_ERR_AXIS); + } + } + + /* only map fwd/inv functions that are possible with the given axis setup */ + if (n == 4) { + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; + } + if (n == 3 && Q->axis[0] < 3 && Q->axis[1] < 3 && Q->axis[2] < 3) { + P->fwd3d = forward_3d; + P->inv3d = reverse_3d; + } + if (n == 2 && Q->axis[0] < 2 && Q->axis[1] < 2) { + P->fwd = forward_2d; + P->inv = reverse_2d; + } + + if (P->fwd4d == NULL && P->fwd3d == NULL && P->fwd == NULL) { + proj_log_error(P, "swapaxis: bad axis order"); + return pj_default_destructor(P, PJD_ERR_AXIS); + } + + if (pj_param(P->ctx, P->params, "tangularunits").i) { + P->left = PJ_IO_UNITS_RADIANS; + P->right = PJ_IO_UNITS_RADIANS; + } else { + P->left = PJ_IO_UNITS_METERS; + P->right = PJ_IO_UNITS_METERS; + } + + return P; +} + diff --git a/src/PJ_bacon.c b/src/PJ_bacon.c index cb7286be..802ddcb8 100644 --- a/src/PJ_bacon.c +++ b/src/PJ_bacon.c @@ -77,89 +77,3 @@ PJ *PROJECTION(ortel) { } -#ifndef PJ_SELFTEST -int pj_bacon_selftest (void) {return 0;} -#else -int pj_bacon_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=bacon +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223334.13255596498, 175450.72592266591}, - {223334.13255596498, -175450.72592266591}, - {-223334.13255596498, 175450.72592266591}, - {-223334.13255596498, -175450.72592266591}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif - - - - -#ifndef PJ_SELFTEST -int pj_apian_selftest (void) {return 0;} -#else -int pj_apian_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=apian +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223374.57735525275, 111701.07212763709}, - { 223374.57735525275, -111701.07212763709}, - {-223374.57735525275, 111701.07212763709}, - {-223374.57735525275, -111701.07212763709}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif - - - - -#ifndef PJ_SELFTEST -int pj_ortel_selftest (void) {return 0;} -#else -int pj_ortel_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=ortel +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223374.57735525275, 111701.07212763709}, - { 223374.57735525275, -111701.07212763709}, - {-223374.57735525275, 111701.07212763709}, - {-223374.57735525275, -111701.07212763709}, - }; - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif - diff --git a/src/PJ_bipc.c b/src/PJ_bipc.c index 0019d614..4247fc17 100644 --- a/src/PJ_bipc.c +++ b/src/PJ_bipc.c @@ -171,61 +171,3 @@ PJ *PROJECTION(bipc) { } -#ifndef PJ_SELFTEST -int pj_bipc_selftest (void) {return 0;} -#else - -int pj_bipc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=bipc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=bipc +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {2452160.2177257561, -14548450.759654747}, - {2447915.213725341, -14763427.21279873}, - {2021695.5229349085, -14540413.695283702}, - {2018090.5030046992, -14755620.651414108}, - }; - - XY s_fwd_expect[] = { - {2460565.7409749646, -14598319.9893308}, - {2456306.1859352002, -14814033.339502094}, - {2028625.4978190989, -14590255.375482792}, - {2025008.1205891429, -14806200.018759441}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-73.038700284978702, 17.248118466239116}, - {-73.03730373933017, 17.249414978178777}, - {-73.03589317304332, 17.245536403008771}, - {-73.034496627213585, 17.246832895573739}, - }; - - LP s_inv_expect[] = { - {-73.038693104942126, 17.248116270440242}, - {-73.037301330021322, 17.24940835333777}, - {-73.035895582251086, 17.245543027866539}, - {-73.034503807150301, 17.246835091521532}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_boggs.c b/src/PJ_boggs.c index e6efd7d3..fe17eaa6 100644 --- a/src/PJ_boggs.c +++ b/src/PJ_boggs.c @@ -41,29 +41,4 @@ PJ *PROJECTION(boggs) { return P; } -#ifndef PJ_SELFTEST -int pj_boggs_selftest (void) {return 0;} -#else -int pj_boggs_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - char s_args[] = {"+proj=boggs +a=6400000 +lat_1=0 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 211949.70080818201, 117720.99830541089}, - { 211949.70080818201, -117720.99830541089}, - {-211949.70080818201, 117720.99830541089}, - {-211949.70080818201, -117720.99830541089}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 0, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif diff --git a/src/PJ_bonne.c b/src/PJ_bonne.c index 368829c5..4611c5d4 100644 --- a/src/PJ_bonne.c +++ b/src/PJ_bonne.c @@ -111,6 +111,8 @@ PJ *PROJECTION(bonne) { if (P->es != 0.0) { Q->en = pj_enfn(P->es); + if (0==Q->en) + return destructor(P, ENOMEM); Q->m1 = pj_mlfn(Q->phi1, Q->am1 = sin(Q->phi1), c = cos(Q->phi1), Q->en); Q->am1 = c / (sqrt(1. - P->es * Q->am1 * Q->am1) * Q->am1); @@ -128,60 +130,3 @@ PJ *PROJECTION(bonne) { } -#ifndef PJ_SELFTEST -int pj_bonne_selftest (void) {return 0;} -#else -int pj_bonne_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=bonne +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=bonne +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222605.29609715697, 55321.139565494814}, - { 222605.29609923941, -165827.64779905154}, - {-222605.29609715697, 55321.139565494814}, - {-222605.29609923941, -165827.64779905154}, - }; - - XY s_fwd_expect[] = { - { 223368.11557252839, 55884.555246393575}, - { 223368.11557463196, -167517.59936969393}, - {-223368.11557252839, 55884.555246393575}, - {-223368.11557463196, -167517.59936969393}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966987691132891, 0.50090436853737497}, - { 0.0017966982774478867, 0.4990956309655612}, - {-0.0017966987691132891, 0.50090436853737497}, - {-0.0017966982774478867, 0.4990956309655612}, - }; - - LP s_inv_expect[] = { - { 0.0017905615332457991, 0.50089524631087834}, - { 0.0017905610449335603, 0.49910475320072978}, - {-0.0017905615332457991, 0.50089524631087834}, - {-0.0017905610449335603, 0.49910475320072978}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_calcofi.c b/src/PJ_calcofi.c index b188f7e9..5c0b64ab 100644 --- a/src/PJ_calcofi.c +++ b/src/PJ_calcofi.c @@ -163,61 +163,3 @@ PJ *PROJECTION(calcofi) { } -#ifndef PJ_SELFTEST -int pj_calcofi_selftest (void) {return 0;} -#else - -int pj_calcofi_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=calcofi +ellps=GRS80 +lat_1=0.5 +lat_2=2 +no_defs"}; - char s_args[] = {"+proj=calcofi +R=6400000 +lat_1=0.5 +lat_2=2 +no_defs"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {508.44487214981905, -1171.7648604175156}, - {514.99916815188112, -1145.8219814677668}, - {500.68538412539851, -1131.4453779204598}, - {507.36971913666355, -1106.1782014834275}, - }; - - XY s_fwd_expect[] = { - {507.09050748781806, -1164.7273751978314}, - {513.68613637462886, -1138.9992682173072}, - {499.33626147591531, -1124.4351309968195}, - {506.0605703929898, -1099.3756650673038}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-110.36330792469906, 12.032056975840137}, - {-98.455008863288782, 18.698723642506803}, - {-207.4470245036909, 81.314089278595247}, - {-62.486322854481287, 87.980755945261919}, - }; - - LP s_inv_expect[] = { - {-110.30519040955151, 12.032056975840137}, - {-98.322360950234085, 18.698723642506803}, - {-207.54490681381429, 81.314089278595247}, - {-62.576950371885275, 87.980755945261919}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_cart.c b/src/PJ_cart.c index 914fa94b..2bcf3b4b 100644 --- a/src/PJ_cart.c +++ b/src/PJ_cart.c @@ -42,7 +42,7 @@ #define PJ_LIB__ #include "proj_internal.h" -#include <projects.h> +#include "projects.h" #include <assert.h> #include <stddef.h> #include <math.h> @@ -120,8 +120,13 @@ static double normal_radius_of_curvature (double a, double es, double phi) { /*********************************************************************/ static double geocentric_radius (double a, double b, double phi) { -/*********************************************************************/ - /* This is from WP2, but uses hypot() for potentially better numerical robustness */ +/********************************************************************* + Return the geocentric radius at latitude phi, of an ellipsoid + with semimajor axis a and semiminor axis b. + + This is from WP2, but uses hypot() for potentially better + numerical robustness +***********************************************************************/ return hypot (a*a*cos (phi), b*b*sin(phi)) / hypot (a*cos(phi), b*sin(phi)); } @@ -129,18 +134,15 @@ static double geocentric_radius (double a, double b, double phi) { /*********************************************************************/ static XYZ cartesian (LPZ geodetic, PJ *P) { /*********************************************************************/ - double N, h, lam, phi, cosphi = cos(geodetic.phi); + double N, cosphi = cos(geodetic.phi); XYZ xyz; N = normal_radius_of_curvature(P->a, P->es, geodetic.phi); - phi = geodetic.phi; - lam = geodetic.lam; - h = geodetic.z; /* HM formula 5-27 (z formula follows WP) */ - xyz.x = (N + h) * cosphi * cos(lam); - xyz.y = (N + h) * cosphi * sin(lam); - xyz.z = (N * (1 - P->es) + h) * sin(phi); + xyz.x = (N + geodetic.z) * cosphi * cos(geodetic.lam); + xyz.y = (N + geodetic.z) * cosphi * sin(geodetic.lam); + xyz.z = (N * (1 - P->es) + geodetic.z) * sin(geodetic.phi); return xyz; } @@ -149,23 +151,19 @@ static XYZ cartesian (LPZ geodetic, PJ *P) { /*********************************************************************/ static LPZ geodetic (XYZ cartesian, PJ *P) { /*********************************************************************/ - double N, b, p, theta, c, s, e2s; + double N, p, theta, c, s; LPZ lpz; /* Perpendicular distance from point to Z-axis (HM eq. 5-28) */ p = hypot (cartesian.x, cartesian.y); - /* Ancillary ellipsoidal parameters */ - b = P->b; - e2s = P->e2s; - /* HM eq. (5-37) */ - theta = atan2 (cartesian.z * P->a, p * b); + theta = atan2 (cartesian.z * P->a, p * P->b); /* HM eq. (5-36) (from BB, 1976) */ c = cos(theta); s = sin(theta); - lpz.phi = atan2 (cartesian.z + e2s*b*s*s*s, p - P->es*P->a*c*c*c); + lpz.phi = atan2 (cartesian.z + P->e2s*P->b*s*s*s, p - P->es*P->a*c*c*c); lpz.lam = atan2 (cartesian.y, cartesian.x); N = normal_radius_of_curvature (P->a, P->es, lpz.phi); @@ -176,7 +174,7 @@ static LPZ geodetic (XYZ cartesian, PJ *P) { /* by computing the height as the cartesian z value */ /* minus the geocentric radius of the Earth at the given */ /* latitude */ - double r = geocentric_radius (P->a, b, lpz.phi); + double r = geocentric_radius (P->a, P->b, lpz.phi); lpz.z = fabs (cartesian.z) - r; } else @@ -210,7 +208,7 @@ static LP cart_reverse (XY xy, PJ *P) { /*********************************************************************/ -PJ *PROJECTION(cart) { +PJ *CONVERSION(cart,1) { /*********************************************************************/ P->fwd3d = cartesian; P->inv3d = geodetic; @@ -221,371 +219,3 @@ PJ *PROJECTION(cart) { return P; } -#ifndef PJ_SELFTEST -/* selftest stub */ -int pj_cart_selftest (void) {return 0;} -#else -/* Testing quite a bit of the pj_obs_api as a side effect (inspired by pj_obs_api_test.c) */ -int pj_cart_selftest (void) { - PJ_CONTEXT *ctx; - PJ *P; - PJ_OBS a, b, obs[2]; - PJ_COORD coord[2]; - - PJ_INFO info; - PJ_PROJ_INFO pj_info; - PJ_GRID_INFO grid_info; - PJ_INIT_INFO init_info; - - PJ_DERIVS derivs; - PJ_FACTORS factors; - - const PJ_OPERATIONS *oper_list; - const PJ_ELLPS *ellps_list; - const PJ_UNITS *unit_list; - const PJ_PRIME_MERIDIANS *pm_list; - - int err; - size_t n, sz; - double dist, h, t; - char *args[3] = {"proj=utm", "zone=32", "ellps=GRS80"}; - char *arg = {"+proj=utm +zone=32 +ellps=GRS80"}; - char buf[40]; - - /* An utm projection on the GRS80 ellipsoid */ - P = proj_create (PJ_DEFAULT_CTX, arg); - if (0==P) - return 1; - - - /* Clean up */ - proj_destroy (P); - - /* Same projection, now using argc/argv style initialization */ - P = proj_create_argv (PJ_DEFAULT_CTX, 3, args); - if (0==P) - return 2; - - /* zero initialize everything, then set (longitude, latitude) to (12, 55) */ - a = proj_obs_null; - /* a.coo.lp: The coordinate part of a, interpreted as a classic LP pair */ - a.coo.lp.lam = PJ_TORAD(12); - a.coo.lp.phi = PJ_TORAD(55); - - /* Forward projection */ - b = proj_trans_obs (P, PJ_FWD, a); - - /* Inverse projection */ - a = proj_trans_obs (P, PJ_INV, b); - - /* Null projection */ - a = proj_trans_obs (P, PJ_IDENT, a); - - /* Forward again, to get two linear items for comparison */ - a = proj_trans_obs (P, PJ_FWD, a); - - dist = proj_xy_dist (a.coo.xy, b.coo.xy); - if (dist > 2e-9) - return 3; - - /* Clear any previous error */ - proj_errno_set (P, 0); - - /* Invalid projection */ - a = proj_trans_obs (P, 42, a); - if (a.coo.lpz.lam!=HUGE_VAL) - return 4; - err = proj_errno (P); - if (0==err) - return 5; - - /* Clear error again */ - proj_errno_set (P, 0); - - /* Clean up */ - proj_destroy (P); - - /* Now do some 3D transformations */ - P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); - if (0==P) - return 6; - - /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 100) */ - a = b = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(12); - a.coo.lpz.phi = PJ_TORAD(55); - a.coo.lpz.z = 100; - - /* Forward projection: 3D-Cartesian-to-Ellipsoidal */ - b = proj_trans_obs (P, PJ_FWD, a); - - /* Check roundtrip precision for 10000 iterations each way */ - dist = proj_roundtrip (P, PJ_FWD, 10000, a.coo); - dist = proj_roundtrip (P, PJ_INV, 10000, b.coo); - if (dist > 2e-9) - return 7; - - - /* Test at the North Pole */ - a = b = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(0); - a.coo.lpz.phi = PJ_TORAD(90); - a.coo.lpz.z = 100; - - /* Forward projection: Ellipsoidal-to-3D-Cartesian */ - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 1e-12) - return 8; - - /* Test at the South Pole */ - a = b = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(0); - a.coo.lpz.phi = PJ_TORAD(-90); - a.coo.lpz.z = 100; - - /* Forward projection: Ellipsoidal-to-3D-Cartesian */ - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 1e-12) - return 9; - - /* Inverse projection: 3D-Cartesian-to-Ellipsoidal */ - b = proj_trans_obs (P, PJ_INV, b); - - /* Move p to another context */ - ctx = proj_context_create (); - if (ctx==pj_get_default_ctx()) - return 10; - proj_context_set (P, ctx); - if (ctx != P->ctx) - return 11; - b = proj_trans_obs (P, PJ_FWD, b); - - /* Move it back to the default context */ - proj_context_set (P, 0); - if (pj_get_default_ctx() != P->ctx) - return 12; - proj_context_destroy (ctx); - - /* We go on with the work - now back on the default context */ - b = proj_trans_obs (P, PJ_INV, b); - proj_destroy (P); - - - /* Testing the proj_transform nightmare */ - - /* An utm projection on the GRS80 ellipsoid */ - P = proj_create (PJ_DEFAULT_CTX, "+proj=utm +zone=32 +ellps=GRS80"); - if (0==P) - return 13; - - obs[0].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); - obs[1].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); - sz = sizeof (PJ_OBS); - - /* Forward projection */ - a = proj_trans_obs (P, PJ_FWD, obs[0]); - b = proj_trans_obs (P, PJ_FWD, obs[1]); - - n = proj_transform ( - P, PJ_FWD, - &(obs[0].coo.lpz.lam), sz, 2, - &(obs[0].coo.lpz.phi), sz, 2, - &(obs[0].coo.lpz.z), sz, 2, - 0, sz, 0 - ); - if (2!=n) - return 14; - if (a.coo.lpz.lam != obs[0].coo.lpz.lam) return 15; - if (a.coo.lpz.phi != obs[0].coo.lpz.phi) return 16; - if (a.coo.lpz.z != obs[0].coo.lpz.z) return 17; - if (b.coo.lpz.lam != obs[1].coo.lpz.lam) return 18; - if (b.coo.lpz.phi != obs[1].coo.lpz.phi) return 19; - if (b.coo.lpz.z != obs[1].coo.lpz.z) return 20; - - /* now test the case of constant z */ - obs[0].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); - obs[1].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); - h = 27; - t = 33; - n = proj_transform ( - P, PJ_FWD, - &(obs[0].coo.lpz.lam), sz, 2, - &(obs[0].coo.lpz.phi), sz, 2, - &h, 0, 1, - &t, 0, 1 - ); - if (2!=n) - return 21; - if (a.coo.lpz.lam != obs[0].coo.lpz.lam) return 22; - if (a.coo.lpz.phi != obs[0].coo.lpz.phi) return 23; - if (45 != obs[0].coo.lpz.z) return 24; - if (b.coo.lpz.lam != obs[1].coo.lpz.lam) return 25; - if (b.coo.lpz.phi != obs[1].coo.lpz.phi) return 26; - if (50 != obs[1].coo.lpz.z) return 27; /* NOTE: unchanged */ - if (50==h) return 28; - - /* test proj_transform_obs() */ - - obs[0].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); - obs[1].coo = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); - - if (proj_transform_obs(P, PJ_FWD, 2, obs)) - return 30; - - if (a.coo.lpz.lam != obs[0].coo.lpz.lam) return 31; - if (a.coo.lpz.phi != obs[0].coo.lpz.phi) return 32; - if (a.coo.lpz.z != obs[0].coo.lpz.z) return 33; - if (b.coo.lpz.lam != obs[1].coo.lpz.lam) return 34; - if (b.coo.lpz.phi != obs[1].coo.lpz.phi) return 35; - if (b.coo.lpz.z != obs[1].coo.lpz.z) return 36; - - /* test proj_transform_coord() */ - - coord[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); - coord[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); - if (proj_transform_coord(P, PJ_FWD, 2, coord)) - return 40; - - if (a.coo.lpz.lam != coord[0].lpz.lam) return 41; - if (a.coo.lpz.phi != coord[0].lpz.phi) return 42; - if (a.coo.lpz.z != coord[0].lpz.z) return 43; - if (b.coo.lpz.lam != coord[1].lpz.lam) return 44; - if (b.coo.lpz.phi != coord[1].lpz.phi) return 45; - if (b.coo.lpz.z != coord[1].lpz.z) return 46; - - /* Clean up after transform* tests */ - proj_destroy (P); - - /* test proj_create_crs_to_crs() */ - P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "epsg:25832", "epsg:25833"); - if (P==0) - return 50; - - a.coo.xy.x = 700000.0; - a.coo.xy.y = 6000000.0; - b.coo.xy.x = 307788.8761171057; - b.coo.xy.y = 5999669.3036037628; - - a = proj_trans_obs(P, PJ_FWD, a); - if (dist > 1e-7) - return 51; - proj_destroy(P); - - /* let's make sure that only entries in init-files results in a usable PJ */ - P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "proj=utm +zone=32 +datum=WGS84", "proj=utm +zone=33 +datum=WGS84"); - if (P != 0) { - proj_destroy(P); - return 52; - } - proj_destroy(P); - - /* ********************************************************************** */ - /* Test info functions */ - /* ********************************************************************** */ - - /* proj_info() */ - /* this one is difficult to test, since the output changes with the setup */ - info = proj_info(); - if (info.version[0] != '\0' ) { - char tmpstr[64]; - sprintf(tmpstr, "%d.%d.%d", info.major, info.minor, info.patch); - if (strcmp(info.version, tmpstr)) return 55; - } - if (info.release[0] == '\0') return 56; - if (info.searchpath[0] == '\0') return 57; - - /* proj_pj_info() */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=august"); /* august has no inverse */ - if (proj_pj_info(P).has_inverse) { proj_destroy(P); return 60; } - proj_destroy(P); - - P = proj_create(PJ_DEFAULT_CTX, arg); - pj_info = proj_pj_info(P); - if ( !pj_info.has_inverse ) { proj_destroy(P); return 61; } - if ( strcmp(pj_info.definition, arg) ) { proj_destroy(P); return 62; } - if ( strcmp(pj_info.id, "utm") ) { proj_destroy(P); return 63; } - proj_destroy(P); - - /* proj_grid_info() */ - grid_info = proj_grid_info("egm96_15.gtx"); - if ( strlen(grid_info.filename) == 0 ) return 64; - if ( strcmp(grid_info.gridname, "egm96_15.gtx") ) return 65; - grid_info = proj_grid_info("nonexistinggrid"); - if ( strlen(grid_info.filename) > 0 ) return 66; - - /* proj_init_info() */ - init_info = proj_init_info("unknowninit"); - if ( strlen(init_info.filename) != 0 ) return 67; - - init_info = proj_init_info("epsg"); - /* Need to allow for "Unknown" until all commonly distributed EPSG-files comes with a metadata section */ - if ( strcmp(init_info.origin, "EPSG") && strcmp(init_info.origin, "Unknown") ) return 69; - if ( strcmp(init_info.name, "epsg") ) return 68; - - - - /* test proj_rtodms() and proj_dmstor() */ - if (strcmp("180dN", proj_rtodms(buf, M_PI, 'N', 'S'))) - return 70; - - if (proj_dmstor(&buf[0], NULL) != M_PI) - return 71; - - if (strcmp("114d35'29.612\"S", proj_rtodms(buf, -2.0, 'N', 'S'))) - return 72; - - /* we can't expect perfect numerical accuracy so testing with a tolerance */ - if (fabs(-2.0 - proj_dmstor(&buf[0], NULL)) > 1e-7) - return 73; - - - /* test proj_derivatives_retrieve() and proj_factors_retrieve() */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=merc"); - a = proj_obs_null; - a.coo.lp.lam = PJ_TORAD(12); - a.coo.lp.phi = PJ_TORAD(55); - - derivs = proj_derivatives(P, a.coo.lp); - if (proj_errno(P)) - return 80; /* derivs not created correctly */ - - if ( fabs(derivs.x_l - 1.0) > 1e-5 ) return 81; - if ( fabs(derivs.x_p - 0.0) > 1e-5 ) return 82; - if ( fabs(derivs.y_l - 0.0) > 1e-5 ) return 83; - if ( fabs(derivs.y_p - 1.73959) > 1e-5 ) return 84; - - - factors = proj_factors(P, a.coo.lp); - if (proj_errno(P)) - return 85; /* factors not created correctly */ - - /* check a few key characteristics of the Mercator projection */ - if (factors.omega != 0.0) return 86; /* angular distortion should be 0 */ - if (factors.thetap != M_PI_2) return 87; /* Meridian/parallel angle should be 90 deg */ - if (factors.conv != 0.0) return 88; /* meridian convergence should be 0 */ - - - proj_destroy(P); - - /* Check that proj_list_* functions work by looping through them */ - n = 0; - for (oper_list = proj_list_operations(); oper_list->id; ++oper_list) n++; - if (n == 0) return 90; - - n = 0; - for (ellps_list = proj_list_ellps(); ellps_list->id; ++ellps_list) n++; - if (n == 0) return 91; - - n = 0; - for (unit_list = proj_list_units(); unit_list->id; ++unit_list) n++; - if (n == 0) return 92; - - n = 0; - for (pm_list = proj_list_prime_meridians(); pm_list->id; ++pm_list) n++; - if (n == 0) return 93; - - return 0; -} - - -#endif diff --git a/src/PJ_cass.c b/src/PJ_cass.c index 6955146e..ddb3eaf3 100644 --- a/src/PJ_cass.c +++ b/src/PJ_cass.c @@ -118,59 +118,3 @@ PJ *PROJECTION(cass) { } -#ifndef PJ_SELFTEST -int pj_cass_selftest (void) {return 0;} -#else - -int pj_cass_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=cass +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=cass +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222605.28577699114, 110642.22925399939}, - { 222605.28577699114, -110642.22925399939}, - {-222605.28577699114, 110642.22925399939}, - {-222605.28577699114, -110642.22925399939}, - }; - - XY s_fwd_expect[] = { - { 223368.10520348375, 111769.14504058579}, - { 223368.10520348375, -111769.14504058579}, - {-223368.10520348375, 111769.14504058579}, - {-223368.10520348375, -111769.14504058579}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305684613522, 0.00090436947663183841}, - { 0.0017966305684613522, -0.00090436947663183841}, - {-0.0017966305684613522, 0.00090436947663183841}, - {-0.0017966305684613522, -0.00090436947663183841}, - }; - - LP s_inv_expect[] = { - { 0.0017904931100023887, 0.00089524655445477922}, - { 0.0017904931100023887, -0.00089524655445477922}, - {-0.0017904931100023887, 0.00089524655445477922}, - {-0.0017904931100023887, -0.00089524655445477922}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif diff --git a/src/PJ_cc.c b/src/PJ_cc.c index 9ba51386..8a7da5b5 100644 --- a/src/PJ_cc.c +++ b/src/PJ_cc.c @@ -38,46 +38,3 @@ PJ *PROJECTION(cc) { } -#ifndef PJ_SELFTEST -int pj_cc_selftest (void) {return 0;} -#else - -int pj_cc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=cc +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223402.14425527418, 111712.41554059254}, - {223402.14425527418, -111712.41554059254}, - {-223402.14425527418, 111712.41554059254}, - {-223402.14425527418, -111712.41554059254}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.0017904931097838226, 0.00089524655481905597}, - {0.0017904931097838226, -0.00089524655481905597}, - {-0.0017904931097838226, 0.00089524655481905597}, - {-0.0017904931097838226, -0.00089524655481905597}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_cea.c b/src/PJ_cea.c index 0ec7376c..60ed3a37 100644 --- a/src/PJ_cea.c +++ b/src/PJ_cea.c @@ -98,60 +98,3 @@ PJ *PROJECTION(cea) { } -#ifndef PJ_SELFTEST -int pj_cea_selftest (void) {return 0;} -#else - -int pj_cea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=cea +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=cea +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222638.981586547132, 110568.812396267356}, - { 222638.981586547132, -110568.812396265886}, - {-222638.981586547132, 110568.812396267356}, - {-222638.981586547132, -110568.812396265886}, - }; - - XY s_fwd_expect[] = { - { 223402.144255274179, 111695.401198614476}, - { 223402.144255274179, -111695.401198614476}, - {-223402.144255274179, 111695.401198614476}, - {-223402.144255274179, -111695.401198614476}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056823904264, 0.000904369476105564289}, - { 0.00179663056823904264, -0.000904369476105564289}, - {-0.00179663056823904264, 0.000904369476105564289}, - {-0.00179663056823904264, -0.000904369476105564289}, - }; - - LP s_inv_expect[] = { - { 0.00179049310978382265, 0.000895246554928338998}, - { 0.00179049310978382265, -0.000895246554928338998}, - {-0.00179049310978382265, 0.000895246554928338998}, - {-0.00179049310978382265, -0.000895246554928338998}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - -#endif diff --git a/src/PJ_chamb.c b/src/PJ_chamb.c index 9edb699f..d0b9250e 100644 --- a/src/PJ_chamb.c +++ b/src/PJ_chamb.c @@ -136,32 +136,3 @@ PJ *PROJECTION(chamb) { } -#ifndef PJ_SELFTEST -int pj_chamb_selftest (void) {return 0;} -#else - -int pj_chamb_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=chamb +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {-27864.7795868005815, -223364.324593274243}, - {-251312.283053493476, -223402.145526208304}, - {-27864.7856491046077, 223364.327328827145}, - {-251312.289116443484, 223402.142197287147}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_collg.c b/src/PJ_collg.c index 01c65cd0..bf7d9f14 100644 --- a/src/PJ_collg.c +++ b/src/PJ_collg.c @@ -49,46 +49,3 @@ PJ *PROJECTION(collg) { return P; } -#ifndef PJ_SELFTEST -int pj_collg_selftest (void) {return 0;} -#else - -int pj_collg_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=collg +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {249872.921577929839, 99423.1747884602082}, - {254272.532301245432, -98559.3077607425657}, - {-249872.921577929839, 99423.1747884602082}, - {-254272.532301245432, -98559.3077607425657}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00158679719207879865, 0.00101017310941749921}, - {0.001586769215623956, -0.00101018201458258111}, - {-0.00158679719207879865, 0.00101017310941749921}, - {-0.001586769215623956, -0.00101018201458258111}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_comill.c b/src/PJ_comill.c index a329c0ac..a34762e8 100644 --- a/src/PJ_comill.c +++ b/src/PJ_comill.c @@ -81,46 +81,3 @@ PJ *PROJECTION(comill) { } -#ifndef PJ_SELFTEST -int pj_comill_selftest (void) {return 0;} -#else - -int pj_comill_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=comill +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223402.144255274179, 110611.859089458536}, - {223402.144255274179, -110611.859089458536}, - {-223402.144255274179, 110611.859089458536}, - {-223402.144255274179, -110611.859089458536}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00179049310978382265, 0.000904106801510605831}, - {0.00179049310978382265, -0.000904106801510605831}, - {-0.00179049310978382265, 0.000904106801510605831}, - {-0.00179049310978382265, -0.000904106801510605831}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_crast.c b/src/PJ_crast.c index b47b0e55..81182117 100644 --- a/src/PJ_crast.c +++ b/src/PJ_crast.c @@ -37,47 +37,3 @@ PJ *PROJECTION(crast) { return P; } -#ifndef PJ_SELFTEST -int pj_crast_selftest (void) {return 0;} -#else - -int pj_crast_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=crast +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - - XY s_fwd_expect[] = { - {218280.142056780722, 114306.045604279774}, - {218280.142056780722, -114306.045604279774}, - {-218280.142056780722, 114306.045604279774}, - {-218280.142056780722, -114306.045604279774}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00183225941982580187, 0.00087483943098902331}, - {0.00183225941982580187, -0.00087483943098902331}, - {-0.00183225941982580187, 0.00087483943098902331}, - {-0.00183225941982580187, -0.00087483943098902331}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_deformation.c b/src/PJ_deformation.c new file mode 100644 index 00000000..81dd602d --- /dev/null +++ b/src/PJ_deformation.c @@ -0,0 +1,290 @@ +/*********************************************************************** + + Kinematic datum shifting utilizing a deformation model + + Kristian Evers, 2017-10-29 + +************************************************************************ + +Perform datum shifts by means of a deformation/velocity model. + + X_out = X_in + (T_ct - T_obs)*DX + Y_out = Y_in + (T_ct - T_obs)*DY + Z_out = Z_in + (T_ct - T_obs)*DZ + + +Corrections are done in cartesian space. Coordinates of the +gridded model are in lat/long space and the corrections in the model are +in cartesian space. Hence the input coordinates needs to be converted +to lat/long space when searching for corrections in the grid. The +corrections are then applied to the input coordinates in cartesian +space. + +A full deformation model is described by two grids, one for the horizontal +components and one for the vertical component. The horizontal grid is +stored in CTable/CTable2 and the vertical grid is stored in the GTX +format. Both grids are expected to contain grid-values in units of +m/year. + +************************************************************************ +* Copyright (c) 2017, Kristian Evers +* +* 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. +* +***********************************************************************/ +#define PJ_LIB__ +#include <errno.h> +#include <proj.h> +#include "proj_internal.h" +#include "projects.h" + +PROJ_HEAD(deformation, "Kinematic grid shift"); + +#define TOL 1e-8 +#define MAX_ITERATIONS 10 + +struct pj_opaque { + double t_obs; + double t_epoch; + int has_xy_grids, has_z_grids; + PJ *cart; +}; + +static XYZ get_xygrid_shift(PJ* P, XYZ cartesian) { + PJ_COORD geodetic, shift; + + geodetic.lpz = pj_inv3d(cartesian, P->opaque->cart); + shift.lp = proj_hgrid_value(P, geodetic.lp); + + return shift.xyz; +} + +static double get_zgrid_shift(PJ* P, XYZ cartesian) { + PJ_COORD geodetic; + + geodetic.lpz = pj_inv3d(cartesian, P->opaque->cart); + + return proj_vgrid_value(P, geodetic.lp); +} + +static XYZ reverse_hshift(PJ *P, XYZ input, double dt) { + XYZ out, delta, dif; + int i = MAX_ITERATIONS; + + delta = get_xygrid_shift(P, input); + + out.x = input.x + dt*delta.x; + out.y = input.y - dt*delta.y; + out.z = input.z; + + do { + delta = get_xygrid_shift(P, out); + + if (delta.x == HUGE_VAL) + break; + + dif.x = out.x - dt*delta.x - input.x; + dif.y = out.y + dt*delta.y - input.y; + out.x += dif.x; + out.y += dif.y; + + } while ( --i && hypot(dif.x, dif.y) > TOL ); + + return out; +} + +static XYZ forward_3d(LPZ lpz, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + PJ_COORD out, in; + XYZ shift; + double dt = 0.0; + in.lpz = lpz; + out = in; + + if (Q->t_obs != HUGE_VAL) { + dt = Q->t_obs - Q->t_epoch; + } else { + out = proj_coord_error(); /* in the 3D case +t_obs must be specified */ + proj_log_debug(P, "deformation: +t_obs must be specified"); + return out.xyz; + } + + if (Q->has_xy_grids) { + shift = get_xygrid_shift(P, in.xyz); + + out.xyz.x += dt * shift.x; + out.xyz.y += dt * shift.y; + } + + if (Q->has_z_grids) + out.xyz.z += dt * get_zgrid_shift(P, in.xyz); + + return out.xyz; +} + + +static PJ_COORD forward_4d(PJ_COORD in, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + double dt; + XYZ shift; + PJ_COORD out = in; + + if (Q->t_obs != HUGE_VAL) { + dt = Q->t_obs - Q->t_epoch; + } else { + dt = in.xyzt.t - Q->t_epoch; + } + + if (Q->has_xy_grids) { + shift = get_xygrid_shift(P, in.xyz); + out.xyz.x += dt * shift.x; + out.xyz.y += dt * shift.y; + } + + if (Q->has_z_grids) + out.xyz.z += dt * get_zgrid_shift(P, in.xyz); + + return out; +} + + +static LPZ reverse_3d(XYZ in, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + PJ_COORD out; + double dt = 0.0; + out.xyz = in; + + if (Q->t_obs != HUGE_VAL) { + dt = Q->t_epoch - Q->t_obs; + } else { + out = proj_coord_error(); /* in the 3D case +t_obs must be specified */ + proj_log_debug(P, "deformation: +t_obs must be specified"); + return out.lpz; + } + + if (Q->has_xy_grids) { + out.xyz = reverse_hshift(P, in, dt); + } + + if (Q->has_z_grids) + out.xyz.z = in.z + dt * get_zgrid_shift(P, in); + + return out.lpz; +} + +static PJ_COORD reverse_4d(PJ_COORD in, PJ *P) { + struct pj_opaque *Q = (struct pj_opaque *) P->opaque; + PJ_COORD out = in; + double dt; + + if (Q->t_obs != HUGE_VAL) { + dt = Q->t_epoch - Q->t_obs; + } else { + dt = Q->t_epoch - in.xyzt.t; + } + + if (Q->has_xy_grids) + out.xyz = reverse_hshift(P, in.xyz, dt); + + if (Q->has_z_grids) + out.xyz.z = in.xyz.z + dt * get_zgrid_shift(P, in.xyz); + + return out; +} + +static void *destructor(PJ *P, int errlev) { + if (0==P) + return 0; + + if (0==P->opaque) + return pj_default_destructor (P, errlev); + + if (P->opaque->cart) + P->opaque->cart->destructor (P->opaque->cart, errlev); + + return pj_default_destructor(P, errlev); +} + + +PJ *TRANSFORMATION(deformation,1) { + struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); + if (0==Q) + return pj_default_destructor(P, ENOMEM); + P->opaque = (void *) Q; + + Q->cart = proj_create(P->ctx, "+proj=cart"); + if (Q->cart == 0) + return destructor(P, ENOMEM); + + /* inherit ellipsoid definition from P to Q->cart (simpler than guessing */ + /* how the ellipsoid was specified in original definition) */ + pj_inherit_ellipsoid_defs(P, Q->cart); + + Q->has_xy_grids = pj_param(P->ctx, P->params, "txy_grids").i; + Q->has_z_grids = pj_param(P->ctx, P->params, "tz_grids").i; + + /* Build gridlists. P->gridlist and P->vgridlist_geoid can be empty if */ + /* +xy_grids or +z_grids only ask for optional grids */ + if (!Q->has_xy_grids && !Q->has_z_grids) { + proj_log_error(P, "deformation: At least one of either +xy_grids or +z_grids should be specified."); + return destructor(P, PJD_ERR_NO_ARGS ); + } + + if (Q->has_xy_grids) { + Q->has_xy_grids = proj_hgrid_init(P, "xy_grids"); + if (proj_errno(P)) { + proj_log_error(P, "deformation: could not find requested grid(s)."); + return destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID); + } + } + + if (Q->has_z_grids) { + Q->has_z_grids = proj_vgrid_init(P, "z_grids"); + if (proj_errno(P)) { + proj_log_error(P, "deformation: could not find requested grid(s)."); + return destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID); + } + } + + Q->t_obs = HUGE_VAL; + if (pj_param(P->ctx, P->params, "tt_obs").i) { + Q->t_obs = pj_param(P->ctx, P->params, "dt_obs").f; + } + + if (pj_param(P->ctx, P->params, "tt_epoch").i) { + Q->t_epoch = pj_param(P->ctx, P->params, "dt_epoch").f; + } else { + proj_log_error(P, "deformation: +t_epoch parameter missing."); + return destructor(P, PJD_ERR_MISSING_ARGS); + } + + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; + P->fwd3d = forward_3d; + P->inv3d = reverse_3d; + P->fwd = 0; + P->inv = 0; + + P->left = PJ_IO_UNITS_METERS; + P->right = PJ_IO_UNITS_METERS; + P->destructor = destructor; + + return P; +} + diff --git a/src/PJ_denoy.c b/src/PJ_denoy.c index 3964c7da..d89a7e3e 100644 --- a/src/PJ_denoy.c +++ b/src/PJ_denoy.c @@ -29,31 +29,3 @@ PJ *PROJECTION(denoy) { return P; } -#ifndef PJ_SELFTEST -int pj_denoy_selftest (void) {return 0;} -#else - -int pj_denoy_selftest (void) { - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=denoy +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223377.422876954137, 111701.07212763709}, - { 223377.422876954137, -111701.07212763709}, - {-223377.422876954137, 111701.07212763709}, - {-223377.422876954137, -111701.07212763709}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, 0, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_eck1.c b/src/PJ_eck1.c index bd5c1916..4a9ac06b 100644 --- a/src/PJ_eck1.c +++ b/src/PJ_eck1.c @@ -39,45 +39,3 @@ PJ *PROJECTION(eck1) { } -#ifndef PJ_SELFTEST -int pj_eck1_selftest (void) {return 0;} -#else - -int pj_eck1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck1 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - XY s_fwd_expect[] = { - { 204680.88820295094, 102912.17842606473}, - { 204680.88820295094, -102912.17842606473}, - {-204680.88820295094, 102912.17842606473}, - {-204680.88820295094, -102912.17842606473}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0019434150820034624, 0.00097170229538813102}, - { 0.0019434150820034624, -0.00097170229538813102}, - {-0.0019434150820034624, 0.00097170229538813102}, - {-0.0019434150820034624, -0.00097170229538813102}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eck2.c b/src/PJ_eck2.c index 3b2e4e49..b953b54f 100644 --- a/src/PJ_eck2.c +++ b/src/PJ_eck2.c @@ -53,46 +53,3 @@ PJ *PROJECTION(eck2) { } -#ifndef PJ_SELFTEST -int pj_eck2_selftest (void) {return 0;} -#else - -int pj_eck2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 204472.87090796008, 121633.73497524235}, - { 204472.87090796008, -121633.73497524235}, - {-204472.87090796008, 121633.73497524235}, - {-204472.87090796008, -121633.73497524235}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0019434150820034624, 0.00082480429919795412}, - { 0.0019434150820034624, -0.00082480429919795412}, - {-0.0019434150820034624, 0.00082480429919795412}, - {-0.0019434150820034624, -0.00082480429919795412}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eck3.c b/src/PJ_eck3.c index 8dc72c7c..21353be2 100644 --- a/src/PJ_eck3.c +++ b/src/PJ_eck3.c @@ -106,180 +106,3 @@ PJ *PROJECTION(putp1) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_eck3_selftest (void) {return 0;} -#else - -int pj_eck3_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck3 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 188652.01572153764, 94328.919337031271}, - { 188652.01572153764, -94328.919337031271}, - {-188652.01572153764, 94328.919337031271}, - {-188652.01572153764, -94328.919337031271}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0021202405520236059, 0.0010601202759750307}, - { 0.0021202405520236059, -0.0010601202759750307}, - {-0.0021202405520236059, 0.0010601202759750307}, - {-0.0021202405520236059, -0.0010601202759750307}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_kav7_selftest (void) {return 0;} -#else - -int pj_kav7_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=kav7 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 193462.9749437288, 111701.07212763709}, - { 193462.9749437288, -111701.07212763709}, - {-193462.9749437288, 111701.07212763709}, - {-193462.9749437288, -111701.07212763709} - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0020674833579085268, 0.00089524655489191132}, - { 0.0020674833579085268, -0.00089524655489191132}, - {-0.0020674833579085268, 0.00089524655489191132}, - {-0.0020674833579085268, -0.00089524655489191132} - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_wag6_selftest (void) {return 0;} -#else - -int pj_wag6_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag6 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 211652.56216440981, 105831.18078732977}, - { 211652.56216440981, -105831.18078732977}, - {-211652.56216440981, 105831.18078732977}, - {-211652.56216440981, -105831.18078732977} - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0018898022163257513, 0.000944901108123818}, - { 0.0018898022163257513, -0.000944901108123818}, - {-0.0018898022163257513, 0.000944901108123818}, - {-0.0018898022163257513, -0.000944901108123818} - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - -#ifndef PJ_SELFTEST -int pj_putp1_selftest (void) {return 0;} -#else - -int pj_putp1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp1 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 211642.76275416015, 105831.18078732977}, - { 211642.76275416015, -105831.18078732977}, - {-211642.76275416015, 105831.18078732977}, - {-211642.76275416015, -105831.18078732977} - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0018898022164038663, 0.000944901108123818}, - { 0.0018898022164038663, -0.000944901108123818}, - {-0.0018898022164038663, 0.000944901108123818}, - {-0.0018898022164038663, -0.000944901108123818} - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eck4.c b/src/PJ_eck4.c index 0ad9ec43..c3e1b677 100644 --- a/src/PJ_eck4.c +++ b/src/PJ_eck4.c @@ -59,47 +59,3 @@ PJ *PROJECTION(eck4) { return P; } - -#ifndef PJ_SELFTEST -int pj_eck4_selftest (void) {return 0;} -#else - -int pj_eck4_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck4 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 188646.38935641639, 132268.54017406539}, - { 188646.38935641639, -132268.54017406539}, - {-188646.38935641639, 132268.54017406539}, - {-188646.38935641639, -132268.54017406539}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0021202405520236059, 0.00075601458836610643}, - { 0.0021202405520236059, -0.00075601458836610643}, - {-0.0021202405520236059, 0.00075601458836610643}, - {-0.0021202405520236059, -0.00075601458836610643}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eck5.c b/src/PJ_eck5.c index 13617c1d..34a258ee 100644 --- a/src/PJ_eck5.c +++ b/src/PJ_eck5.c @@ -36,46 +36,3 @@ PJ *PROJECTION(eck5) { return P; } -#ifndef PJ_SELFTEST -int pj_eck5_selftest (void) {return 0;} -#else - -int pj_eck5_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck5 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 197031.39213406085, 98523.198847226551}, - { 197031.39213406085, -98523.198847226551}, - {-197031.39213406085, 98523.198847226551}, - {-197031.39213406085, -98523.198847226551}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.002029978749734037, 0.001014989374787388}, - {0.002029978749734037, -0.001014989374787388}, - {-0.002029978749734037, 0.001014989374787388}, - {-0.002029978749734037, -0.001014989374787388}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eqc.c b/src/PJ_eqc.c index 4f471df1..908147a2 100644 --- a/src/PJ_eqc.c +++ b/src/PJ_eqc.c @@ -49,46 +49,3 @@ PJ *PROJECTION(eqc) { } -#ifndef PJ_SELFTEST -int pj_eqc_selftest (void) {return 0;} -#else - -int pj_eqc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eqc +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223402.144255274179, 111701.07212763709}, - { 223402.144255274179, -111701.07212763709}, - {-223402.144255274179, 111701.07212763709}, - {-223402.144255274179, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049310978382265, 0.000895246554891911323}, - { 0.00179049310978382265, -0.000895246554891911323}, - {-0.00179049310978382265, 0.000895246554891911323}, - {-0.00179049310978382265, -0.000895246554891911323}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_eqdc.c b/src/PJ_eqdc.c index 6b3449f7..6846abaa 100644 --- a/src/PJ_eqdc.c +++ b/src/PJ_eqdc.c @@ -54,19 +54,6 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ } -static void special(LP lp, PJ *P, struct FACTORS *fac) { - struct pj_opaque *Q = P->opaque; - double sinphi, cosphi; - - sinphi = sin(lp.phi); - cosphi = cos(lp.phi); - fac->code |= IS_ANAL_HK; - fac->h = 1.; - fac->k = Q->n * (Q->c - (Q->ellips ? pj_mlfn(lp.phi, sinphi, - cosphi, Q->en) : lp.phi)) / pj_msfn(sinphi, cosphi, P->es); -} - - static void *destructor (PJ *P, int errlev) { /* Destructor */ if (0==P) return 0; @@ -93,7 +80,7 @@ PJ *PROJECTION(eqdc) { Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f; if (fabs(Q->phi1 + Q->phi2) < EPS10) - pj_default_destructor (P, PJD_ERR_CONIC_LAT_EQUAL); + return pj_default_destructor (P, PJD_ERR_CONIC_LAT_EQUAL); if (!(Q->en = pj_enfn(P->es))) return pj_default_destructor(P, ENOMEM); @@ -124,67 +111,8 @@ PJ *PROJECTION(eqdc) { P->inv = e_inverse; P->fwd = e_forward; - P->spc = special; return P; } -#ifndef PJ_SELFTEST -int pj_eqdc_selftest (void) {return 0;} -#else - -int pj_eqdc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=eqdc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=eqdc +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222588.440269285755, 110659.134907347048}, - { 222756.836702042434, -110489.578087220681}, - {-222588.440269285755, 110659.134907347048}, - {-222756.836702042434, -110489.578087220681}, - }; - - XY s_fwd_expect[] = { - { 223351.088175113517, 111786.108747173785}, - { 223521.200266735133, -111615.970741240744}, - {-223351.088175113517, 111786.108747173785}, - {-223521.200266735133, -111615.970741240744}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179635944879094839, 0.000904368858588402644}, - { 0.00179635822020772734, -0.000904370095529954975}, - {-0.00179635944879094839, 0.000904368858588402644}, - {-0.00179635822020772734, -0.000904370095529954975}, - }; - - LP s_inv_expect[] = { - { 0.0017902210900486641, 0.000895245944814909169}, - { 0.00179021986984890255, -0.000895247165333684842}, - {-0.0017902210900486641, 0.000895245944814909169}, - {-0.00179021986984890255, -0.000895247165333684842}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_fahey.c b/src/PJ_fahey.c index 42318f8f..53606119 100644 --- a/src/PJ_fahey.c +++ b/src/PJ_fahey.c @@ -37,46 +37,3 @@ PJ *PROJECTION(fahey) { return P; } -#ifndef PJ_SELFTEST -int pj_fahey_selftest (void) {return 0;} -#else - -int pj_fahey_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=fahey +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 182993.34464912376, 101603.19356988439}, - { 182993.34464912376, -101603.19356988439}, - {-182993.34464912376, 101603.19356988439}, - {-182993.34464912376, -101603.19356988439}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.0021857886080359551, 0.00098424601668238403}, - {0.0021857886080359551, -0.00098424601668238403}, - {-0.0021857886080359551, 0.00098424601668238403}, - {-0.0021857886080359551, -0.00098424601668238403}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_fouc_s.c b/src/PJ_fouc_s.c index 343e5878..b8ae4a0c 100644 --- a/src/PJ_fouc_s.c +++ b/src/PJ_fouc_s.c @@ -67,46 +67,3 @@ PJ *PROJECTION(fouc_s) { } -#ifndef PJ_SELFTEST -int pj_fouc_s_selftest (void) {return 0;} -#else - -int pj_fouc_s_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=fouc_s +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223402.14425527424, 111695.40119861449}, - { 223402.14425527424, -111695.40119861449}, - {-223402.14425527424, 111695.40119861449}, - {-223402.14425527424, -111695.40119861449}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931097838226, 0.000895246554928339}, - { 0.0017904931097838226, -0.000895246554928339}, - {-0.0017904931097838226, 0.000895246554928339}, - {-0.0017904931097838226, -0.000895246554928339}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_gall.c b/src/PJ_gall.c index 01a56e33..cb213e2d 100644 --- a/src/PJ_gall.c +++ b/src/PJ_gall.c @@ -41,46 +41,3 @@ PJ *PROJECTION(gall) { } -#ifndef PJ_SELFTEST -int pj_gall_selftest (void) {return 0;} -#else - -int pj_gall_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=gall +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 157969.17113451968, 95345.249178385886}, - { 157969.17113451968, -95345.249178385886}, - {-157969.17113451968, 95345.249178385886}, - {-157969.17113451968, -95345.249178385886}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0025321396391918614, 0.001048846580346495}, - { 0.0025321396391918614, -0.001048846580346495}, - {-0.0025321396391918614, 0.001048846580346495}, - {-0.0025321396391918614, -0.001048846580346495}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_geos.c b/src/PJ_geos.c index 5fd3e56b..a787db23 100644 --- a/src/PJ_geos.c +++ b/src/PJ_geos.c @@ -234,61 +234,3 @@ PJ *PROJECTION(geos) { } -#ifndef PJ_SELFTEST -int pj_geos_selftest (void) {return 0;} -#else - -int pj_geos_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=geos +ellps=GRS80 +lat_1=0.5 +lat_2=2 +h=35785831"}; - char s_args[] = {"+proj=geos +R=6400000 +lat_1=0.5 +lat_2=2 +h=35785831"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222527.07036580026, 110551.30341332949}, - { 222527.07036580026, -110551.30341332949}, - {-222527.07036580026, 110551.30341332949}, - {-222527.07036580026, -110551.30341332949}, - }; - - XY s_fwd_expect[] = { - { 223289.45763579503, 111677.65745653701}, - { 223289.45763579503, -111677.65745653701}, - {-223289.45763579503, 111677.65745653701}, - {-223289.45763579503, -111677.65745653701}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305689715385, 0.00090436947723267452}, - { 0.0017966305689715385, -0.00090436947723267452}, - {-0.0017966305689715385, 0.00090436947723267452}, - {-0.0017966305689715385, -0.00090436947723267452}, - }; - - LP s_inv_expect[] = { - { 0.0017904931105078943, 0.00089524655504237148}, - { 0.0017904931105078943, -0.00089524655504237148}, - {-0.0017904931105078943, 0.00089524655504237148}, - {-0.0017904931105078943, -0.00089524655504237148}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_gins8.c b/src/PJ_gins8.c index b27ec092..ae0d4dee 100644 --- a/src/PJ_gins8.c +++ b/src/PJ_gins8.c @@ -31,32 +31,3 @@ PJ *PROJECTION(gins8) { } -#ifndef PJ_SELFTEST -int pj_gins8_selftest (void) {return 0;} -#else - -int pj_gins8_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=gins8 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 194350.25093959007, 111703.90763533533}, - { 194350.25093959007, -111703.90763533533}, - {-194350.25093959007, 111703.90763533533}, - {-194350.25093959007, -111703.90763533533}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_gn_sinu.c b/src/PJ_gn_sinu.c index d13f2834..585d43ca 100644 --- a/src/PJ_gn_sinu.c +++ b/src/PJ_gn_sinu.c @@ -120,7 +120,7 @@ PJ *PROJECTION(sinu) { if (!(Q->en = pj_enfn(P->es))) return pj_default_destructor (P, ENOMEM); - + if (P->es != 0.0) { P->inv = e_inverse; P->fwd = e_forward; @@ -183,195 +183,3 @@ PJ *PROJECTION(gn_sinu) { return P; } - -#ifndef PJ_SELFTEST -int pj_sinu_selftest (void) {return 0;} -#else - -int pj_sinu_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=sinu +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=sinu +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222605.29953946592, 110574.38855415257}, - { 222605.29953946592, -110574.38855415257}, - {-222605.29953946592, 110574.38855415257}, - {-222605.29953946592, -110574.38855415257}, - }; - - XY s_fwd_expect[] = { - { 223368.11902663155, 111701.07212763709}, - { 223368.11902663155, -111701.07212763709}, - {-223368.11902663155, 111701.07212763709}, - {-223368.11902663155, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305684613522, 0.00090436947707945409}, - { 0.0017966305684613522, -0.00090436947707945409}, - {-0.0017966305684613522, 0.00090436947707945409}, - {-0.0017966305684613522, -0.00090436947707945409}, - }; - - LP s_inv_expect[] = { - { 0.0017904931100023887, 0.00089524655489191132}, - { 0.0017904931100023887, -0.00089524655489191132}, - {-0.0017904931100023887, 0.00089524655489191132}, - {-0.0017904931100023887, -0.00089524655489191132}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_eck6_selftest (void) {return 0;} -#else - -int pj_eck6_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=eck6 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 197021.60562899226, 126640.42073317352}, - { 197021.60562899226, -126640.42073317352}, - {-197021.60562899226, 126640.42073317352}, - {-197021.60562899226, -126640.42073317352}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.002029978749734037, 0.00078963032910382171}, - { 0.002029978749734037, -0.00078963032910382171}, - {-0.002029978749734037, 0.00078963032910382171}, - {-0.002029978749734037, -0.00078963032910382171}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_mbtfps_selftest (void) {return 0;} -#else - -int pj_mbtfps_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mbtfps +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 204740.11747857218, 121864.72971934026}, - { 204740.11747857218, -121864.72971934026}, - {-204740.11747857218, 121864.72971934026}, - {-204740.11747857218, -121864.72971934026}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0019534152166442065, 0.00082057965689633387}, - { 0.0019534152166442065, -0.00082057965689633387}, - {-0.0019534152166442065, 0.00082057965689633387}, - {-0.0019534152166442065, -0.00082057965689633387}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - -#ifndef PJ_SELFTEST -int pj_gn_sinu_selftest (void) {return 0;} -#else - -int pj_gn_sinu_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=gn_sinu +a=6400000 +lat_1=0.5 +lat_2=2 +m=1 +n=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223385.13250469571, 111698.23644718733}, - { 223385.13250469571, -111698.23644718733}, - {-223385.13250469571, 111698.23644718733}, - {-223385.13250469571, -111698.23644718733}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931098931057, 0.00089524655491012516}, - { 0.0017904931098931057, -0.00089524655491012516}, - {-0.0017904931098931057, 0.00089524655491012516}, - {-0.0017904931098931057, -0.00089524655491012516}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_gnom.c b/src/PJ_gnom.c index 1d3f3386..12774569 100644 --- a/src/PJ_gnom.c +++ b/src/PJ_gnom.c @@ -6,15 +6,18 @@ PROJ_HEAD(gnom, "Gnomonic") "\n\tAzi, Sph."; #define EPS10 1.e-10 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 + +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; struct pj_opaque { double sinph0; double cosph0; - int mode; + enum Mode mode; }; @@ -135,47 +138,3 @@ PJ *PROJECTION(gnom) { return P; } - -#ifndef PJ_SELFTEST -int pj_gnom_selftest (void) {return 0;} -#else - -int pj_gnom_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=gnom +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223492.92474718543, 111780.50920659291}, - { 223492.92474718543, -111780.50920659291}, - {-223492.92474718543, 111780.50920659291}, - {-223492.92474718543, -111780.50920659291}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931092009798, 0.00089524655438192376}, - { 0.0017904931092009798, -0.00089524655438192376}, - {-0.0017904931092009798, 0.00089524655438192376}, - {-0.0017904931092009798, -0.00089524655438192376}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_goode.c b/src/PJ_goode.c index 3bfeb21f..34312b3b 100644 --- a/src/PJ_goode.c +++ b/src/PJ_goode.c @@ -71,7 +71,7 @@ PJ *PROJECTION(goode) { Q->moll->ctx = P->ctx; if (!(Q->sinu = pj_sinu(Q->sinu)) || !(Q->moll = pj_moll(Q->moll))) return destructor (P, ENOMEM); - + P->fwd = s_forward; P->inv = s_inverse; @@ -79,46 +79,3 @@ PJ *PROJECTION(goode) { } -#ifndef PJ_SELFTEST -int pj_goode_selftest (void) {return 0;} -#else - -int pj_goode_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=goode +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223368.11902663155, 111701.07212763709}, - { 223368.11902663155, -111701.07212763709}, - {-223368.11902663155, 111701.07212763709}, - {-223368.11902663155, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931100023887, 0.00089524655489191132}, - { 0.0017904931100023887, -0.00089524655489191132}, - {-0.0017904931100023887, 0.00089524655489191132}, - {-0.0017904931100023887, -0.00089524655489191132}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_gstmerc.c b/src/PJ_gstmerc.c index c2846761..81ec4e17 100644 --- a/src/PJ_gstmerc.c +++ b/src/PJ_gstmerc.c @@ -68,48 +68,3 @@ PJ *PROJECTION(gstmerc) { return P; } - -#ifndef PJ_SELFTEST -int pj_gstmerc_selftest (void) {return 0;} -#else - -int pj_gstmerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=gstmerc +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - - XY s_fwd_expect[] = { - { 223413.46640632182, 111769.14504058557}, - { 223413.46640632182, -111769.14504058668}, - {-223413.46640632302, 111769.14504058557}, - {-223413.46640632302, -111769.14504058668}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931097109673, 0.0008952465544509083}, - { 0.0017904931097109673, -0.0008952465544509083}, - {-0.0017904931097109673, 0.0008952465544509083}, - {-0.0017904931097109673, -0.0008952465544509083}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_hammer.c b/src/PJ_hammer.c index c18c9a69..4cdaba89 100644 --- a/src/PJ_hammer.c +++ b/src/PJ_hammer.c @@ -71,47 +71,3 @@ PJ *PROJECTION(hammer) { return P; } - -#ifndef PJ_SELFTEST -int pj_hammer_selftest (void) {return 0;} -#else - -int pj_hammer_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=hammer +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223373.78870324057, 111703.90739776699}, - { 223373.78870324057, -111703.90739776699}, - {-223373.78870324057, 111703.90739776699}, - {-223373.78870324057, -111703.90739776699}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.001790493109965961, 0.00089524655487369749}, - { 0.001790493109965961, -0.00089524655487369749}, - {-0.001790493109965961, 0.00089524655487369749}, - {-0.001790493109965961, -0.00089524655487369749}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_hatano.c b/src/PJ_hatano.c index be95fe73..79f46a7d 100644 --- a/src/PJ_hatano.c +++ b/src/PJ_hatano.c @@ -79,54 +79,3 @@ PJ *PROJECTION(hatano) { return P; } -#ifndef PJ_SELFTEST -int pj_hatano_selftest (void) {return 0;} -#else - -int pj_hatano_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=hatano +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 189878.87894652804, 131409.8024406255 -}, - { 189881.08195244463, -131409.14227607418 -}, - {-189878.87894652804, 131409.8024406255 -}, - {-189881.08195244463, -131409.14227607418 -}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0021064624821817597, 0.00076095689425791926 -}, - { 0.0021064624821676096, -0.00076095777439265377 -}, - {-0.0021064624821817597, 0.00076095689425791926 -}, - {-0.0021064624821676096, -0.00076095777439265377 -}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c index 241d7ef4..d8e1a921 100644 --- a/src/PJ_healpix.c +++ b/src/PJ_healpix.c @@ -620,6 +620,8 @@ PJ *PROJECTION(healpix) { if (P->es != 0.0) { Q->apa = pj_authset(P->es); /* For auth_lat(). */ + if (0==Q->apa) + return destructor(P, ENOMEM); Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; @@ -651,6 +653,8 @@ PJ *PROJECTION(rhealpix) { return destructor (P, PJD_ERR_AXIS); if (P->es != 0.0) { Q->apa = pj_authset(P->es); /* For auth_lat(). */ + if (0==Q->apa) + return destructor(P, ENOMEM); Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */ P->a = P->a*sqrt(0.5*Q->qp); /* Set P->a to authalic radius. */ P->ra = 1.0/P->a; @@ -664,121 +668,3 @@ PJ *PROJECTION(rhealpix) { return P; } - -#ifndef PJ_SELFTEST -int pj_healpix_selftest (void) {return 0;} -#else - -int pj_healpix_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=healpix +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=healpix +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222390.10394923863, 130406.58866448226}, - { 222390.10394923863, -130406.58866448054}, - {-222390.10394923863, 130406.58866448226}, - {-222390.10394923863, -130406.58866448054}, - }; - - XY s_fwd_expect[] = { - { 223402.14425527418, 131588.04444199943}, - { 223402.14425527418, -131588.04444199943}, - {-223402.14425527418, 131588.04444199943}, - {-223402.14425527418, -131588.04444199943}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017986411845524453, 0.00076679453057823619}, - { 0.0017986411845524453, -0.00076679453057823619}, - {-0.0017986411845524453, 0.00076679453057823619}, - {-0.0017986411845524453, -0.00076679453057823619}, - }; - - LP s_inv_expect[] = { - { 0.0017904931097838226, 0.00075990887733981202}, - { 0.0017904931097838226, -0.00075990887733981202}, - {-0.0017904931097838226, 0.00075990887733981202}, - {-0.0017904931097838226, -0.00075990887733981202}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_rhealpix_selftest (void) {return 0;} -#else - -int pj_rhealpix_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=rhealpix +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=rhealpix +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222390.10394923863, 130406.58866448226}, - { 222390.10394923863, -130406.58866448054}, - {-222390.10394923863, 130406.58866448226}, - {-222390.10394923863, -130406.58866448054}, - }; - - XY s_fwd_expect[] = { - { 223402.14425527418, 131588.04444199943}, - { 223402.14425527418, -131588.04444199943}, - {-223402.14425527418, 131588.04444199943}, - {-223402.14425527418, -131588.04444199943}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017986411845524453, 0.00076679453057823619}, - { 0.0017986411845524453, -0.00076679453057823619}, - {-0.0017986411845524453, 0.00076679453057823619}, - {-0.0017986411845524453, -0.00076679453057823619}, - }; - - LP s_inv_expect[] = { - { 0.0017904931097838226, 0.00075990887733981202}, - { 0.0017904931097838226, -0.00075990887733981202}, - {-0.0017904931097838226, 0.00075990887733981202}, - {-0.0017904931097838226, -0.00075990887733981202}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_helmert.c b/src/PJ_helmert.c index ffbdd01a..478a2c82 100644 --- a/src/PJ_helmert.c +++ b/src/PJ_helmert.c @@ -92,8 +92,9 @@ struct pj_opaque_helmert { #define R21 (Q->R[2][1]) #define R22 (Q->R[2][2]) +/**************************************************************************/ static void update_parameters(PJ *P) { - /************************************************************************** +/*************************************************************************** Update transformation parameters. --------------------------------- @@ -114,7 +115,8 @@ static void update_parameters(PJ *P) { of that parameter. [0] http://itrf.ign.fr/doc_ITRF/Transfo-ITRF2008_ITRFs.txt - **************************************************************************/ + +*******************************************************************************/ struct pj_opaque_helmert *Q = (struct pj_opaque_helmert *) P->opaque; double dt = Q->t_obs - Q->epoch; @@ -146,8 +148,9 @@ static void update_parameters(PJ *P) { return; } +/**************************************************************************/ static void build_rot_matrix(PJ *P) { - /************************************************************************** +/*************************************************************************** Build rotation matrix. ---------------------- @@ -208,7 +211,7 @@ static void build_rot_matrix(PJ *P) { as published, the "transpose" option provides the ability to switch between the conventions. - ***************************************************************************/ +***************************************************************************/ struct pj_opaque_helmert *Q = (struct pj_opaque_helmert *) P->opaque; double f, t, p; /* phi/fi , theta, psi */ @@ -420,35 +423,35 @@ static LPZ helmert_reverse_3d (XYZ xyz, PJ *P) { } -static PJ_OBS helmert_forward_obs (PJ_OBS point, PJ *P) { +static PJ_COORD helmert_forward_4d (PJ_COORD point, PJ *P) { struct pj_opaque_helmert *Q = (struct pj_opaque_helmert *) P->opaque; /* We only need to rebuild the rotation matrix if the * observation time is different from the last call */ - if (point.coo.xyzt.t != Q->t_obs) { - Q->t_obs = point.coo.xyzt.t; + if (point.xyzt.t != Q->t_obs) { + Q->t_obs = point.xyzt.t; update_parameters(P); build_rot_matrix(P); } - point.coo.xyz = helmert_forward_3d (point.coo.lpz, P); + point.xyz = helmert_forward_3d (point.lpz, P); return point; } -static PJ_OBS helmert_reverse_obs (PJ_OBS point, PJ *P) { +static PJ_COORD helmert_reverse_4d (PJ_COORD point, PJ *P) { struct pj_opaque_helmert *Q = (struct pj_opaque_helmert *) P->opaque; /* We only need to rebuild the rotation matrix if the * observation time is different from the last call */ - if (point.coo.xyzt.t != Q->t_obs) { - Q->t_obs = point.coo.xyzt.t; + if (point.xyzt.t != Q->t_obs) { + Q->t_obs = point.xyzt.t; update_parameters(P); build_rot_matrix(P); } - point.coo.lpz = helmert_reverse_3d (point.coo.xyz, P); + point.lpz = helmert_reverse_3d (point.xyz, P); return point; } @@ -458,15 +461,15 @@ static PJ_OBS helmert_reverse_obs (PJ_OBS point, PJ *P) { #define ARCSEC_TO_RAD (DEG_TO_RAD / 3600.0) /***********************************************************************/ -PJ *PROJECTION(helmert) { +PJ *TRANSFORMATION(helmert, 0) { /***********************************************************************/ struct pj_opaque_helmert *Q = pj_calloc (1, sizeof (struct pj_opaque_helmert)); if (0==Q) return pj_default_destructor (P, ENOMEM); P->opaque = (void *) Q; - P->fwdobs = helmert_forward_obs; - P->invobs = helmert_reverse_obs; + P->fwd4d = helmert_forward_4d; + P->inv4d = helmert_reverse_4d; P->fwd3d = helmert_forward_3d; P->inv3d = helmert_reverse_3d; P->fwd = helmert_forward; @@ -580,145 +583,3 @@ PJ *PROJECTION(helmert) { return P; } - - -#ifndef PJ_SELFTEST - -int pj_helmert_selftest (void) {return 0;} - -#else - - -static int test (char *args, PJ_TRIPLET in, PJ_TRIPLET expect, double tol) { - PJ_TRIPLET out; - PJ *P = pj_init_plus (args); - - if (0==P) - return 5; - - out.xyz = pj_fwd3d (in.lpz, P); - if (proj_xyz_dist (out.xyz, expect.xyz) > tol) { - proj_log_error(P, "Tolerance of forward calculation not met"); - proj_log_error(P, " Expect: %10.10f, %10.10f, %10.10f", expect.xyz.x, expect.xyz.y, expect.xyz.z); - proj_log_error(P, " Out: %10.10f, %10.10f, %10.10f", out.xyz.x, out.xyz.y, out.xyz.z); - proj_log_level(NULL, 0); - proj_destroy (P); - return 1; - } - - out.lpz = pj_inv3d (out.xyz, P); - if (proj_xyz_dist (out.xyz, in.xyz) > tol) { - proj_log_error(P, "Tolerance of inverse calculation not met"); - proj_log_error(P, " In: %10.10f, %10.10f, %10.10f", in.xyz.x, in.xyz.y, in.xyz.z); - proj_log_error(P, " Out: %10.10f, %10.10f, %10.10f", out.xyz.x, out.xyz.y, out.xyz.z); - proj_log_level(NULL, 0); - proj_destroy (P); - return 2; - } - - proj_destroy (P); - return 0; -} - - - -int pj_helmert_selftest (void) { - int ret; - - /* This example is from - Lotti Jivall: - Simplified transformations from ITRF2008/IGS08 to ETRS89 for maritime applications */ - PJ_TRIPLET in1 = {{3565285.0000, 855949.0000, 5201383.0000}}; - PJ_TRIPLET expect1 = {{3565285.41342351, 855948.67986759, 5201382.72939791}}; - char args1[] = { - " +proj=helmert +ellps=GRS80" - " +x=0.67678 +y=0.65495 +z=-0.52827" - " +rx=-0.022742 +ry=0.012667 +rz=0.022704 +s=-0.01070" - /*" +rx=-22.742 +ry=12.667 +rz=22.704 +s=-0.01070" */ - }; - - - /* This example is a random point, transformed from ED50 to ETRS89 using KMStrans2 */ - PJ_TRIPLET in2 = {{3494994.3012, 1056601.9725, 5212382.1666}}; - PJ_TRIPLET expect2 = {{3494909.84026368, 1056506.78938633, 5212265.66699761}}; - char args2[] = { - " +proj=helmert +ellps=GRS80" - " +x=-81.0703 +y=-89.3603 +z=-115.7526" - " +rx=-0.48488 +ry=-0.02436 +rz=-0.41321 +s=-0.540645" - }; - - - /* This example is a coordinate from the geodetic observatory in Onsala, - Sweden transformed from ITRF2000 @ 2017.0 to ITRF93 @ 2017.0. - The test coordinate was transformed using GNSStrans. - Transformation parameters published by ITRF: - ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP */ - PJ_TRIPLET in3 = {{3370658.378, 711877.314, 5349787.086}}; /* ITRF2000@2017.0 */ - PJ_TRIPLET expect3 = {{3370658.18890, 711877.42370, 5349787.12430}}; /* ITRF93@2017.0 */ - char args3[] = { - " +proj=helmert +ellps=GRS80" - " +x=0.0127 +y=0.0065 +z=-0.0209 +s=0.00195" - " +rx=-0.00039 +ry=0.00080 +rz=-0.00114" - " +dx=-0.0029 +dy=-0.0002 +dz=-0.0006 +ds=0.00001" - " +drx=-0.00011 +dry=-0.00019 +drz=0.00007" - " +epoch=1988.0 +tobs=2017.0 +transpose" - }; - - /* Test the 4D-capabilities of the proj.h API, especially that the rotation - matrix is updated when necessary. Test coordinates from GNSStrans. */ - XYZ expect4a = {3370658.18890, 711877.42370, 5349787.12430}; - XYZ expect4b = {3370658.18087, 711877.42750, 5349787.12648}; - PJ_OBS in4 = {{{3370658.378, 711877.314, 5349787.086, 2017.0}}, {{ 0, 0, 0}}, 0, 0}; - PJ_OBS out; - - PJ *helmert = proj_create( - 0, - " +proj=helmert +ellps=GRS80" - " +x=0.0127 +y=0.0065 +z=-0.0209 +s=0.00195" - " +rx=-0.00039 +ry=0.00080 +rz=-0.00114" - " +dx=-0.0029 +dy=-0.0002 +dz=-0.0006 +ds=0.00001" - " +drx=-0.00011 +dry=-0.00019 +drz=0.00007" - " +epoch=1988.0 +transpose" - ); - - /* This example is from "A mathematical relationship between NAD27 and NAD83 (91) - State Plane coordinates in Southeastern Wisconsin": - - http://www.sewrpc.org/SEWRPCFiles/Publications/TechRep/tr-034-Mathematical-Relationship-Between-NAD27-and-NAD83-91-State-Plane-Coordinates-Southeastern-Wisconsin.pdf - - The test data is taken from p. 29. Here we are using point 203 and converting it - from NAD27 (ft) -> NAD83 (m). The paper reports a difference of 0.0014 m from measured - to computed coordinates, hence the test tolerance is set accordingly. */ - PJ_TRIPLET in5 = {{2546506.957, 542256.609, 0}}; - PJ_TRIPLET expect5 = {{766563.675, 165282.277, 0}}; - char args5[] = " +proj=helmert +ellps=GRS80 +x=-9597.3572 +y=.6112 +s=0.304794780637 +theta=-1.244048"; - - /* Run tests 1-3 & 5 */ - ret = test (args1, in1, expect1, 1e-4); if (ret) return ret; - ret = test (args2, in2, expect2, 1e-4); if (ret) return ret + 10; - ret = test (args3, in3, expect3, 1e-4); if (ret) return ret + 20; - ret = test (args5, in5, expect5, 0.001); if (ret) return ret + 40; - - /* Run test 4 */ - out = proj_trans_obs (helmert, PJ_FWD, in4); - if (proj_xyz_dist (out.coo.xyz, expect4a) > 1e-4) { - proj_log_error(helmert, "Tolerance of test 4a not met!"); - proj_log_error(helmert, " In: %10.10f, %10.10f, %10.10f", in4.coo.xyz.x, in4.coo.xyz.y, in4.coo.xyz.z); - proj_log_error(helmert, " Out: %10.10f, %10.10f, %10.10f", out.coo.xyz.x, out.coo.xyz.y, out.coo.xyz.z); - return 31; - } - - in4.coo.xyzt.t = 2018.0; - out = proj_trans_obs (helmert, PJ_FWD, in4); - if (proj_xyz_dist (out.coo.xyz, expect4b) > 1e-4) { - proj_log_error(helmert, "Tolerance of test 4b not met!"); - proj_log_error(helmert, " In: %10.10f, %10.10f, %10.10f", in4.coo.xyz.x, in4.coo.xyz.y, in4.coo.xyz.z); - proj_log_error(helmert, " Out: %10.10f, %10.10f, %10.10f", out.coo.xyz.x, out.coo.xyz.y, out.coo.xyz.z); - return 32; - } - - proj_destroy(helmert); - return 0; -} - -#endif diff --git a/src/PJ_hgridshift.c b/src/PJ_hgridshift.c index 0adc9e00..92275e51 100644 --- a/src/PJ_hgridshift.c +++ b/src/PJ_hgridshift.c @@ -4,7 +4,6 @@ PROJ_HEAD(hgridshift, "Horizontal grid shift"); - static XYZ forward_3d(LPZ lpz, PJ *P) { PJ_TRIPLET point; point.lpz = lpz; @@ -12,9 +11,7 @@ static XYZ forward_3d(LPZ lpz, PJ *P) { if (P->gridlist != NULL) { /* Only try the gridshift if at least one grid is loaded, * otherwise just pass the coordinate through unchanged. */ - pj_apply_gridshift_3( P->ctx, P->gridlist, - P->gridlist_count, 1, 1, 0, - &point.xyz.x, &point.xyz.y, &point.xyz.z ); + point.lp = proj_hgrid_apply(P, point.lp, PJ_FWD); } return point.xyz; @@ -28,55 +25,30 @@ static LPZ reverse_3d(XYZ xyz, PJ *P) { if (P->gridlist != NULL) { /* Only try the gridshift if at least one grid is loaded, * otherwise just pass the coordinate through unchanged. */ - pj_apply_gridshift_3( P->ctx, P->gridlist, - P->gridlist_count, 0, 1, 0, - &point.xyz.x, &point.xyz.y, &point.xyz.z ); + point.lp = proj_hgrid_apply(P, point.lp, PJ_INV); } return point.lpz; } -static PJ_OBS forward_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.xyz = forward_3d (obs.coo.lpz, P); - return point; +static PJ_COORD forward_4d (PJ_COORD obs, PJ *P) { + obs.xyz = forward_3d (obs.lpz, P); + return obs; } -static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.lpz = reverse_3d (obs.coo.xyz, P); - return point; +static PJ_COORD reverse_4d (PJ_COORD obs, PJ *P) { + obs.lpz = reverse_3d (obs.xyz, P); + return obs; } -#if 0 -static XY forward_xy(LP lp, PJ *P) { - PJ_TRIPLET point; - point.lp = lp; - point.lpz.z = 0; - point.xyz = forward_3d (point.lpz, P); - return point.xy; -} - - -static LP reverse_lp(XY xy, PJ *P) { - PJ_TRIPLET point; - point.xy = xy; - point.xyz.z = 0; - point.lpz = reverse_3d (point.xyz, P); - return point.lp; -} -#endif +PJ *TRANSFORMATION(hgridshift,0) { - - -PJ *PROJECTION(hgridshift) { - - P->fwdobs = forward_obs; - P->invobs = reverse_obs; + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; P->fwd3d = forward_3d; P->inv3d = reverse_3d; P->fwd = 0; @@ -90,63 +62,14 @@ PJ *PROJECTION(hgridshift) { return pj_default_destructor (P, PJD_ERR_NO_ARGS); } - /* Build gridlist. P->gridlist can be empty if +grids only ask for optional grids. */ - P->gridlist = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, "sgrids").s, - &(P->gridlist_count) ); + proj_hgrid_init(P, "grids"); /* Was gridlist compiled properly? */ - if ( pj_ctx_get_errno(pj_get_ctx(P)) ) { + if ( proj_errno(P) ) { proj_log_error(P, "hgridshift: could not find required grid(s)."); - return pj_default_destructor (P, PJD_ERR_FAILED_TO_LOAD_GRID); + return pj_default_destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID); } return P; } - -#ifndef PJ_SELFTEST -/* selftest stub */ -int pj_hgridshift_selftest (void) {return 0;} -#else -int pj_hgridshift_selftest (void) { - PJ *P; - PJ_OBS expect, a, b; - double dist; - - /* fail on purpose: +grids parameter is mandatory*/ - P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift"); - if (0!=P) { - proj_destroy (P); - return 99; - } - - /* fail on purpose: open non-existing grid */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift +grids=@nonexistinggrid.gsb,anothernonexistinggrid.gsb"); - if (0!=P) { - proj_destroy (P); - return 999; - } - - /* Failure most likely means the grid is missing */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift +grids=nzgd2kgrid0005.gsb +ellps=GRS80"); - if (0==P) - return 10; - - a = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(173); - a.coo.lpz.phi = PJ_TORAD(-45); - - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 0.00000001) - return 1; - - expect.coo.lpz.lam = PJ_TORAD(172.999892181021551); - expect.coo.lpz.phi = PJ_TORAD(-45.001620431954613); - b = proj_trans_obs(P, PJ_FWD, a); - if (proj_xy_dist(expect.coo.xy, b.coo.xy) > 1e-4) - return 2; - - proj_destroy(P); - return 0; -} -#endif diff --git a/src/PJ_horner.c b/src/PJ_horner.c index d6d2c51c..6f1450cd 100644 --- a/src/PJ_horner.c +++ b/src/PJ_horner.c @@ -1,19 +1,3 @@ -#define PJ_LIB__ -#include "proj_internal.h" -#include "projects.h" -#include <assert.h> -#include <stddef.h> -#include <math.h> -#include <errno.h> - -PROJ_HEAD(horner, "Horner polynomial evaluation"); - -/* make horner.h interface with proj's memory management */ -#define horner_dealloc(x) pj_dealloc(x) -#define horner_calloc(n,x) pj_calloc(n,x) - -/* The next few hundred lines is mostly cut-and-paste from the horner.h header library */ - /*********************************************************************** Interfacing to a classic piece of geodetic software @@ -91,6 +75,20 @@ PROJ_HEAD(horner, "Horner polynomial evaluation"); * *****************************************************************************/ +#define PJ_LIB__ +#include "proj_internal.h" +#include "projects.h" +#include <assert.h> +#include <stddef.h> +#include <math.h> +#include <errno.h> + +PROJ_HEAD(horner, "Horner polynomial evaluation"); + +/* make horner.h interface with proj's memory management */ +#define horner_dealloc(x) pj_dealloc(x) +#define horner_calloc(n,x) pj_calloc(n,x) + struct horner; typedef struct horner HORNER; @@ -289,13 +287,13 @@ summing the tiny high order elements first. -static PJ_OBS horner_forward_obs (PJ_OBS point, PJ *P) { - point.coo.uv = horner ((HORNER *) P->opaque, 1, point.coo.uv); +static PJ_COORD horner_forward_4d (PJ_COORD point, PJ *P) { + point.uv = horner ((HORNER *) P->opaque, 1, point.uv); return point; } -static PJ_OBS horner_reverse_obs (PJ_OBS point, PJ *P) { - point.coo.uv = horner ((HORNER *) P->opaque, -1, point.coo.uv); +static PJ_COORD horner_reverse_4d (PJ_COORD point, PJ *P) { + point.uv = horner ((HORNER *) P->opaque, -1, point.uv); return point; } @@ -371,13 +369,13 @@ polynomial evaluation engine. -static PJ_OBS complex_horner_forward_obs (PJ_OBS point, PJ *P) { - point.coo.uv = complex_horner ((HORNER *) P->opaque, PJ_FWD, point.coo.uv); +static PJ_COORD complex_horner_forward_4d (PJ_COORD point, PJ *P) { + point.uv = complex_horner ((HORNER *) P->opaque, PJ_FWD, point.uv); return point; } -static PJ_OBS complex_horner_reverse_obs (PJ_OBS point, PJ *P) { - point.coo.uv = complex_horner ((HORNER *) P->opaque, PJ_INV, point.coo.uv); +static PJ_COORD complex_horner_reverse_4d (PJ_COORD point, PJ *P) { + point.uv = complex_horner ((HORNER *) P->opaque, PJ_INV, point.uv); return point; } @@ -399,7 +397,7 @@ static int parse_coefs (PJ *P, double *coefs, char *param, int ncoefs) { buf = pj_calloc (strlen (param) + 2, sizeof(char)); if (0==buf) { - proj_log_error (P, "Horner: Out of core"); + proj_log_error (P, "Horner: No memory left"); return 0; } @@ -431,13 +429,13 @@ PJ *PROJECTION(horner) { /*********************************************************************/ int degree = 0, n, complex_horner = 0; HORNER *Q; - P->fwdobs = horner_forward_obs; - P->invobs = horner_reverse_obs; - P->fwd3d = 0; - P->inv3d = 0; - P->fwd = 0; - P->inv = 0; - P->left = P->right = PJ_IO_UNITS_METERS; + P->fwd4d = horner_forward_4d; + P->inv4d = horner_reverse_4d; + P->fwd3d = 0; + P->inv3d = 0; + P->fwd = 0; + P->inv = 0; + P->left = P->right = PJ_IO_UNITS_METERS; P->destructor = horner_freeup; /* Polynomial degree specified? */ @@ -462,8 +460,8 @@ PJ *PROJECTION(horner) { return horner_freeup (P, PJD_ERR_MISSING_ARGS); if (0==parse_coefs (P, Q->inv_c, "inv_c", n)) return horner_freeup (P, PJD_ERR_MISSING_ARGS); - P->fwdobs = complex_horner_forward_obs; - P->invobs = complex_horner_reverse_obs; + P->fwd4d = complex_horner_forward_4d; + P->inv4d = complex_horner_reverse_4d; } else { @@ -488,85 +486,3 @@ PJ *PROJECTION(horner) { return P; } -#ifndef PJ_SELFTEST -/* selftest stub */ -int pj_horner_selftest (void) {return 0;} -#else -char tc32_utm32[] = { - " +proj=horner" - " +ellps=intl" - " +range=500000" - " +fwd_origin=877605.269066,6125810.306769" - " +inv_origin=877605.760036,6125811.281773" - " +deg=4" - " +fwd_v=6.1258112678e+06,9.9999971567e-01,1.5372750011e-10,5.9300860915e-15,2.2609497633e-19,4.3188227445e-05,2.8225130416e-10,7.8740007114e-16,-1.7453997279e-19,1.6877465415e-10,-1.1234649773e-14,-1.7042333358e-18,-7.9303467953e-15,-5.2906832535e-19,3.9984284847e-19" - " +fwd_u=8.7760574982e+05,9.9999752475e-01,2.8817299305e-10,5.5641310680e-15,-1.5544700949e-18,-4.1357045890e-05,4.2106213519e-11,2.8525551629e-14,-1.9107771273e-18,3.3615590093e-10,2.4380247154e-14,-2.0241230315e-18,1.2429019719e-15,5.3886155968e-19,-1.0167505000e-18" - " +inv_v=6.1258103208e+06,1.0000002826e+00,-1.5372762184e-10,-5.9304261011e-15,-2.2612705361e-19,-4.3188331419e-05,-2.8225549995e-10,-7.8529116371e-16,1.7476576773e-19,-1.6875687989e-10,1.1236475299e-14,1.7042518057e-18,7.9300735257e-15,5.2881862699e-19,-3.9990736798e-19" - " +inv_u=8.7760527928e+05,1.0000024735e+00,-2.8817540032e-10,-5.5627059451e-15,1.5543637570e-18,4.1357152105e-05,-4.2114813612e-11,-2.8523713454e-14,1.9109017837e-18,-3.3616407783e-10,-2.4382678126e-14,2.0245020199e-18,-1.2441377565e-15,-5.3885232238e-19,1.0167203661e-18" -}; - - -char sb_utm32[] = { - " +proj=horner" - " +ellps=intl" - " +range=500000" - " +tolerance=0.0005" - " +fwd_origin=4.94690026817276e+05,6.13342113183056e+06" - " +inv_origin=6.19480258923588e+05,6.13258568148837e+06" - " +deg=3" - " +fwd_c=6.13258562111350e+06,6.19480105709997e+05,9.99378966275206e-01,-2.82153291753490e-02,-2.27089979140026e-10,-1.77019590701470e-09,1.08522286274070e-14,2.11430298751604e-15" - " +inv_c=6.13342118787027e+06,4.94690181709311e+05,9.99824464710368e-01,2.82279070814774e-02,7.66123542220864e-11,1.78425334628927e-09,-1.05584823306400e-14,-3.32554258683744e-15" -}; - -int pj_horner_selftest (void) { - PJ *P; - PJ_OBS a, b, c; - double dist; - - /* Real polynonia relating the technical coordinate system TC32 to "System 45 Bornholm" */ - P = proj_create (PJ_DEFAULT_CTX, tc32_utm32); - if (0==P) - return 10; - - a = b = proj_obs_null; - a.coo.uv.v = 6125305.4245; - a.coo.uv.u = 878354.8539; - - /* Check roundtrip precision for 1 iteration each way, starting in forward direction */ - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 0.01) - return 1; - - /* The complex polynomial transformation between the "System Storebaelt" and utm32/ed50 */ - P = proj_create (PJ_DEFAULT_CTX, sb_utm32); - if (0==P) - return 11; - - /* Test value: utm32_ed50(620000, 6130000) = sb_ed50(495136.8544, 6130821.2945) */ - a = b = c = proj_obs_null; - a.coo.uv.v = 6130821.2945; - a.coo.uv.u = 495136.8544; - c.coo.uv.v = 6130000.0000; - c.coo.uv.u = 620000.0000; - - /* Forward projection */ - b = proj_trans_obs (P, PJ_FWD, a); - dist = proj_xy_dist (b.coo.xy, c.coo.xy); - if (dist > 0.001) - return 2; - - /* Inverse projection */ - b = proj_trans_obs (P, PJ_INV, c); - dist = proj_xy_dist (b.coo.xy, a.coo.xy); - if (dist > 0.001) - return 3; - - /* Check roundtrip precision for 1 iteration each way */ - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 0.01) - return 4; - - proj_destroy(P); - return 0; -} -#endif diff --git a/src/PJ_igh.c b/src/PJ_igh.c index 33cdde22..d1d684e7 100644 --- a/src/PJ_igh.c +++ b/src/PJ_igh.c @@ -222,46 +222,3 @@ PJ *PROJECTION(igh) { } -#ifndef PJ_SELFTEST -int pj_igh_selftest (void) {return 0;} -#else - -int pj_igh_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=igh +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223878.49745627123, 111701.07212763709}, - { 223708.37131305804, -111701.07212763709}, - {-222857.74059699223, 111701.07212763709}, - {-223027.86674020503, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.001790489447892545, 0.00089524655489191132}, - { 0.0017904906685957927, -0.00089524655489191132}, - {-0.001790496772112032, 0.00089524655489191132}, - {-0.0017904955514087843, -0.00089524655489191132}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_imw_p.c b/src/PJ_imw_p.c index 29ed3457..9ebb8b4a 100644 --- a/src/PJ_imw_p.c +++ b/src/PJ_imw_p.c @@ -9,11 +9,17 @@ PROJ_HEAD(imw_p, "International Map of the World Polyconic") #define TOL 1e-10 #define EPS 1e-10 +enum Mode { + NONE_IS_ZERO = 0, /* phi_1 and phi_2 != 0 */ + PHI_1_IS_ZERO = 1, /* phi_1 = 0 */ + PHI_2_IS_ZERO = -1 /* phi_2 = 0 */ +}; + struct pj_opaque { - double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; \ - double phi_1, phi_2, lam_1; \ - double *en; \ - int mode; /* = 0, phi_1 and phi_2 != 0, = 1, phi_1 = 0, = -1 phi_2 = 0 */ + double P, Pp, Q, Qp, R_1, R_2, sphi_1, sphi_2, C2; + double phi_1, phi_2, lam_1; + double *en; + enum Mode mode; }; @@ -53,7 +59,7 @@ static XY loc_for(LP lp, PJ *P, double *yc) { C = sqrt(R * R - xa * xa); if (lp.phi < 0.) C = - C; C += ya - R; - if (Q->mode < 0) { + if (Q->mode == PHI_2_IS_ZERO) { xb = lp.lam; yb = Q->C2; } else { @@ -61,7 +67,7 @@ static XY loc_for(LP lp, PJ *P, double *yc) { xb = Q->R_2 * sin(t); yb = Q->C2 + Q->R_2 * (1. - cos(t)); } - if (Q->mode > 0) { + if (Q->mode == PHI_1_IS_ZERO) { xc = lp.lam; *yc = 0.; } else { @@ -171,18 +177,18 @@ PJ *PROJECTION(imw_p) { else sig = 8.; Q->lam_1 = sig * DEG_TO_RAD; } - Q->mode = 0; + Q->mode = NONE_IS_ZERO; if (Q->phi_1 != 0.0) xy(P, Q->phi_1, &x1, &y1, &Q->sphi_1, &Q->R_1); else { - Q->mode = 1; + Q->mode = PHI_1_IS_ZERO; y1 = 0.; x1 = Q->lam_1; } if (Q->phi_2 != 0.0) xy(P, Q->phi_2, &x2, &T2, &Q->sphi_2, &Q->R_2); else { - Q->mode = -1; + Q->mode = PHI_2_IS_ZERO; T2 = 0.; x2 = Q->lam_1; } @@ -205,47 +211,3 @@ PJ *PROJECTION(imw_p) { return P; } - -#ifndef PJ_SELFTEST -int pj_imw_p_selftest (void) {return 0;} -#else - -int pj_imw_p_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=imw_p +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222588.4411393762, 55321.128653809537}, - { 222756.90637768712, -165827.58428832365}, - {-222588.4411393762, 55321.128653809537}, - {-222756.90637768712, -165827.58428832365}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966991379592214, 0.50090492361427374}, - { 0.0017966979081574697, 0.49909507588689922}, - {-0.0017966991379592214, 0.50090492361427374}, - {-0.0017966979081574697, 0.49909507588689922}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_isea.c b/src/PJ_isea.c index 223d8f28..bf006a62 100644 --- a/src/PJ_isea.c +++ b/src/PJ_isea.c @@ -1147,33 +1147,3 @@ PJ *PROJECTION(isea) { return P; } - -#ifndef PJ_SELFTEST -int pj_isea_selftest (void) {return 0;} -#else - -int pj_isea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=isea +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {-1097074.9480224741, 3442909.3090371834}, - {-1097074.9482647954, 3233611.7285857084}, - {-1575486.3536415542, 3442168.3420281881}, - {-1575486.353880283, 3234352.6955947056}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c index 640ce07f..ef00d715 100644 --- a/src/PJ_krovak.c +++ b/src/PJ_krovak.c @@ -219,47 +219,3 @@ PJ *PROJECTION(krovak) { return P; } - -#ifndef PJ_SELFTEST -int pj_krovak_selftest (void) {return 0;} -#else - -int pj_krovak_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=krovak +ellps=GRS80 +no_defs"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {-3196535.2325636409, -6617878.8675514441}, - {-3260035.4405521089, -6898873.6148780314}, - {-3756305.3288691747, -6478142.5615715114}, - {-3831703.6585019818, -6759107.1701553948}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {24.836218918719162, 59.758403933233858}, - {24.836315484509566, 59.756888425730189}, - {24.830447747947495, 59.758403933233858}, - {24.830351182157091, 59.756888425730189}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_labrd.c b/src/PJ_labrd.c index 4b5d93a5..16c45a0d 100644 --- a/src/PJ_labrd.c +++ b/src/PJ_labrd.c @@ -128,47 +128,3 @@ PJ *PROJECTION(labrd) { return P; } - -#ifndef PJ_SELFTEST -int pj_labrd_selftest (void) {return 0;} -#else - -int pj_labrd_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=labrd +ellps=GRS80 +lon_0=0.5 +lat_0=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 166973.166090228391, -110536.912730266107}, - { 166973.168287157256, -331761.993650884193}, - {-278345.500519976194, -110469.032642031714}, - {-278345.504185269645, -331829.870790275279}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.501797719349373672, 2.00090435742047923}, - {0.501797717380853658, 1.99909564058898681}, - {0.498202280650626328, 2.00090435742047923}, - {0.498202282619146342, 1.99909564058898681}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_laea.c b/src/PJ_laea.c index ddca63d9..82a341d8 100644 --- a/src/PJ_laea.c +++ b/src/PJ_laea.c @@ -5,6 +5,13 @@ PROJ_HEAD(laea, "Lambert Azimuthal Equal Area") "\n\tAzi, Sph&Ell"; +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; + struct pj_opaque { double sinb1; double cosb1; @@ -15,16 +22,12 @@ struct pj_opaque { double dd; double rq; double *apa; - int mode; + enum Mode mode; }; #define EPS10 1.e-10 #define NITER 20 #define CONV 1.e-10 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ XY xy = {0.0,0.0}; @@ -255,6 +258,8 @@ PJ *PROJECTION(laea) { Q->qp = pj_qsfn(1., P->e, P->one_es); Q->mmf = .5 / (1. - P->es); Q->apa = pj_authset(P->es); + if (0==Q->apa) + return destructor(P, ENOMEM); switch (Q->mode) { case N_POLE: case S_POLE: @@ -290,62 +295,3 @@ PJ *PROJECTION(laea) { return P; } - -#ifndef PJ_SELFTEST -int pj_laea_selftest (void) {return 0;} -#else - -int pj_laea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=laea +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=laea +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222602.471450095181, 110589.82722441027}, - { 222602.471450095181, -110589.827224408786}, - {-222602.471450095181, 110589.82722441027}, - {-222602.471450095181, -110589.827224408786}, - }; - - XY s_fwd_expect[] = { - { 223365.281370124663, 111716.668072915665}, - { 223365.281370124663, -111716.668072915665}, - {-223365.281370124663, 111716.668072915665}, - {-223365.281370124663, -111716.668072915665}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056847900867, 0.000904369475966495845}, - { 0.00179663056847900867, -0.000904369475966495845}, - {-0.00179663056847900867, 0.000904369475966495845}, - {-0.00179663056847900867, -0.000904369475966495845}, - }; - - LP s_inv_expect[] = { - { 0.00179049311002060264, 0.000895246554791735271}, - { 0.00179049311002060264, -0.000895246554791735271}, - {-0.00179049311002060264, 0.000895246554791735271}, - {-0.00179049311002060264, -0.000895246554791735271}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_lagrng.c b/src/PJ_lagrng.c index e30f6a36..b4744ed5 100644 --- a/src/PJ_lagrng.c +++ b/src/PJ_lagrng.c @@ -61,33 +61,3 @@ PJ *PROJECTION(lagrng) { return P; } - -#ifndef PJ_SELFTEST -int pj_lagrng_selftest (void) {return 0;} -#else - -int pj_lagrng_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=lagrng +a=6400000 +W=2 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 111703.37591722561, 27929.8319080333386}, - { 111699.122088816002, -83784.1780133577704}, - {-111703.37591722561, 27929.8319080333386}, - {-111699.122088816002, -83784.1780133577704}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_larr.c b/src/PJ_larr.c index cd6e6c8a..a8d1af56 100644 --- a/src/PJ_larr.c +++ b/src/PJ_larr.c @@ -24,33 +24,3 @@ PJ *PROJECTION(larr) { return P; } - -#ifndef PJ_SELFTEST -int pj_larr_selftest (void) {return 0;} -#else - -int pj_larr_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=larr +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223393.637624200899, 111707.215961255497}, - {223393.637624200899, -111707.215961255497}, - {-223393.637624200899, 111707.215961255497}, - {-223393.637624200899, -111707.215961255497}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_lask.c b/src/PJ_lask.c index d0efeb7d..0bb3812c 100644 --- a/src/PJ_lask.c +++ b/src/PJ_lask.c @@ -37,32 +37,3 @@ PJ *PROJECTION(lask) { return P; } -#ifndef PJ_SELFTEST -int pj_lask_selftest (void) {return 0;} -#else - -int pj_lask_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=lask +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 217928.275907355128, 112144.32922014239}, - { 217928.275907355128, -112144.32922014239}, - {-217928.275907355128, 112144.32922014239}, - {-217928.275907355128, -112144.32922014239}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_latlong.c b/src/PJ_latlong.c index dec69b70..5919023a 100644 --- a/src/PJ_latlong.c +++ b/src/PJ_latlong.c @@ -1,6 +1,6 @@ /****************************************************************************** * Project: PROJ.4 - * Purpose: Stub projection implementation for lat/long coordinates. We + * Purpose: Stub projection implementation for lat/long coordinates. We * don't actually change the coordinates, but we want proj=latlong * to act sort of like a projection. * Author: Frank Warmerdam, warmerdam@pobox.com @@ -29,7 +29,9 @@ /* very loosely based upon DMA code by Bradford W. Drew */ #define PJ_LIB__ -#include <projects.h> +#include "proj_internal.h" +#include <proj.h> +#include "projects.h" PROJ_HEAD(lonlat, "Lat/long (Geodetic)") "\n\t"; PROJ_HEAD(latlon, "Lat/long (Geodetic alias)") "\n\t"; @@ -52,6 +54,15 @@ static LP inverse(XY xy, PJ *P) { return lp; } +static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) { + (void) P; + return obs; +} + +static PJ_COORD inverse_4d(PJ_COORD obs, PJ *P) { + (void) P; + return obs; +} PJ *PROJECTION(latlong) { P->is_latlong = 1; @@ -59,6 +70,10 @@ PJ *PROJECTION(latlong) { P->y0 = 0.0; P->inv = inverse; P->fwd = forward; + P->inv4d = inverse_4d; + P->fwd4d = forward_4d; + P->left = PJ_IO_UNITS_RADIANS; + P->right = PJ_IO_UNITS_RADIANS; return P; } @@ -70,6 +85,10 @@ PJ *PROJECTION(longlat) { P->y0 = 0.0; P->inv = inverse; P->fwd = forward; + P->inv4d = inverse_4d; + P->fwd4d = forward_4d; + P->left = PJ_IO_UNITS_RADIANS; + P->right = PJ_IO_UNITS_RADIANS; return P; } @@ -81,6 +100,10 @@ PJ *PROJECTION(latlon) { P->y0 = 0.0; P->inv = inverse; P->fwd = forward; + P->inv4d = inverse_4d; + P->fwd4d = forward_4d; + P->left = PJ_IO_UNITS_RADIANS; + P->right = PJ_IO_UNITS_RADIANS; return P; } @@ -90,20 +113,13 @@ PJ *PROJECTION(lonlat) { P->is_latlong = 1; P->x0 = 0.0; P->y0 = 0.0; - P->inv = inverse; P->fwd = forward; + P->inv = inverse; + P->fwd = forward; + P->inv4d = inverse_4d; + P->fwd4d = forward_4d; + P->left = PJ_IO_UNITS_RADIANS; + P->right = PJ_IO_UNITS_RADIANS; return P; } - -/* Bogus self-test functions. Self-tests can't be implemented the usual way for - * these "projections" since they can't be used directly from proj. - * We still need them though, as all projections are automatically added to - * the list of self-test functions. - * - * The code should be covered by the tests in nad/. - * */ -int pj_latlong_selftest (void) {return 0;} -int pj_longlat_selftest (void) {return 0;} -int pj_latlon_selftest (void) {return 0;} -int pj_lonlat_selftest (void) {return 0;} diff --git a/src/PJ_lcc.c b/src/PJ_lcc.c index 78c227b8..a24d5ac0 100644 --- a/src/PJ_lcc.c +++ b/src/PJ_lcc.c @@ -73,21 +73,6 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */ return lp; } -static void special(LP lp, PJ *P, struct FACTORS *fac) { - struct pj_opaque *Q = P->opaque; - double rho; - if (fabs(fabs(lp.phi) - M_HALFPI) < EPS10) { - if ((lp.phi * Q->n) <= 0.) return; - rho = 0.; - } else - rho = Q->c * (Q->ellips ? pow(pj_tsfn(lp.phi, sin(lp.phi), - P->e), Q->n) : pow(tan(M_FORTPI + .5 * lp.phi), -Q->n)); - fac->code |= IS_ANAL_HK + IS_ANAL_CONV; - fac->k = fac->h = P->k0 * Q->n * rho / - pj_msfn(sin(lp.phi), cos(lp.phi), P->es); - fac->conv = Q->n * lp.lam; -} - PJ *PROJECTION(lcc) { double cosphi, sinphi; @@ -139,52 +124,7 @@ PJ *PROJECTION(lcc) { P->inv = e_inverse; P->fwd = e_forward; - P->spc = special; return P; } - -#ifndef PJ_SELFTEST -int pj_lcc_selftest (void) {return 0;} -#else - -int pj_lcc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=lcc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222588.439735968423, 110660.533870799671}, - { 222756.879700278747, -110532.797660827026}, - {-222588.439735968423, 110660.533870799671}, - {-222756.879700278747, -110532.797660827026}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179635940600536667, 0.000904232207322381741}, - { 0.00179635817735249777, -0.000904233135128348995}, - {-0.00179635940600536667, 0.000904232207322381741}, - {-0.00179635817735249777, -0.000904233135128348995}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_lcca.c b/src/PJ_lcca.c index 7d1355b9..61b2ed02 100644 --- a/src/PJ_lcca.c +++ b/src/PJ_lcca.c @@ -1,5 +1,50 @@ -/* PROJ.4 Cartographic Projection System -*/ +/***************************************************************************** + + Lambert Conformal Conic Alternative + ----------------------------------- + + This is Gerald Evenden's 2003 implementation of an alternative + "almost" LCC, which has been in use historically, but which + should NOT be used for new projects - i.e: use this implementation + if you need interoperability with old data represented in this + projection, but not in any other case. + + The code was originally discussed on the PROJ.4 mailing list in + a thread archived over at + + http://lists.maptools.org/pipermail/proj/2003-March/000644.html + + It was discussed again in the thread starting at + + http://lists.maptools.org/pipermail/proj/2017-October/007828.html + and continuing at + http://lists.maptools.org/pipermail/proj/2017-November/007831.html + + which prompted Clifford J. Mugnier to add these clarifying notes: + + The French Army Truncated Cubic Lambert (partially conformal) Conic + projection is the Legal system for the projection in France between + the late 1800s and 1948 when the French Legislature changed the law + to recognize the fully conformal version. + + It was (might still be in one or two North African prior French + Colonies) used in North Africa in Algeria, Tunisia, & Morocco, as + well as in Syria during the Levant. + + Last time I have seen it used was about 30+ years ago in + Algeria when it was used to define Lease Block boundaries for + Petroleum Exploration & Production. + + (signed) + + Clifford J. Mugnier, c.p., c.m.s. + Chief of Geodesy + LSU Center for GeoInformatics + Dept. of Civil Engineering + LOUISIANA STATE UNIVERSITY + +*****************************************************************************/ + #define PJ_LIB__ #include <errno.h> #include <proj.h> @@ -113,48 +158,3 @@ PJ *PROJECTION(lcca) { return P; } - - -#ifndef PJ_SELFTEST -int pj_lcca_selftest (void) {return 0;} -#else - -int pj_lcca_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=lcca +ellps=GRS80 +lat_0=1 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222605.285770237417, 67.8060072715846616}, - { 222740.037637936533, -221125.539829601563}, - {-222605.285770237417, 67.8060072715846616}, - {-222740.037637936533, -221125.539829601563}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179690290525662526, 1.00090436621350798}, - { 0.00179690192174008037, 0.999095632791497268}, - {-0.00179690290525662526, 1.00090436621350798}, - {-0.00179690192174008037, 0.999095632791497268}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_loxim.c b/src/PJ_loxim.c index a4ae074b..bb870713 100644 --- a/src/PJ_loxim.c +++ b/src/PJ_loxim.c @@ -71,47 +71,3 @@ PJ *PROJECTION(loxim) { return P; } - -#ifndef PJ_SELFTEST -int pj_loxim_selftest (void) {return 0;} -#else - -int pj_loxim_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=loxim +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223382.295791338867, 55850.5360638185448}, - { 223393.637462243292, -167551.608191455656}, - {-223382.295791338867, 55850.5360638185448}, - {-223393.637462243292, -167551.608191455656}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179056141104335601, 0.500895246554891926}, - { 0.00179056116683692576, 0.499104753445108074}, - {-0.00179056141104335601, 0.500895246554891926}, - {-0.00179056116683692576, 0.499104753445108074}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_lsat.c b/src/PJ_lsat.c index 1b3778d6..65b20fe4 100644 --- a/src/PJ_lsat.c +++ b/src/PJ_lsat.c @@ -163,7 +163,7 @@ PJ *PROJECTION(lsat) { path = pj_param(P->ctx, P->params, "ipath").i; if (path <= 0 || path > (land <= 3 ? 251 : 233)) - pj_default_destructor(P, PJD_ERR_PATH_NOT_IN_RANGE); + return pj_default_destructor(P, PJD_ERR_PATH_NOT_IN_RANGE); if (land <= 3) { P->lam0 = DEG_TO_RAD * 128.87 - M_TWOPI / 251. * path; @@ -208,47 +208,3 @@ PJ *PROJECTION(lsat) { return P; } - -#ifndef PJ_SELFTEST -int pj_lsat_selftest (void) {return 0;} -#else - -int pj_lsat_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=lsat +ellps=GRS80 +lat_1=0.5 +lat_2=2 +lsat=1 +path=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {18241950.01455855, 9998256.83982293494}, - {18746856.2533194572, 10215761.669925211}, - {18565503.6836331636, 9085039.14672705345}, - {19019696.9020289108, 9247763.0394328218}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {126.000423834530011, 0.00172378224025701425}, - {126.002213738256714, 0.00188015467480917966}, - {126.000734468914601, -0.00188015467480917966}, - {126.002524372641304, -0.00172378224025701425}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_mbt_fps.c b/src/PJ_mbt_fps.c index c35da04c..2fccf3aa 100644 --- a/src/PJ_mbt_fps.c +++ b/src/PJ_mbt_fps.c @@ -53,46 +53,3 @@ PJ *PROJECTION(mbt_fps) { return P; } -#ifndef PJ_SELFTEST -int pj_mbt_fps_selftest (void) {return 0;} -#else - -int pj_mbt_fps_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mbt_fps +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 198798.176129849948, 125512.017254530627}, - { 198798.176129849948, -125512.017254530627}, - {-198798.176129849948, 125512.017254530627}, - {-198798.176129849948, -125512.017254530627}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00201197086238270742, 0.000796711850174446003}, - { 0.00201197086238270742, -0.000796711850174446003}, - {-0.00201197086238270742, 0.000796711850174446003}, - {-0.00201197086238270742, -0.000796711850174446003}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_mbtfpp.c b/src/PJ_mbtfpp.c index 2bbb16b1..3bf2fa94 100644 --- a/src/PJ_mbtfpp.c +++ b/src/PJ_mbtfpp.c @@ -61,46 +61,3 @@ PJ *PROJECTION(mbtfpp) { return P; } -#ifndef PJ_SELFTEST -int pj_mbtfpp_selftest (void) {return 0;} -#else - -int pj_mbtfpp_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mbtfpp +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {206804.786929820373, 120649.762565792524}, - {206804.786929820373, -120649.762565792524}, - {-206804.786929820373, 120649.762565792524}, - {-206804.786929820373, -120649.762565792524}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00193395359462902698, 0.00082883725477665357}, - {0.00193395359462902698, -0.00082883725477665357}, - {-0.00193395359462902698, 0.00082883725477665357}, - {-0.00193395359462902698, -0.00082883725477665357}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_mbtfpq.c b/src/PJ_mbtfpq.c index 4901401e..4a0d48df 100644 --- a/src/PJ_mbtfpq.c +++ b/src/PJ_mbtfpq.c @@ -70,46 +70,3 @@ PJ *PROJECTION(mbtfpq) { return P; } -#ifndef PJ_SELFTEST -int pj_mbtfpq_selftest (void) {return 0;} -#else - -int pj_mbtfpq_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mbtfpq +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 209391.854738393013, 119161.040199054827}, - { 209391.854738393013, -119161.040199054827}, - {-209391.854738393013, 119161.040199054827}, - {-209391.854738393013, -119161.040199054827}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00191010555824111571, 0.000839185447792341723}, - { 0.00191010555824111571, -0.000839185447792341723}, - {-0.00191010555824111571, 0.000839185447792341723}, - {-0.00191010555824111571, -0.000839185447792341723}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_merc.c b/src/PJ_merc.c index d17a2d50..5e0827b7 100644 --- a/src/PJ_merc.c +++ b/src/PJ_merc.c @@ -76,62 +76,3 @@ PJ *PROJECTION(merc) { return P; } - -#ifndef PJ_SELFTEST -int pj_merc_selftest (void) {return 0;} -#else - -int pj_merc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=merc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=merc +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222638.981586547132, 110579.965218249708}, - { 222638.981586547132, -110579.965218249112}, - {-222638.981586547132, 110579.965218249708}, - {-222638.981586547132, -110579.965218249112}, - }; - - XY s_fwd_expect[] = { - { 223402.144255274179, 111706.743574944077}, - { 223402.144255274179, -111706.743574944485}, - {-223402.144255274179, 111706.743574944077}, - {-223402.144255274179, -111706.743574944485}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056823904264, 0.00090436947522799056}, - { 0.00179663056823904264, -0.00090436947522799056}, - {-0.00179663056823904264, 0.00090436947522799056}, - {-0.00179663056823904264, -0.00090436947522799056}, - }; - - LP s_inv_expect[] = { - { 0.00179049310978382265, 0.000895246554845297135}, - { 0.00179049310978382265, -0.000895246554858019272}, - {-0.00179049310978382265, 0.000895246554845297135}, - {-0.00179049310978382265, -0.000895246554858019272}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_mill.c b/src/PJ_mill.c index 829bc3be..fdb0b2ad 100644 --- a/src/PJ_mill.c +++ b/src/PJ_mill.c @@ -33,47 +33,3 @@ PJ *PROJECTION(mill) { return P; } - -#ifndef PJ_SELFTEST -int pj_mill_selftest (void) {return 0;} -#else - -int pj_mill_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mill +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223402.144255274179, 111704.701754393827}, - { 223402.144255274179, -111704.701754396243}, - {-223402.144255274179, 111704.701754393827}, - {-223402.144255274179, -111704.701754396243}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049310978382265, 0.000895246554873922024}, - { 0.00179049310978382265, -0.000895246554873922024}, - {-0.00179049310978382265, 0.000895246554873922024}, - {-0.00179049310978382265, -0.000895246554873922024}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_misrsom.c b/src/PJ_misrsom.c index 5c5a226f..d23f5fa8 100644 --- a/src/PJ_misrsom.c +++ b/src/PJ_misrsom.c @@ -215,62 +215,3 @@ PJ *PROJECTION(misrsom) { return P; } - -#ifndef PJ_SELFTEST -int pj_misrsom_selftest (void) {return 0;} -#else - -int pj_misrsom_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=misrsom +ellps=GRS80 +lat_1=0.5 +lat_2=2 +path=1"}; - char s_args[] = {"+proj=misrsom +R=6400000 +lat_1=0.5 +lat_2=2 +path=1"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {18556630.3683698252, 9533394.6753112711}, - {19041866.0067297369, 9707182.17532352544}, - {18816810.1301847994, 8647669.64980295487}, - {19252610.7845367305, 8778164.08580140397}, - }; - - XY s_fwd_expect[] = { - {18641249.2791703865, 9563342.53233416565}, - {19130982.4615812786, 9739539.59350463562}, - {18903483.5150115378, 8675064.50061797537}, - {19343388.3998006098, 8807471.90406848863}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {127.759503987730625, 0.00173515039622462014}, - {127.761295471077958, 0.00187196632421706517}, - {127.759775773557251, -0.00187196632421891525}, - {127.76156725690457, -0.00173515039622462014}, - }; - - LP s_inv_expect[] = { - {127.75950514818588, 0.00171623111593511971}, - {127.761290323778738, 0.00185412132880796244}, - {127.759780920856471, -0.00185412132880796244}, - {127.761566096449329, -0.00171623111593511971}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_mod_ster.c b/src/PJ_mod_ster.c index 767863c1..c8e4c6b8 100644 --- a/src/PJ_mod_ster.c +++ b/src/PJ_mod_ster.c @@ -277,256 +277,3 @@ PJ *PROJECTION(gs50) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_mil_os_selftest (void) {return 0;} -#else - -int pj_mil_os_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=mil_os +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {-1908527.94959420455, -1726237.4730614475}, - {-1916673.02291848511, -1943133.88812552323}, - {-2344429.41208962305, -1706258.05121891224}, - {-2354637.83553299867, -1926468.60513541684}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {20.0020363939492398, 18.0009683469140498}, - {20.0020363715837419, 17.999031631815086}, - {19.9979636060507602, 18.0009683469140498}, - {19.9979636284162581, 17.999031631815086}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_lee_os_selftest (void) {return 0;} -#else - -int pj_lee_os_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=lee_os +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {-25564478.9526050538, 154490848.8286255}, - { 30115393.9385746419, 125193997.439701974}, - {-31039340.5921660066, 57678685.0448915437}, - {-3088419.93942357088, 58150091.0991110131}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {-164.997479457813824, -9.99875886103541411}, - {-164.997479438558884, -10.0012411200022751}, - {-165.002520542186289, -9.99875886103545142}, - {-165.002520561440946, -10.0012411200022999}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_gs48_selftest (void) {return 0;} -#else - -int pj_gs48_selftest (void) { - double tolerance_lp = 1e-12; - double tolerance_xy = 1e-8; - - char s_args[] = {"+proj=gs48 +R=6370997"}; - - /* All latitudes and longitudes within the continental US */ - LP fwd_in[] = { - { -119.0, 40.0}, - { -70.0, 64.0}, - { -80.0, 25.0}, - { -95.0, 35.0} - }; - - XY s_fwd_expect[] = { - { -1923908.446529345820, 355874.658944479190}, - { 1354020.375109298155, 3040846.007866524626}, - { 1625139.160484319553, -1413614.894029108109}, - { 90241.658071457961, -439595.048485902138}, - }; - - XY inv_in[] = { - { -1923000.0, 355000.0}, - { 1354000.0, 3040000.0}, - { 1625000.0, -1413000.0}, - { 90000.0, -439000.0}, - }; - - LP s_inv_expect[] = { - {-118.987112613284, 39.994449789388}, - { -70.005208999424, 63.993387835525}, - { -80.000346610440, 25.005602546594}, - { -95.002606473071, 35.005424705030}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_alsk_selftest (void) {return 0;} -#else - -int pj_alsk_selftest (void) { - - /* The standard test points are way outside the definition area bounds, hence we relax tolerances */ - double tolerance_lp = 1e-12; - double tolerance_xy = 1e-8; - - char e_args[] = {"+proj=alsk +ellps=clrk66"}; - char s_args[] = {"+proj=alsk +R=6370997"}; - - LP fwd_in[] = { - {-160.0, 55.0}, - {-160.0, 70.0}, - {-145.0, 70.0}, - {-145.0, 60.0} - }; - - XY e_fwd_expect[] = { - {-513253.146950842060, -968928.031867943470}, - {-305001.133897637190, 687494.464958650530}, - {266454.305088600490, 683423.477493030950}, - {389141.322439243960, -423913.251230396680}, - }; - - XY s_fwd_expect[] = { - {-511510.319410844070, -967150.991676078060}, - {-303744.771290368980, 685439.745941123230}, - {265354.974019662940, 681386.892874573010}, - {387711.995394026630, -422980.685505462640}, - }; - - XY inv_in[] = { - {-500000.0, -950000.0}, - {-305000.0, 700000.0}, - { 250000.0, 700000.0}, - { 400000.0, -400000.0} - }; - - LP e_inv_expect[] = { - {-159.830804302926, 55.183195262220}, - {-160.042203155537, 70.111086864056}, - {-145.381043551466, 70.163900908411}, - {-144.758985461448, 60.202929200739}, - }; - - LP s_inv_expect[] = { - {-159.854014457557, 55.165653849074}, - {-160.082332371601, 70.128307617632}, - {-145.347827407243, 70.181566919011}, - {-144.734239827146, 60.193564732505}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_gs50_selftest (void) {return 0;} -#else - -int pj_gs50_selftest (void) { - double tolerance_lp = 1e-12; - double tolerance_xy = 1e-8; - - char e_args[] = {"+proj=gs50 +ellps=clrk66"}; - char s_args[] = {"+proj=gs50 +R=6370997"}; - - LP fwd_in[] = { - {-160.0, 65.0}, - {-130.0, 45.0}, - { -65.0, 45.0}, - { -80.0, 36.0}, - }; - - XY e_fwd_expect[] = { - {-1874628.5377402329, 2660907.942291015300}, - { -771831.51885333552, 48465.166491304852}, - { 4030931.8339815089, 1323687.864777399200}, - { 3450764.2615361013, -175619.041820732440}, - }; - - XY s_fwd_expect[] = { - {-1867268.2534600089, 2656506.230401823300}, - { -769572.18967299373, 48324.312440863941}, - { 4019393.068680791200, 1320191.309350289200}, - { 3442685.615172345700, -178760.423489428680}, - }; - - XY inv_in[] = { - {-1800000.0, 2600000.0}, - { -800000.0, 500000.0}, - { 4000000.0, 1300000.0}, - { 3900000.0, -170000.0}, - }; - - LP e_inv_expect[] = { - {-157.989284999679, 64.851559609698}, - {-131.171390466814, 49.084969745967}, - { -65.491568685301, 44.992837923774}, - { -75.550660091101, 34.191114075743}, - }; - - LP s_inv_expect[] = { - {-158.163295044933, 64.854288364994}, - {-131.206816959506, 49.082915350974}, - { -65.348945220767, 44.957292681774}, - { -75.446820242089, 34.185406225616}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_moll.c b/src/PJ_moll.c index 8470bb3e..66e6315a 100644 --- a/src/PJ_moll.c +++ b/src/PJ_moll.c @@ -106,138 +106,3 @@ PJ *PROJECTION(wag5) { return P; } - -#ifndef PJ_SELFTEST -int pj_moll_selftest (void) {return 0;} -#else - -int pj_moll_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=moll +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {201113.698641813244, 124066.283433859542}, - {201113.698641813244, -124066.283433859542}, - {-201113.698641813244, 124066.283433859542}, - {-201113.698641813244, -124066.283433859542}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00198873782220854774, 0.000806005080362811612}, - {0.00198873782220854774, -0.000806005080362811612}, - {-0.00198873782220854774, 0.000806005080362811612}, - {-0.00198873782220854774, -0.000806005080362811612}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_wag4_selftest (void) {return 0;} -#else - -int pj_wag4_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag4 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 192801.218662384286, 129416.216394802992}, - { 192801.218662384286, -129416.216394802992}, - {-192801.218662384286, 129416.216394802992}, - {-192801.218662384286, -129416.216394802992}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00207450259783523421, 0.000772682950537716476}, - { 0.00207450259783523421, -0.000772682950537716476}, - {-0.00207450259783523421, 0.000772682950537716476}, - {-0.00207450259783523421, -0.000772682950537716476}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - -#ifndef PJ_SELFTEST -int pj_wag5_selftest (void) {return 0;} -#else - -int pj_wag5_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag5 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - - XY s_fwd_expect[] = { - { 203227.05192532466, 138651.631442713202}, - { 203227.05192532466, -138651.631442713202}, - {-203227.05192532466, 138651.631442713202}, - {-203227.05192532466, -138651.631442713202}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - - - - LP s_inv_expect[] = { - { 0.00196807227086416396, 0.00072121615041701424}, - { 0.00196807227086416396, -0.00072121615041701424}, - {-0.00196807227086416396, 0.00072121615041701424}, - {-0.00196807227086416396, -0.00072121615041701424}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_molodensky.c b/src/PJ_molodensky.c index f09f07cd..1b0eb3a1 100644 --- a/src/PJ_molodensky.c +++ b/src/PJ_molodensky.c @@ -90,6 +90,13 @@ static double RM (double a, double es, double phi) { E.J Krakiwsky & D.B. Thomson, 1974, GEODETIC POSITION COMPUTATIONS, + + Fredericton NB, Canada: + University of New Brunswick, + Department of Geodesy and Geomatics Engineering, + Lecture Notes No. 39, + 99 pp. + http://www2.unb.ca/gge/Pubs/LN39.pdf **********************************************************/ @@ -228,10 +235,9 @@ static XYZ forward_3d(LPZ lpz, PJ *P) { } -static PJ_OBS forward_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.xyz = forward_3d(obs.coo.lpz, P); - return point; +static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) { + obs.xyz = forward_3d(obs.lpz, P); + return obs; } @@ -256,21 +262,20 @@ static LPZ reverse_3d(XYZ xyz, PJ *P) { } -static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.lpz = reverse_3d(obs.coo.xyz, P); - return point; +static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) { + obs.lpz = reverse_3d(obs.xyz, P); + return obs; } -PJ *PROJECTION(molodensky) { +PJ *TRANSFORMATION(molodensky,1) { struct pj_opaque_molodensky *Q = pj_calloc(1, sizeof(struct pj_opaque_molodensky)); if (0==Q) return pj_default_destructor(P, ENOMEM); P->opaque = (void *) Q; - P->fwdobs = forward_obs; - P->invobs = reverse_obs; + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; P->fwd3d = forward_3d; P->inv3d = reverse_3d; P->fwd = forward_2d; @@ -307,81 +312,3 @@ PJ *PROJECTION(molodensky) { return P; } - -#ifndef PJ_SELFTEST -int pj_molodensky_selftest (void) {return 0;} -#else -int pj_molodensky_selftest (void) { - - PJ_OBS in, res, exp; - PJ *P; - - /* Test the abridged Molodensky first. Example from appendix 3 of Deakin (2004). */ - P = proj_create(PJ_DEFAULT_CTX, - "+proj=molodensky +a=6378160 +rf=298.25 " - "+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 " - "+abridged " - ); - if (0==P) - return 10; - - in.coo.lpz.lam = PJ_TORAD(144.9667); - in.coo.lpz.phi = PJ_TORAD(-37.8); - in.coo.lpz.z = 50.0; - - exp.coo.lpz.lam = PJ_TORAD(144.968); - exp.coo.lpz.phi = PJ_TORAD(-37.79848); - exp.coo.lpz.z = 46.378; - - res = proj_trans_obs(P, PJ_FWD, in); - - if (proj_lp_dist(P, res.coo.lp, exp.coo.lp) > 2 ) { /* we don't expect much accurecy here... */ - proj_destroy(P); - return 11; - } - - /* let's try a roundtrip */ - if (proj_roundtrip(P, PJ_FWD, 100, in.coo) > 1) { - proj_destroy(P); - return 12; - } - - if (res.coo.lpz.z - exp.coo.lpz.z > 1e-3) { - proj_destroy(P); - return 13; - } - - proj_destroy(P); - - /* Test the abridged Molodensky first. Example from appendix 3 of Deaking (2004). */ - - P = proj_create(PJ_DEFAULT_CTX, - "+proj=molodensky +a=6378160 +rf=298.25 " - "+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 " - ); - if (0==P) - return 20; - - res = proj_trans_obs(P, PJ_FWD, in); - - if (proj_lp_dist(P, res.coo.lp, exp.coo.lp) > 2 ) { /* we don't expect much accurecy here... */ - proj_destroy(P); - return 21; - } - - /* let's try a roundtrip */ - if (proj_roundtrip(P, PJ_FWD, 100, in.coo) > 1) { - proj_destroy(P); - return 22; - } - - if (res.coo.lpz.z - exp.coo.lpz.z > 1e-3) { - proj_destroy(P); - return 23; - } - - proj_destroy(P); - return 0; -} - -#endif diff --git a/src/PJ_natearth.c b/src/PJ_natearth.c index 9c40f3da..10abb23c 100644 --- a/src/PJ_natearth.c +++ b/src/PJ_natearth.c @@ -96,46 +96,3 @@ PJ *PROJECTION(natearth) { return P; } -#ifndef PJ_SELFTEST -int pj_natearth_selftest (void) {return 0;} -#else - -int pj_natearth_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=natearth +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 194507.265257889288, 112508.737358294515}, - { 194507.265257889288, -112508.737358294515}, - {-194507.265257889288, 112508.737358294515}, - {-194507.265257889288, -112508.737358294515}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00205638349586440223, 0.000888823913291242177}, - { 0.00205638349586440223, -0.000888823913291242177}, - {-0.00205638349586440223, 0.000888823913291242177}, - {-0.00205638349586440223, -0.000888823913291242177}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_natearth2.c b/src/PJ_natearth2.c index 95bb8646..dbdc8fed 100644 --- a/src/PJ_natearth2.c +++ b/src/PJ_natearth2.c @@ -93,46 +93,3 @@ PJ *PROJECTION(natearth2) { return P; } -#ifndef PJ_SELFTEST -int pj_natearth2_selftest (void) {return 0;} -#else - -int pj_natearth2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=natearth2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 189255.172934730799, 113022.495810907014}, - { 189255.172934730799, -113022.495810907014}, - {-189255.172934730799, 113022.495810907014}, - {-189255.172934730799, -113022.495810907014}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00211344929691056112, 0.000884779612080993237}, - { 0.00211344929691056112, -0.000884779612080993237}, - {-0.00211344929691056112, 0.000884779612080993237}, - {-0.00211344929691056112, -0.000884779612080993237}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_nell.c b/src/PJ_nell.c index ac071fc9..51f9f99a 100644 --- a/src/PJ_nell.c +++ b/src/PJ_nell.c @@ -47,46 +47,3 @@ PJ *PROJECTION(nell) { return P; } -#ifndef PJ_SELFTEST -int pj_nell_selftest (void) {return 0;} -#else - -int pj_nell_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=nell +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223385.132504695706, 111698.23644718733}, - { 223385.132504695706, -111698.23644718733}, - {-223385.132504695706, 111698.23644718733}, - {-223385.132504695706, -111698.23644718733}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049310989310567, 0.000895246554910125161}, - { 0.00179049310989310567, -0.000895246554910125161}, - {-0.00179049310989310567, 0.000895246554910125161}, - {-0.00179049310989310567, -0.000895246554910125161}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_nell_h.c b/src/PJ_nell_h.c index fe9a75c6..24957786 100644 --- a/src/PJ_nell_h.c +++ b/src/PJ_nell_h.c @@ -49,47 +49,3 @@ PJ *PROJECTION(nell_h) { return P; } - -#ifndef PJ_SELFTEST -int pj_nell_h_selftest (void) {return 0;} -#else - -int pj_nell_h_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=nell_h +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223385.131640952837, 111698.236533561678}, - { 223385.131640952837, -111698.236533561678}, - {-223385.131640952837, 111698.236533561678}, - {-223385.131640952837, -111698.236533561678}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049310989310567, 0.000895246554910125378}, - { 0.00179049310989310567, -0.000895246554910125378}, - {-0.00179049310989310567, 0.000895246554910125378}, - {-0.00179049310989310567, -0.000895246554910125378}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_nocol.c b/src/PJ_nocol.c index 934ba7ab..13688a9f 100644 --- a/src/PJ_nocol.c +++ b/src/PJ_nocol.c @@ -50,33 +50,3 @@ PJ *PROJECTION(nicol) { return P; } - -#ifndef PJ_SELFTEST -int pj_nicol_selftest (void) {return 0;} -#else - -int pj_nicol_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=nicol +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223374.561814139714, 111732.553988545071}, - { 223374.561814139714, -111732.553988545071}, - {-223374.561814139714, 111732.553988545071}, - {-223374.561814139714, -111732.553988545071}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_nsper.c b/src/PJ_nsper.c index 4975bb17..0b3a1d1b 100644 --- a/src/PJ_nsper.c +++ b/src/PJ_nsper.c @@ -3,6 +3,13 @@ #include <proj.h> #include "projects.h" +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; + struct pj_opaque { double height; double sinph0; @@ -16,7 +23,7 @@ struct pj_opaque { double sg; double sw; double cw; - int mode; + enum Mode mode; int tilt; }; @@ -24,10 +31,6 @@ PROJ_HEAD(nsper, "Near-sided perspective") "\n\tAzi, Sph\n\th="; PROJ_HEAD(tpers, "Tilted perspective") "\n\tAzi, Sph\n\ttilt= azi= h="; # define EPS10 1.e-10 -# define N_POLE 0 -# define S_POLE 1 -# define EQUIT 2 -# define OBLIQ 3 static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ @@ -192,92 +195,3 @@ PJ *PROJECTION(tpers) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_nsper_selftest (void) {return 0;} -#else - -int pj_nsper_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=nsper +a=6400000 +h=1000000"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 222239.816114099842, 111153.763991924759}, - { 222239.816114099842, -111153.763991924759}, - {-222239.816114099842, 111153.763991924759}, - {-222239.816114099842, -111153.763991924759}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049311728792437, 0.000895246558425396135}, - { 0.00179049311728792437, -0.000895246558425396135}, - {-0.00179049311728792437, 0.000895246558425396135}, - {-0.00179049311728792437, -0.000895246558425396135}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - -#ifndef PJ_SELFTEST -int pj_tpers_selftest (void) {return 0;} -#else - -int pj_tpers_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=tpers +a=6400000 +h=1000000 +azi=20"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 170820.288955531199, 180460.865555804776}, - { 246853.941538942483, -28439.8780357754222}, - {-246853.941538942483, 28439.8780357754222}, - {-170820.288955531199, -180460.865555804776} - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00198870552603137678, 0.000228871872278689991}, - { 0.00137632081376749859, -0.00145364129728205432}, - {-0.00137632081376749859, 0.00145364129728205432}, - {-0.00198870552603137678, -0.000228871872278689991}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_nzmg.c b/src/PJ_nzmg.c index b489e32f..2d65a6e1 100644 --- a/src/PJ_nzmg.c +++ b/src/PJ_nzmg.c @@ -118,47 +118,3 @@ PJ *PROJECTION(nzmg) { return P; } - -#ifndef PJ_SELFTEST -int pj_nzmg_selftest (void) {return 0;} -#else - -int pj_nzmg_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=nzmg +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {3352675144.74742508, -7043205391.10024357}, - {3691989502.77930641, -6729069415.33210468}, - {4099000768.45323849, -7863208779.66724873}, - {4466166927.36997604, -7502531736.62860489}, - }; - - XY inv_in[] = { - { 200000, 100000}, - { 200000,-100000}, - {-200000, 100000}, - {-200000,-100000} - }; - - LP e_inv_expect[] = { - {175.48208682711271, -69.4226921826331846}, - {175.756819472543611, -69.5335710883796168}, - {134.605119233460016, -61.4599957106629091}, - {134.333684315954827, -61.6215536756024349}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_ob_tran.c b/src/PJ_ob_tran.c index d35bb1b3..4ce4bd4d 100644 --- a/src/PJ_ob_tran.c +++ b/src/PJ_ob_tran.c @@ -86,10 +86,10 @@ static void *destructor(PJ *P, int errlev) { return 0; if (0==P->opaque) return pj_default_destructor (P, errlev); - + if (P->opaque->link) P->opaque->link->destructor (P->opaque->link, errlev); - + return pj_default_destructor(P, errlev); } @@ -135,7 +135,7 @@ static ARGS ob_tran_target_params (paralist *params) { args.argv = pj_calloc (argc - 1, sizeof (char *)); if (0==args.argv) return args; - + /* Copy all args *except* the proj=ob_tran arg to the argv array */ for (i = 0; params != 0; params = params->next) { if (0==strcmp (params->param, "proj=ob_tran")) @@ -228,82 +228,13 @@ PJ *PROJECTION(ob_tran) { if (fabs(phip) > TOL) { /* oblique */ Q->cphip = cos(phip); Q->sphip = sin(phip); - P->fwd = o_forward; + P->fwd = Q->link->fwd ? o_forward : 0; P->inv = Q->link->inv ? o_inverse : 0; } else { /* transverse */ - P->fwd = t_forward; + P->fwd = Q->link->fwd ? t_forward : 0; P->inv = Q->link->inv ? t_inverse : 0; } return P; } -#ifndef PJ_SELFTEST -int pj_ob_tran_selftest (void) {return 0;} -#else - -int pj_ob_tran_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - double d; - PJ *P; - PJ_COORD a, b; - - char s_args[] = {"+proj=ob_tran +R=6400000 +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {-2.6856872138416592, 1.2374302350496296}, - {-2.6954069748943286, 1.2026833954513816}, - {-2.8993663925401947, 1.2374302350496296}, - {-2.8896466314875244, 1.2026833954513816}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 121.5518748407577, -2.5361001573966084}, - { 63.261184340201858, 17.585319578673531}, - {-141.10073322351622, 26.091712304855108}, - {-65.862385598848391, 51.830295078417215}, - }; - - /* -- Tests from nad/testvarious -------------------------------------------- */ - P = proj_create (0, "+proj=ob_tran +o_proj=moll +R=6378137.0 +o_lon_p=0 +o_lat_p=0 +lon_0=180"); - if (0==P) - return 1; - - a = proj_coord (300000, 400000, 0, 0); - b.lpz.lam = -proj_torad (42 + (45 + 22.377/60)/60); - b.lpz.phi = proj_torad (85 + (35 + 28.083/60)/60); - a = proj_trans_coord (P, -1, a); - d = proj_lp_dist (P, a.lp, b.lp); - if (d > 1e-3) - return 2; - - a = proj_coord (proj_torad(10), proj_torad(20), 0, 0); - b = proj_coord (-1384841.18787, 7581707.88240, 0, 0); - a = proj_trans_coord (P, 1, a); - d = proj_xy_dist (a.xy, b.xy); - if (d > 1e-3) - return 3; - - proj_destroy (P); - /* -------------------------------------------------------------------------- */ - - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif
\ No newline at end of file diff --git a/src/PJ_ocea.c b/src/PJ_ocea.c index d3fe9fe7..33760180 100644 --- a/src/PJ_ocea.c +++ b/src/PJ_ocea.c @@ -96,47 +96,3 @@ PJ *PROJECTION(ocea) { return P; } - -#ifndef PJ_SELFTEST -int pj_ocea_selftest (void) {return 0;} -#else - -int pj_ocea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=ocea +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {19994423.837934087962, 223322.760576727800}, - {20217962.128015257418, 223322.760576729401}, - {19994423.837934091687, -223322.760576726549}, - {20217962.128015264869, -223322.760576724948}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 179.999104753445, 0.001790493110}, - {-179.999104753445, 0.001790493110}, - { 179.999104753445, -0.001790493110}, - {-179.999104753445, -0.001790493110}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_oea.c b/src/PJ_oea.c index 800a266e..58ea7e93 100644 --- a/src/PJ_oea.c +++ b/src/PJ_oea.c @@ -82,47 +82,3 @@ PJ *PROJECTION(oea) { return P; } - -#ifndef PJ_SELFTEST -int pj_oea_selftest (void) {return 0;} -#else - -int pj_oea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=oea +a=6400000 +lat_1=0.5 +lat_2=2 +n=1 +m=2 +theta=3"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 228926.872097864107, 99870.4884300760023}, - { 217242.584036940476, -123247.885607474513}, - {-217242.584036940476, 123247.885607474556}, - {-228926.872097864078, -99870.4884300760168}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017411857167771369, 0.000987726819566195693}, - { 0.00183489288577854998, -0.000800312481495174641}, - {-0.00183489288577854954, 0.000800312481495174966}, - {-0.00174118571677713712, -0.000987726819566195043}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c index f0b4b439..22f0daca 100644 --- a/src/PJ_omerc.c +++ b/src/PJ_omerc.c @@ -223,47 +223,3 @@ PJ *PROJECTION(omerc) { return P; } - -#ifndef PJ_SELFTEST -int pj_omerc_selftest (void) {return 0;} -#else - -int pj_omerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=omerc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222650.796885261341, 110642.229314983808}, - { 222650.796885261341, -110642.229314983808}, - {-222650.796885261545, 110642.229314983808}, - {-222650.796885261545, -110642.229314983808}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056816996357, 0.000904369474808157338}, - { 0.00179663056816996357, -0.000904369474820879583}, - {-0.0017966305681604536, 0.000904369474808157338}, - {-0.0017966305681604536, -0.000904369474820879583}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_ortho.c b/src/PJ_ortho.c index 3179189b..4da8247f 100644 --- a/src/PJ_ortho.c +++ b/src/PJ_ortho.c @@ -5,17 +5,20 @@ PROJ_HEAD(ortho, "Orthographic") "\n\tAzi, Sph."; +enum Mode { + N_POLE = 0, + S_POLE = 1, + EQUIT = 2, + OBLIQ = 3 +}; + struct pj_opaque { double sinph0; double cosph0; - int mode; + enum Mode mode; }; #define EPS10 1.e-10 -#define N_POLE 0 -#define S_POLE 1 -#define EQUIT 2 -#define OBLIQ 3 static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */ @@ -127,47 +130,3 @@ PJ *PROJECTION(ortho) { return P; } - -#ifndef PJ_SELFTEST -int pj_ortho_selftest (void) {return 0;} -#else - -int pj_ortho_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=ortho +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223322.76057672748, 111695.401198614476}, - { 223322.76057672748, -111695.401198614476}, - {-223322.76057672748, 111695.401198614476}, - {-223322.76057672748, -111695.401198614476}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931102938101, 0.000895246554928338998}, - { 0.0017904931102938101, -0.000895246554928338998}, - {-0.0017904931102938101, 0.000895246554928338998}, - {-0.0017904931102938101, -0.000895246554928338998}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_patterson.c b/src/PJ_patterson.c index 40b90010..0a1113ac 100644 --- a/src/PJ_patterson.c +++ b/src/PJ_patterson.c @@ -113,47 +113,3 @@ PJ *PROJECTION(patterson) { return P; } - -#ifndef PJ_SELFTEST -int pj_patterson_selftest (void) {return 0;} -#else - -int pj_patterson_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=patterson +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223402.144255274179, 113354.250397779804}, - {223402.144255274179, -113354.250397779804}, - {-223402.144255274179, 113354.250397779804}, - {-223402.144255274179, -113354.250397779804}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.00179049310978382265, 0.000882190140807953657}, - {0.00179049310978382265, -0.000882190140807953657}, - {-0.00179049310978382265, 0.000882190140807953657}, - {-0.00179049310978382265, -0.000882190140807953657}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_pipeline.c b/src/PJ_pipeline.c index 9352b4fd..e1568423 100644 --- a/src/PJ_pipeline.c +++ b/src/PJ_pipeline.c @@ -45,9 +45,10 @@ It is a very powerful concept, that increases the range of relevance of the proj.4 system substantially. It is, however, not a particularly intrusive - addition to the code base: The implementation is by and large completed by - adding an extra projection called "pipeline" (i.e. this file), which - handles all business. + addition to the PROJ.4 code base: The implementation is by and large completed + by adding an extra projection called "pipeline" (i.e. this file), which + handles all business, and a small amount of added functionality in the + pj_init code, implementing support for multilevel, embedded pipelines. Syntactically, the pipeline system introduces the "+step" keyword (which indicates the start of each transformation step), the "+omit_fwd" and @@ -63,10 +64,11 @@ Where <ARGS> indicate the Helmert arguments: 3 translations (+x=..., +y=..., +z=...), 3 rotations (+rx=..., +ry=..., +rz=...) and a scale factor (+s=...). - Following geodetic conventions, the rotations are given in Milliarcseconds, + Following geodetic conventions, the rotations are given in arcseconds, and the scale factor is given as parts-per-million. - [1] B. W. Kernighan & P. J. Plauger: Software tools. Addison-Wesley, 1976, 338 pp. + [1] B. W. Kernighan & P. J. Plauger: Software tools. + Reading, Massachusetts, Addison-Wesley, 1976, 338 pp. ******************************************************************************** @@ -96,8 +98,9 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20 ********************************************************************************/ #define PJ_LIB__ +#include <geodesic.h> #include "proj_internal.h" -#include <projects.h> +#include "projects.h" #include <assert.h> #include <stddef.h> @@ -105,24 +108,19 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20 PROJ_HEAD(pipeline, "Transformation pipeline manager"); /* Projection specific elements for the PJ object */ -#define PIPELINE_STACK_SIZE 100 struct pj_opaque { int reversible; int steps; - int depth; int verbose; - int *reverse_step; - int *omit_forward; - int *omit_inverse; char **argv; char **current_argv; - PJ_OBS stack[PIPELINE_STACK_SIZE]; PJ **pipeline; }; -static PJ_OBS pipeline_forward_obs (PJ_OBS, PJ *P); -static PJ_OBS pipeline_reverse_obs (PJ_OBS, PJ *P); + +static PJ_COORD pipeline_forward_4d (PJ_COORD, PJ *P); +static PJ_COORD pipeline_reverse_4d (PJ_COORD, PJ *P); static XYZ pipeline_forward_3d (LPZ lpz, PJ *P); static LPZ pipeline_reverse_3d (XYZ xyz, PJ *P); static XY pipeline_forward (LP lpz, PJ *P); @@ -156,10 +154,11 @@ static LP pipeline_reverse (XY xyz, PJ *P); The P->left and P->right elements indicate isomorphism. - For classic proj style projections, they both have the - value PJ_IO_UNITS_CLASSIC (default initialization), indicating - that the forward driver expects angular input coordinates, and - provides linear output coordinates. + For classic proj style projections, P->left has the value + PJ_IO_UNITS_RADIANS, while P->right has the value + PJ_IO_UNITS_CLASSIC, indicating that the forward driver expects + angular input coordinates, and provides linear output coordinates, + scaled by the P->a semimajor axis length. Newer projections may set P->left and P->right to either PJ_IO_UNITS_METERS, PJ_IO_UNITS_RADIANS or PJ_IO_UNITS_ANY, @@ -176,88 +175,61 @@ static LP pipeline_reverse (XY xyz, PJ *P); -static PJ_OBS pipeline_forward_obs (PJ_OBS point, PJ *P) { +static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) { int i, first_step, last_step; first_step = 1; last_step = P->opaque->steps + 1; - for (i = first_step; i != last_step; i++) { - proj_log_trace (P, "In[%2.2d]: %20.15g %20.15g %20.15g - %20.20s", - i-first_step, point.coo.xyz.x, point.coo.xyz.y, point.coo.xyz.z, - P->opaque->pipeline[i]->descr - ); - - if (P->opaque->omit_forward[i]) - continue; - if (P->opaque->reverse_step[i]) - point = proj_trans_obs (P->opaque->pipeline[i], PJ_INV, point); - else - point = proj_trans_obs (P->opaque->pipeline[i], PJ_FWD, point); - if (P->opaque->depth < PIPELINE_STACK_SIZE) - P->opaque->stack[P->opaque->depth++] = point; - } - proj_log_trace (P, "Out[ ]: %20.15g %20.15g %20.15g", point.coo.xyz.x, point.coo.xyz.y, point.coo.xyz.z); + for (i = first_step; i != last_step; i++) + point = proj_trans (P->opaque->pipeline[i], 1, point); - P->opaque->depth = 0; /* Clear the stack */ return point; } -static PJ_OBS pipeline_reverse_obs (PJ_OBS point, PJ *P) { + +static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) { int i, first_step, last_step; first_step = P->opaque->steps; last_step = 0; - for (i = first_step; i != last_step; i--) { - proj_log_trace (P, "In[%2.2d]: %20.15g %20.15g %20.15g - %.4f %.4f", - i - 1, point.coo.xyz.x, point.coo.xyz.y, point.coo.xyz.z, - P->opaque->pipeline[i]->a, P->opaque->pipeline[i]->rf - ); - if (P->opaque->omit_inverse[i]) - continue; - if (P->opaque->reverse_step[i]) - point = proj_trans_obs (P->opaque->pipeline[i], PJ_FWD, point); - else - point = proj_trans_obs (P->opaque->pipeline[i], PJ_INV, point); - if (P->opaque->depth < PIPELINE_STACK_SIZE) - P->opaque->stack[P->opaque->depth++] = point; - } - proj_log_trace (P, "Out[ ]: %20.15g %20.15g %20.15g", point.coo.xyz.x, point.coo.xyz.y, point.coo.xyz.z); - P->opaque->depth = 0; /* Clear the stack */ + for (i = first_step; i != last_step; i--) + point = proj_trans (P->opaque->pipeline[i], -1, point); + return point; } -/* Delegate the work to pipeline_forward_obs() */ +/* Delegate the work to pipeline_forward_4d() */ static XYZ pipeline_forward_3d (LPZ lpz, PJ *P) { - PJ_OBS point = proj_obs_null; - point.coo.lpz = lpz; - point = pipeline_forward_obs (point, P); - return point.coo.xyz; + PJ_COORD point = {{0,0,0,0}}; + point.lpz = lpz; + point = pipeline_forward_4d (point, P); + return point.xyz; } -/* Delegate the work to pipeline_reverse_obs() */ +/* Delegate the work to pipeline_reverse_4d() */ static LPZ pipeline_reverse_3d (XYZ xyz, PJ *P) { - PJ_OBS point = proj_obs_null; - point.coo.xyz = xyz; - point = pipeline_reverse_obs (point, P); - return point.coo.lpz; + PJ_COORD point = {{0,0,0,0}}; + point.xyz = xyz; + point = pipeline_reverse_4d (point, P); + return point.lpz; } static XY pipeline_forward (LP lp, PJ *P) { - PJ_OBS point = proj_obs_null; - point.coo.lp = lp; - point = pipeline_forward_obs (point, P); - return point.coo.xy; + PJ_COORD point = {{0,0,0,0}}; + point.lp = lp; + point = pipeline_forward_4d (point, P); + return point.xy; } static LP pipeline_reverse (XY xy, PJ *P) { - PJ_OBS point = proj_obs_null; - point.coo.xy = xy; - point = pipeline_reverse_obs (point, P); - return point.coo.lp; + PJ_COORD point = {{0,0,0,0}}; + point.xy = xy; + point = pipeline_reverse_4d (point, P); + return point.lp; } @@ -269,15 +241,15 @@ static void *destructor (PJ *P, int errlev) { if (0==P->opaque) return pj_default_destructor (P, errlev); - for (i = 0; i < P->opaque->steps; i++) - pj_default_destructor (P->opaque->pipeline[i+1], errlev); + /* Deallocate each pipeine step, then pipeline array */ + if (0!=P->opaque->pipeline) + for (i = 0; i < P->opaque->steps; i++) + if (0!=P->opaque->pipeline[i+1]) + P->opaque->pipeline[i+1]->destructor (P->opaque->pipeline[i+1], errlev); + pj_dealloc (P->opaque->pipeline); - pj_dealloc (P->opaque->reverse_step); - pj_dealloc (P->opaque->omit_forward); - pj_dealloc (P->opaque->omit_inverse); pj_dealloc (P->opaque->argv); pj_dealloc (P->opaque->current_argv); - pj_dealloc (P->opaque->pipeline); return pj_default_destructor(P, errlev); } @@ -292,18 +264,6 @@ static PJ *pj_create_pipeline (PJ *P, size_t steps) { P->opaque->steps = (int)steps; - P->opaque->reverse_step = pj_calloc (steps + 2, sizeof(int)); - if (0==P->opaque->reverse_step) - return 0; - - P->opaque->omit_forward = pj_calloc (steps + 2, sizeof(int)); - if (0==P->opaque->omit_forward) - return 0; - - P->opaque->omit_inverse = pj_calloc (steps + 2, sizeof(int)); - if (0==P->opaque->omit_inverse) - return 0; - return P; } @@ -332,14 +292,51 @@ static char **argv_params (paralist *params, size_t argc) { return argv; } +/* Being the special operator that the pipeline is, we have to handle the */ +/* ellipsoid differently than usual. In general, the pipeline operation does */ +/* not need an ellipsoid, but in some cases it is beneficial nonetheless. */ +/* Unfortunately we can't use the normal ellipsoid setter in pj_init, since */ +/* it adds a +ellps parameter to the global args if nothing else is specified*/ +/* This is problematic since that ellipsoid spec is then passed on to the */ +/* pipeline children. This is rarely what we want, so here we implement our */ +/* own logic instead. If an ellipsoid is set in the global args, it is used */ +/* as the pipeline ellipsoid. Otherwise we use WGS84 parameters as default. */ +/* At last we calculate the rest of the ellipsoid parameters and */ +/* re-initialize P->geod. */ +static void set_ellipsoid(PJ *P) { + paralist *cur, *attachment; + + /* Break the linked list after the global args */ + attachment = 0; + for (cur = P->params; cur != 0; cur = cur->next) + if (strcmp("step", cur->next->param) == 0) { + attachment = cur->next; + cur->next = 0; + break; + } + + /* Check if there's any ellipsoid specification in the global params. */ + /* If not, use WGS84 as default */ + if (pj_ell_set(P->ctx, P->params, &P->a, &P->es)) { + P->a = 6378137.0; + P->es = .00669438002290341575; + } + + pj_calc_ellps_params(P, P->a, P->es); + geod_init(P->geod, P->a, (1 - sqrt (1 - P->es))); + + /* Re-attach the dangling list */ + cur->next = attachment; +} + -PJ *PROJECTION(pipeline) { +PJ *OPERATION(pipeline,0) { int i, nsteps = 0, argc; int i_pipeline = -1, i_first_step = -1, i_current_step; char **argv, **current_argv; - P->fwdobs = pipeline_forward_obs; - P->invobs = pipeline_reverse_obs; + P->fwd4d = pipeline_forward_4d; + P->inv4d = pipeline_reverse_4d; P->fwd3d = pipeline_forward_3d; P->inv3d = pipeline_reverse_3d; P->fwd = pipeline_forward; @@ -374,7 +371,7 @@ PJ *PROJECTION(pipeline) { if (0==strcmp ("proj=pipeline", argv[i])) { if (-1 != i_pipeline) { - proj_log_error (P, "Pipeline: Nesting invalid"); + proj_log_error (P, "Pipeline: Nesting only allowed when child pipelines are wrapped in +init's"); return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: nested pipelines */ } i_pipeline = i; @@ -393,6 +390,8 @@ PJ *PROJECTION(pipeline) { if (0==pj_create_pipeline (P, nsteps)) return destructor (P, ENOMEM); + set_ellipsoid(P); + /* Now loop over all steps, building a new set of arguments for each init */ for (i_current_step = i_first_step, i = 0; i < nsteps; i++) { int j; @@ -412,209 +411,36 @@ PJ *PROJECTION(pipeline) { for (j = i_pipeline + 1; 0 != strcmp ("step", argv[j]); j++) current_argv[current_argc++] = argv[j]; - /* Finally handle non-symmetric steps and inverted steps */ - for (j = 0; j < current_argc; j++) { - if (0==strcmp("omit_inv", current_argv[j])) { - P->opaque->omit_inverse[i+1] = 1; - P->opaque->omit_forward[i+1] = 0; - } - if (0==strcmp("omit_fwd", current_argv[j])) { - P->opaque->omit_inverse[i+1] = 0; - P->opaque->omit_forward[i+1] = 1; - } - if (0==strcmp("inv", current_argv[j])) - P->opaque->reverse_step[i+1] = 1; - } - proj_log_trace (P, "Pipeline: init - %s, %d", current_argv[0], current_argc); for (j = 1; j < current_argc; j++) proj_log_trace (P, " %s", current_argv[j]); - next_step = pj_init (current_argc, current_argv); + next_step = pj_init_ctx (P->ctx, current_argc, current_argv); + proj_log_trace (P, "Pipeline: Step %d at %p", i, next_step); if (0==next_step) { proj_log_error (P, "Pipeline: Bad step definition: %s", current_argv[0]); return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: bad pipeline def */ } + + /* Is this step inverted? */ + for (j = 0; j < current_argc; j++) + if (0==strcmp("inv", current_argv[j])) + next_step->inverted = 1; + P->opaque->pipeline[i+1] = next_step; + proj_log_trace (P, "Pipeline: step done"); } proj_log_trace (P, "Pipeline: %d steps built. Determining i/o characteristics", nsteps); /* Determine forward input (= reverse output) data type */ - - /* First locate the first forward-active pipeline step */ - for (i = 0; i < nsteps; i++) - if (0==P->opaque->omit_forward[i+1]) - break; - if (i==nsteps) { - proj_log_error (P, "Pipeline: No forward steps"); - return destructor (P, PJD_ERR_MALFORMED_PIPELINE); - } - - if (P->opaque->reverse_step[i + 1]) - P->left = P->opaque->pipeline[i + 1]->right; - else - P->left = P->opaque->pipeline[i + 1]->left; - - if (P->left==PJ_IO_UNITS_CLASSIC) { - if (P->opaque->reverse_step[i + 1]) - P->left = PJ_IO_UNITS_METERS; - else - P->left = PJ_IO_UNITS_RADIANS; - } + P->left = pj_left (P->opaque->pipeline[1]); /* Now, correspondingly determine forward output (= reverse input) data type */ - - /* First locate the last reverse-active pipeline step */ - for (i = nsteps - 1; i >= 0; i--) - if (0==P->opaque->omit_inverse[i+1]) - break; - if (i==-1) { - proj_log_error (P, "Pipeline: No reverse steps"); - return destructor (P, PJD_ERR_MALFORMED_PIPELINE); - } - - if (P->opaque->reverse_step[i + 1]) - P->right = P->opaque->pipeline[i + 1]->left; - else - P->right = P->opaque->pipeline[i + 1]->right; - - if (P->right==PJ_IO_UNITS_CLASSIC) { - if (P->opaque->reverse_step[i + 1]) - P->right = PJ_IO_UNITS_RADIANS; - else - P->right = PJ_IO_UNITS_METERS; - } - proj_log_trace (P, "Pipeline: Units - left: [%s], right: [%s]\n", - P->left ==PJ_IO_UNITS_RADIANS? "angular": "linear", - P->right==PJ_IO_UNITS_RADIANS? "angular": "linear"); + P->right = pj_right (P->opaque->pipeline[nsteps]); return P; } -#ifndef PJ_SELFTEST -/* selftest stub */ -int pj_pipeline_selftest (void) {return 0;} -#else - -int pj_pipeline_selftest (void) { - PJ *P; - PJ_OBS a, b; - XY cph_utm32 = {691875.63214, 6098907.82501}; - double dist; - - /* forward-reverse geo->utm->geo */ - P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +step +proj=utm +ellps=GRS80 +inv"); - if (0==P) - return 1000; - /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 0) */ - a = b = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(12); - a.coo.lpz.phi = PJ_TORAD(55); - a.coo.lpz.z = 0; - - /* Forward projection */ - b = proj_trans_obs (P, PJ_FWD, a); - if (proj_lp_dist (P, a.coo.lp, b.coo.lp) > 1e-4) - return 1001; - - /* Inverse projection (still same result: pipeline is symmetrical) */ - a = proj_trans_obs (P, PJ_INV, b); - if (proj_lp_dist (P, a.coo.lp, b.coo.lp) > 1e-4) - return 1002; - - proj_destroy (P); - - /* And now the back-to-back situation utm->geo->utm */ - P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +inv +step +proj=utm +ellps=GRS80"); - if (0==P) - return 2000; - - /* zero initialize everything, then set (easting, northing) to utm(12, 55) */ - a = b = proj_obs_null; - a.coo.xy = cph_utm32; - - /* Forward projection */ - b = proj_trans_obs (P, PJ_FWD, a); - if (proj_xy_dist (a.coo.xy, b.coo.xy) > 1e-4) - return 2001; - - /* Inverse projection */ - a = proj_trans_obs (P, PJ_INV, b); - if (proj_xy_dist (a.coo.xy, b.coo.xy) > 1e-4) - return 2001; - if (proj_xyz_dist (a.coo.xyz, b.coo.xyz) > 1e-4) - return 2002; - - proj_destroy (P); - - - /* Finally testing a corner case: A rather pointless one-step pipeline geo->utm */ - P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 "); - if (0==P) - return 3000; - - - a = b = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(12); - a.coo.lpz.phi = PJ_TORAD(55); - - /* Forward projection */ - b = proj_trans_obs (P, PJ_FWD, a); - if (proj_xy_dist (cph_utm32, b.coo.xy) > 1e-4) - return 3001; - - /* Inverse projection */ - b = proj_trans_obs (P, PJ_INV, b); - if (proj_lp_dist (P, a.coo.lp, b.coo.lp) > 1e-4) - return 3002; - - - /* Since we use pj_lp_dist to determine success above, we should also test that it works */ - - /* Geodesic distance between two points with angular 2D coordinates */ - a.coo.lp.lam = PJ_TORAD(12); - a.coo.lp.phi = PJ_TORAD(60); - b.coo.lp.lam = PJ_TORAD(12); - b.coo.lp.phi = PJ_TORAD(61); - dist = proj_lp_dist (P, a.coo.lp, b.coo.lp); - if (fabs (111420.727870234 - dist) > 1e-4) - return 4001; - - a.coo.lp.lam = PJ_TORAD(12); - a.coo.lp.phi = PJ_TORAD(0.); - b.coo.lp.lam = PJ_TORAD(12); - b.coo.lp.phi = PJ_TORAD(1.); - dist = proj_lp_dist (P, a.coo.lp, b.coo.lp); - if (fabs (110574.388554153 - dist) > 1e-4) - return 4002; - - proj_destroy (P); - - /* test a pipeline with several +init steps */ - P = proj_create( - 0, - "+proj=pipeline " - "+step +init=epsg:25832 +inv " - "+step +init=epsg:25833 " - "+step +init=epsg:25833 +inv " - "+step +init=epsg:25832 " - ); - if (0==P) - return 5000; - - a.coo.xy.x = 700000.0; - a.coo.xy.y = 6000000.0; - - b = proj_trans_obs(P, PJ_FWD, a); - dist = proj_xy_dist(a.coo.xy, b.coo.xy); - if (dist > 1e-7) - return 5001; - - - proj_destroy (P); - return 0; -} -#endif diff --git a/src/PJ_poly.c b/src/PJ_poly.c index 209669c0..7a8fc44d 100644 --- a/src/PJ_poly.c +++ b/src/PJ_poly.c @@ -164,62 +164,3 @@ PJ *PROJECTION(poly) { return P; } - -#ifndef PJ_SELFTEST -int pj_poly_selftest (void) {return 0;} -#else - -int pj_poly_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=poly +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=poly +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222605.285770237475, 110642.194561440483}, - { 222605.285770237475, -110642.194561440483}, - {-222605.285770237475, 110642.194561440483}, - {-222605.285770237475, -110642.194561440483}, - }; - - XY s_fwd_expect[] = { - { 223368.105210218986, 111769.110491224754}, - { 223368.105210218986, -111769.110491224754}, - {-223368.105210218986, 111769.110491224754}, - {-223368.105210218986, -111769.110491224754}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00179663056846135222, 0.000904369476631838518}, - { 0.00179663056846135222, -0.000904369476631838518}, - {-0.00179663056846135222, 0.000904369476631838518}, - {-0.00179663056846135222, -0.000904369476631838518}, - }; - - LP s_inv_expect[] = { - { 0.0017904931100023887, 0.000895246554454779222}, - { 0.0017904931100023887, -0.000895246554454779222}, - {-0.0017904931100023887, 0.000895246554454779222}, - {-0.0017904931100023887, -0.000895246554454779222}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_putp2.c b/src/PJ_putp2.c index 83aa5f45..51cf263d 100644 --- a/src/PJ_putp2.c +++ b/src/PJ_putp2.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" PROJ_HEAD(putp2, "Putnins P2") "\n\tPCyl., Sph."; @@ -57,46 +57,3 @@ PJ *PROJECTION(putp2) { return P; } -#ifndef PJ_SELFTEST -int pj_putp2_selftest (void) {return 0;} -#else - -int pj_putp2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 211638.039634339279, 117895.033043379764}, - { 211638.039634339279, -117895.033043379764}, - {-211638.039634339279, 117895.033043379764}, - {-211638.039634339279, -117895.033043379764}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00188980221640386672, 0.000848201580276863377}, - { 0.00188980221640386672, -0.000848201580276863377}, - {-0.00188980221640386672, 0.000848201580276863377}, - {-0.00188980221640386672, -0.000848201580276863377}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_putp3.c b/src/PJ_putp3.c index cb216370..acc777bc 100644 --- a/src/PJ_putp3.c +++ b/src/PJ_putp3.c @@ -63,93 +63,3 @@ PJ *PROJECTION(putp3p) { return P; } - -#ifndef PJ_SELFTEST -int pj_putp3_selftest (void) {return 0;} -#else - -int pj_putp3_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp3 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 178227.115507793525, 89124.5607860879827}, - { 178227.115507793525, -89124.5607860879827}, - {-178227.115507793525, 89124.5607860879827}, - {-178227.115507793525, -89124.5607860879827}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00224405032986489889, 0.00112202516475805899}, - { 0.00224405032986489889, -0.00112202516475805899}, - {-0.00224405032986489889, 0.00112202516475805899}, - {-0.00224405032986489889, -0.00112202516475805899}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - -#ifndef PJ_SELFTEST -int pj_putp3p_selftest (void) {return 0;} -#else - -int pj_putp3p_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp3p +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 178238.118539984745, 89124.5607860879827}, - { 178238.118539984745, -89124.5607860879827}, - {-178238.118539984745, 89124.5607860879827}, - {-178238.118539984745, -89124.5607860879827}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00224405032969050844, 0.00112202516475805899}, - { 0.00224405032969050844, -0.00112202516475805899}, - {-0.00224405032969050844, 0.00112202516475805899}, - {-0.00224405032969050844, -0.00112202516475805899}, - - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_putp4p.c b/src/PJ_putp4p.c index 197f24c4..958f9681 100644 --- a/src/PJ_putp4p.c +++ b/src/PJ_putp4p.c @@ -1,6 +1,6 @@ #define PJ_LIB__ #include <errno.h> -#include <projects.h> +#include "projects.h" struct pj_opaque { double C_x, C_y; @@ -70,92 +70,3 @@ PJ *PROJECTION(weren) { return P; } - -#ifndef PJ_SELFTEST -int pj_putp4p_selftest (void) {return 0;} -#else - -int pj_putp4p_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp4p +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 195241.47734938623, 127796.782307926231}, - { 195241.47734938623, -127796.782307926231}, - {-195241.47734938623, 127796.782307926231}, - {-195241.47734938623, -127796.782307926231}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00204852830860296001, 0.000782480174932193733}, - { 0.00204852830860296001, -0.000782480174932193733}, - {-0.00204852830860296001, 0.000782480174932193733}, - {-0.00204852830860296001, -0.000782480174932193733}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif - - -#ifndef PJ_SELFTEST -int pj_weren_selftest (void) {return 0;} -#else - -int pj_weren_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=weren +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223378.515757633519, 146214.093042288267}, - { 223378.515757633519, -146214.093042288267}, - {-223378.515757633519, 146214.093042288267}, - {-223378.515757633519, -146214.093042288267}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00179049310987240413, 0.000683917989676492265}, - { 0.00179049310987240413, -0.000683917989676492265}, - {-0.00179049310987240413, 0.000683917989676492265}, - {-0.00179049310987240413, -0.000683917989676492265}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_putp5.c b/src/PJ_putp5.c index f8b431b1..14bfea23 100644 --- a/src/PJ_putp5.c +++ b/src/PJ_putp5.c @@ -69,89 +69,3 @@ PJ *PROJECTION(putp5p) { return P; } -#ifndef PJ_SELFTEST -int pj_putp5_selftest (void) {return 0;} -#else - -int pj_putp5_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp5 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 226367.21338056153, 113204.56855847509}, - { 226367.21338056153, -113204.56855847509}, - {-226367.21338056153, 113204.56855847509}, - {-226367.21338056153, -113204.56855847509}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00176671315102969553, 0.000883356575387199546}, - { 0.00176671315102969553, -0.000883356575387199546}, - {-0.00176671315102969553, 0.000883356575387199546}, - {-0.00176671315102969553, -0.000883356575387199546}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_putp5p_selftest (void) {return 0;} -#else - -int pj_putp5p_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp5p +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 226388.175248755841, 113204.56855847509}, - { 226388.175248755841, -113204.56855847509}, - {-226388.175248755841, 113204.56855847509}, - {-226388.175248755841, -113204.56855847509}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00176671315090204742, 0.000883356575387199546}, - { 0.00176671315090204742, -0.000883356575387199546}, - {-0.00176671315090204742, 0.000883356575387199546}, - {-0.00176671315090204742, -0.000883356575387199546}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif diff --git a/src/PJ_putp6.c b/src/PJ_putp6.c index 50859f14..8c4efa66 100644 --- a/src/PJ_putp6.c +++ b/src/PJ_putp6.c @@ -91,90 +91,3 @@ PJ *PROJECTION(putp6p) { return P; } - -#ifndef PJ_SELFTEST -int pj_putp6_selftest (void) {return 0;} -#else - -int pj_putp6_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp6 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 226369.395133402577, 110218.523796520662}, - { 226369.395133402577, -110218.523796520749}, - {-226369.395133402577, 110218.523796520662}, - {-226369.395133402577, -110218.523796520749}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00176671315102969921, 0.000907295534210503544}, - { 0.00176671315102969921, -0.000907295534205924308}, - {-0.00176671315102969921, 0.000907295534210503544}, - {-0.00176671315102969921, -0.000907295534205924308}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif - - -#ifndef PJ_SELFTEST -int pj_putp6p_selftest (void) {return 0;} -#else - -int pj_putp6p_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=putp6p +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 198034.195132195076, 125989.475461323193}, - { 198034.195132195076, -125989.475461323193}, - {-198034.195132195076, 125989.475461323193}, - {-198034.195132195076, -125989.475461323193}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.00201955053120177067, 0.000793716441164738612}, - { 0.00201955053120177067, -0.000793716441164738612}, - {-0.00201955053120177067, 0.000793716441164738612}, - {-0.00201955053120177067, -0.000793716441164738612}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - -#endif diff --git a/src/PJ_qsc.c b/src/PJ_qsc.c index f8c760a9..36dabeb9 100644 --- a/src/PJ_qsc.c +++ b/src/PJ_qsc.c @@ -42,8 +42,18 @@ #include <errno.h> #include "projects.h" +/* The six cube faces. */ +enum Face { + FACE_FRONT = 0, + FACE_RIGHT = 1, + FACE_BACK = 2, + FACE_LEFT = 3, + FACE_TOP = 4, + FACE_BOTTOM = 5 +}; + struct pj_opaque { - int face; + enum Face face; double a_squared; double b; double one_minus_f; @@ -53,24 +63,18 @@ PROJ_HEAD(qsc, "Quadrilateralized Spherical Cube") "\n\tAzi, Sph."; #define EPS10 1.e-10 -/* The six cube faces. */ -#define FACE_FRONT 0 -#define FACE_RIGHT 1 -#define FACE_BACK 2 -#define FACE_LEFT 3 -#define FACE_TOP 4 -#define FACE_BOTTOM 5 - /* The four areas on a cube face. AREA_0 is the area of definition, * the other three areas are counted counterclockwise. */ -#define AREA_0 0 -#define AREA_1 1 -#define AREA_2 2 -#define AREA_3 3 +enum Area { + AREA_0 = 0, + AREA_1 = 1, + AREA_2 = 2, + AREA_3 = 3 +}; /* Helper function for forward projection: compute the theta angle * and determine the area number. */ -static double qsc_fwd_equat_face_theta(double phi, double y, double x, int *area) { +static double qsc_fwd_equat_face_theta(double phi, double y, double x, enum Area *area) { double theta; if (phi < EPS10) { *area = AREA_0; @@ -111,7 +115,7 @@ static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */ double lat, lon; double theta, phi; double t, mu; /* nu; */ - int area; + enum Area area; /* Convert the geodetic latitude to a geocentric latitude. * This corresponds to the shift from the ellipsoid to the sphere @@ -394,62 +398,3 @@ PJ *PROJECTION(qsc) { return P; } - -#ifndef PJ_SELFTEST -int pj_qsc_selftest (void) {return 0;} -#else - -int pj_qsc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=qsc +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=qsc +R=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 304638.450843852363, 164123.870923793991}, - { 304638.450843852363, -164123.870923793991}, - {-304638.450843852363, 164123.870923793962}, - {-304638.450843852421, -164123.870923793904}, - }; - - XY s_fwd_expect[] = { - { 305863.792402890511, 165827.722754715243}, - { 305863.792402890511, -165827.722754715243}, - {-305863.792402890511, 165827.722754715243}, - {-305863.792402890569, -165827.722754715156}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.00132134098471627126, 0.000610652900922527926}, - { 0.00132134098471627126, -0.000610652900922527926}, - {-0.00132134098471627126, 0.000610652900922527926}, - {-0.00132134098471627126, -0.000610652900922527926}, - }; - - LP s_inv_expect[] = { - { 0.00131682718763827234, 0.000604493198178676161}, - { 0.00131682718763827234, -0.000604493198178676161}, - {-0.00131682718763827234, 0.000604493198178676161}, - {-0.00131682718763827234, -0.000604493198178676161}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_robin.c b/src/PJ_robin.c index d3f92cd9..7532ff71 100644 --- a/src/PJ_robin.c +++ b/src/PJ_robin.c @@ -154,46 +154,3 @@ PJ *PROJECTION(robin) { } -#ifndef PJ_SELFTEST -int pj_robin_selftest (void) {return 0;} -#else - -int pj_robin_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=robin +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 189588.423282507836, 107318.530350702888}, - { 189588.423282507836, -107318.530350702888}, - {-189588.423282507836, 107318.530350702888}, - {-189588.423282507836, -107318.530350702888}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.002109689065506131, 0.000931805533547745983}, - { 0.002109689065506131, -0.000931805533547745983}, - {-0.002109689065506131, 0.000931805533547745983}, - {-0.002109689065506131, -0.000931805533547745983}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_rpoly.c b/src/PJ_rpoly.c index 8f7b16c6..d7241719 100644 --- a/src/PJ_rpoly.c +++ b/src/PJ_rpoly.c @@ -1,6 +1,6 @@ #define PJ_LIB__ #include <errno.h> -#include <projects.h> +#include "projects.h" struct pj_opaque { double phi1; @@ -52,33 +52,3 @@ PJ *PROJECTION(rpoly) { return P; } - -#ifndef PJ_SELFTEST -int pj_rpoly_selftest (void) {return 0;} -#else - -int pj_rpoly_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=rpoly +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223368.09830201423, 111769.110486991223}, - { 223368.09830201423, -111769.110486991223}, - {-223368.09830201423, 111769.110486991223}, - {-223368.09830201423, -111769.110486991223}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_sch.c b/src/PJ_sch.c index dc8cc770..c404fc9a 100644 --- a/src/PJ_sch.c +++ b/src/PJ_sch.c @@ -1,6 +1,4 @@ /****************************************************************************** - * $Id$ - * * Project: SCH Coordinate system * Purpose: Implementation of SCH Coordinate system * References : @@ -228,7 +226,3 @@ PJ *PROJECTION(sch) { return setup(P); } -/* Skipping sef-test since the test system is not capable of handling - * 3D coordinate systems for the time being. Relying on tests in ../nad/ - */ -int pj_sch_selftest (void) {return 0;} diff --git a/src/PJ_sconics.c b/src/PJ_sconics.c index 7f6e094c..93a2f2f4 100644 --- a/src/PJ_sconics.c +++ b/src/PJ_sconics.c @@ -4,23 +4,26 @@ #include "projects.h" +enum Type { + EULER = 0, + MURD1 = 1, + MURD2 = 2, + MURD3 = 3, + PCONIC = 4, + TISSOT = 5, + VITK1 = 6 +}; + struct pj_opaque { double n; double rho_c; double rho_0; double sig; double c1, c2; - int type; + enum Type type; }; -#define EULER 0 -#define MURD1 1 -#define MURD2 2 -#define MURD3 3 -#define PCONIC 4 -#define TISSOT 5 -#define VITK1 6 #define EPS10 1.e-10 #define EPS 1e-10 #define LINE2 "\n\tConic, Sph\n\tlat_1= and lat_2=" @@ -106,7 +109,7 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse } -static PJ *setup(PJ *P, int type) { +static PJ *setup(PJ *P, enum Type type) { double del, cs; int err; struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); @@ -211,474 +214,3 @@ PJ *PROJECTION(vitk1) { return setup(P, VITK1); } - -#ifndef PJ_SELFTEST -int pj_euler_selftest (void) {return 0;} -#else - -int pj_euler_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=euler +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=euler +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222597.63465910763, 111404.24054991946}, - {222767.16563187627, -111234.6764910177}, - {-222597.63465910763, 111404.24054991946}, - {-222767.16563187627, -111234.6764910177}, - }; - - XY s_fwd_expect[] = { - {223360.65559869423, 111786.11238979101}, - {223530.76769031584, -111615.96709862351}, - {-223360.65559869423, 111786.11238979101}, - {-223530.76769031584, -111615.96709862351}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017962807023075235, 0.0008983146697688839}, - {0.0017962794738334226, -0.00089831589842987965}, - {-0.0017962807023075235, 0.0008983146697688839}, - {-0.0017962794738334226, -0.00089831589842987965}, - }; - - LP s_inv_expect[] = { - {0.0017901444369360026, 0.00089524594522202015}, - {0.001790143216840731, -0.00089524716533368484}, - {-0.0017901444369360026, 0.00089524594522202015}, - {-0.001790143216840731, -0.00089524716533368484}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - -#ifndef PJ_SELFTEST -int pj_murd1_selftest (void) {return 0;} -#else - -int pj_murd1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=murd1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=murd1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222600.81347355421, 111404.24418054636}, - {222770.3492878644, -111234.6728566746}, - {-222600.81347355421, 111404.24418054636}, - {-222770.3492878644, -111234.6728566746}, - }; - - XY s_fwd_expect[] = { - {223363.84530949194, 111786.11603286299}, - {223533.96225925098, -111615.96345182261}, - {-223363.84530949194, 111786.11603286299}, - {-223533.96225925098, -111615.96345182261}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017962550410516366, 0.0008983146697688839}, - {0.0017962538125775522, -0.00089831589842987965}, - {-0.0017962550410516366, 0.0008983146697688839}, - {-0.0017962538125775522, -0.00089831589842987965}, - }; - - LP s_inv_expect[] = { - {0.0017901188633413715, 0.00089524594522202015}, - {0.0017901176432461162, -0.00089524716492657387}, - {-0.0017901188633413715, 0.00089524594522202015}, - {-0.0017901176432461162, -0.00089524716492657387}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - - - - - - - - - -#ifndef PJ_SELFTEST -int pj_murd2_selftest (void) {return 0;} -#else - -int pj_murd2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=murd2 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=murd2 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222588.09975123021, 111426.14002741246}, - {222757.72626701824, -111341.43131750476}, - {-222588.09975123021, 111426.14002741246}, - {-222757.72626701824, -111341.43131750476}, - }; - - XY s_fwd_expect[] = { - {223351.08800702673, 111808.08693438848}, - {223521.2959691704, -111723.08785967289}, - {-223351.08800702673, 111808.08693438848}, - {-223521.2959691704, -111723.08785967289}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017963574947305447, 0.00089788747830845382}, - {0.0017963562661689487, -0.00089788809264252983}, - {-0.0017963574947305447, 0.00089788747830845382}, - {-0.0017963562661689487, -0.00089788809264252983}, - }; - - LP s_inv_expect[] = { - {0.0017902209670287586, 0.00089482021163422854}, - {0.0017902197468465887, -0.00089482082161134206}, - {-0.0017902209670287586, 0.00089482021163422854}, - {-0.0017902197468465887, -0.00089482082161134206}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - - - - - -#ifndef PJ_SELFTEST -int pj_murd3_selftest (void) {return 0;} -#else - -int pj_murd3_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=murd3 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=murd3 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222600.81407757697, 111404.24660137216}, - {222770.35473389886, -111234.67043217793}, - {-222600.81407757697, 111404.24660137216}, - {-222770.35473389886, -111234.67043217793}, - }; - - XY s_fwd_expect[] = { - {223363.84591558515, 111786.11846198692}, - {223533.96772395336, -111615.96101901523}, - {-223363.84591558515, 111786.11846198692}, - {-223533.96772395336, -111615.96101901523}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017962550166583809, 0.0008983146697688839}, - {0.0017962537881492445, -0.00089831589842987965}, - {-0.0017962550166583809, 0.0008983146697688839}, - {-0.0017962537881492445, -0.00089831589842987965}, - }; - - LP s_inv_expect[] = { - {0.0017901188390313859, 0.00089524594522202015}, - {0.0017901176189013177, -0.00089524716533368484}, - {-0.0017901188390313859, 0.00089524594522202015}, - {-0.0017901176189013177, -0.00089524716533368484}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - - - - - - -#ifndef PJ_SELFTEST -int pj_pconic_selftest (void) {return 0;} -#else - -int pj_pconic_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=pconic +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=pconic +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222588.09884161691, 111416.60477006658}, - {222757.71809109033, -111331.88153107995}, - {-222588.09884161691, 111416.60477006658}, - {-222757.71809109033, -111331.88153107995}, - }; - - XY s_fwd_expect[] = { - {223351.08709429545, 111798.5189920546}, - {223521.28776521701, -111713.50533845725}, - {-223351.08709429545, 111798.5189920546}, - {-223521.28776521701, -111713.50533845725}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017963575313784969, 0.0008979644089172499}, - {0.0017963563027642206, -0.00089796502355327969}, - {-0.0017963575313784969, 0.0008979644089172499}, - {-0.0017963563027642206, -0.00089796502355327969}, - }; - - LP s_inv_expect[] = { - {0.0017902210035514285, 0.0008948968793741558}, - {0.0017902197833169374, -0.00089489748965381963}, - {-0.0017902210035514285, 0.0008948968793741558}, - {-0.0017902197833169374, -0.00089489748965381963}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - - - - - - - - - - -#ifndef PJ_SELFTEST -int pj_tissot_selftest (void) {return 0;} -#else - -int pj_tissot_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=tissot +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=tissot +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222641.07869963095, 54347.828487281469}, - {222810.61451394114, -168291.08854993948}, - {-222641.07869963095, 54347.828487281469}, - {-222810.61451394114, -168291.08854993948}, - }; - - XY s_fwd_expect[] = { - {223404.24855684943, 54534.122161157939}, - {223574.36550660848, -168867.95732352766}, - {-223404.24855684943, 54534.122161157939}, - {-223574.36550660848, -168867.95732352766}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017962807107425871, 0.51344495513064536}, - {0.0017962794822333915, 0.51164832456244658}, - {-0.0017962807107425871, 0.51344495513064536}, - {-0.0017962794822333915, 0.51164832456244658}, - }; - - LP s_inv_expect[] = { - {0.0017901444453421915, 0.51344188640609856}, - {0.001790143225212064, 0.51165139329554277}, - {-0.0017901444453421915, 0.51344188640609856}, - {-0.001790143225212064, 0.51165139329554277}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - - - - -#ifndef PJ_SELFTEST -int pj_vitk1_selftest (void) {return 0;} -#else - -int pj_vitk1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=vitk1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=vitk1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222607.17121145778, 111404.25144243463}, - {222776.71670959776, -111234.66558744459}, - {-222607.17121145778, 111404.25144243463}, - {-222776.71670959776, -111234.66558744459}, - }; - - XY s_fwd_expect[] = { - {223370.22484047143, 111786.12331964359}, - {223540.3515072545, -111615.9561576751}, - {-223370.22484047143, 111786.12331964359}, - {-223540.3515072545, -111615.9561576751}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017962037198570686, 0.0008983146697688839}, - {0.0017962024913830157, -0.00089831589842987965}, - {-0.0017962037198570686, 0.0008983146697688839}, - {-0.0017962024913830157, -0.00089831589842987965}, - }; - - LP s_inv_expect[] = { - {0.0017900677174648159, 0.00089524594522202015}, - {0.0017900664973695916, -0.00089524716533368484}, - {-0.0017900677174648159, 0.00089524594522202015}, - {-0.0017900664973695916, -0.00089524716533368484}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_somerc.c b/src/PJ_somerc.c index 7324d48a..8222ca24 100644 --- a/src/PJ_somerc.c +++ b/src/PJ_somerc.c @@ -88,62 +88,3 @@ PJ *PROJECTION(somerc) { return P; } - -#ifndef PJ_SELFTEST -int pj_somerc_selftest (void) {return 0;} -#else - -int pj_somerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=somerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=somerc +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222638.98158654713, 110579.96521824898}, - {222638.98158654713, -110579.96521825089}, - {-222638.98158654713, 110579.96521824898}, - {-222638.98158654713, -110579.96521825089}, - }; - - XY s_fwd_expect[] = { - {223402.14425527418, 111706.74357494408}, - {223402.14425527418, -111706.74357494518}, - {-223402.14425527418, 111706.74357494408}, - {-223402.14425527418, -111706.74357494518}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966305682390426, 0.00090436947704129484}, - {0.0017966305682390426, -0.00090436947704377105}, - {-0.0017966305682390426, 0.00090436947704129484}, - {-0.0017966305682390426, -0.00090436947704377105}, - }; - - LP s_inv_expect[] = { - {0.0017904931097838226, 0.00089524655485801927}, - {0.0017904931097838226, -0.00089524655484529714}, - {-0.0017904931097838226, 0.00089524655485801927}, - {-0.0017904931097838226, -0.00089524655484529714}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_stere.c b/src/PJ_stere.c index 02b73507..c01b86f0 100644 --- a/src/PJ_stere.c +++ b/src/PJ_stere.c @@ -7,12 +7,19 @@ PROJ_HEAD(stere, "Stereographic") "\n\tAzi, Sph&Ell\n\tlat_ts="; PROJ_HEAD(ups, "Universal Polar Stereographic") "\n\tAzi, Sph&Ell\n\tsouth"; +enum Mode { + S_POLE = 0, + N_POLE = 1, + OBLIQ = 2, + EQUIT = 3 +}; + struct pj_opaque { double phits; double sinX1; double cosX1; double akm1; - int mode; + enum Mode mode; }; #define sinph0 P->opaque->sinX1 @@ -21,10 +28,6 @@ struct pj_opaque { #define TOL 1.e-8 #define NITER 8 #define CONV 1.e-10 -#define S_POLE 0 -#define N_POLE 1 -#define OBLIQ 2 -#define EQUIT 3 static double ssfn_ (double phit, double sinphi, double eccen) { sinphi *= eccen; @@ -310,110 +313,3 @@ PJ *PROJECTION(ups) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_stere_selftest (void) {return 0;} -#else - -int pj_stere_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=stere +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=stere +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222644.8545501172, 110610.8834741739}, - { 222644.8545501172, -110610.8834741739}, - {-222644.8545501172, 110610.8834741739}, - {-222644.8545501172, -110610.8834741739}, - }; - - XY s_fwd_expect[] = { - { 223407.81025950745, 111737.938996443}, - { 223407.81025950745, -111737.938996443}, - {-223407.81025950745, 111737.938996443}, - {-223407.81025950745, -111737.938996443}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305682022392, 0.00090436947502443507}, - { 0.0017966305682022392, -0.00090436947502443507}, - {-0.0017966305682022392, 0.00090436947502443507}, - {-0.0017966305682022392, -0.00090436947502443507}, - }; - - LP s_inv_expect[] = { - { 0.001790493109747395, 0.00089524655465513144}, - { 0.001790493109747395, -0.00089524655465513144}, - {-0.001790493109747395, 0.00089524655465513144}, - {-0.001790493109747395, -0.00089524655465513144}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif - - - - - -#ifndef PJ_SELFTEST -int pj_ups_selftest (void) {return 0;} -#else - -int pj_ups_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=ups +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {2433455.5634384668, -10412543.301512826}, - {2448749.1185681992, -10850493.419804076}, - {1566544.4365615332, -10412543.301512826}, - {1551250.8814318008, -10850493.419804076}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-44.998567498074834, 64.9182362867341}, - {-44.995702709112308, 64.917020250675748}, - {-45.004297076028529, 64.915804280954518}, - {-45.001432287066002, 64.914588377560719}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/PJ_sterea.c b/src/PJ_sterea.c index e0ff15e7..38b26117 100644 --- a/src/PJ_sterea.c +++ b/src/PJ_sterea.c @@ -114,62 +114,3 @@ PJ *PROJECTION(sterea) { return P; } - -#ifndef PJ_SELFTEST -int pj_sterea_selftest (void) {return 0;} -#else - -int pj_sterea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=sterea +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=sterea +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222644.89410919772, 110611.09187173686}, - { 222644.89410919772, -110611.09187173827}, - {-222644.89410919772, 110611.09187173686}, - {-222644.89410919772, -110611.09187173827}, - }; - - XY s_fwd_expect[] = { - { 223407.81025950745, 111737.93899644315}, - { 223407.81025950745, -111737.93899644315}, - {-223407.81025950745, 111737.93899644315}, - {-223407.81025950745, -111737.93899644315}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305682019911, 0.00090436947683099009}, - { 0.0017966305682019911, -0.00090436947684371233}, - {-0.0017966305682019911, 0.00090436947683099009}, - {-0.0017966305682019911, -0.00090436947684371233}, - }; - - LP s_inv_expect[] = { - { 0.001790493109747395, 0.00089524655465446378}, - { 0.001790493109747395, -0.00089524655465446378}, - {-0.001790493109747395, 0.00089524655465446378}, - {-0.001790493109747395, -0.00089524655465446378}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_sts.c b/src/PJ_sts.c index 3e6168bd..d8866b66 100644 --- a/src/PJ_sts.c +++ b/src/PJ_sts.c @@ -64,8 +64,6 @@ static PJ *setup(PJ *P, double p, double q, int mode) { - - PJ *PROJECTION(fouc) { struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); if (0==Q) @@ -75,66 +73,6 @@ PJ *PROJECTION(fouc) { } -#ifndef PJ_SELFTEST -int pj_fouc_selftest (void) {return 0;} -#else -int pj_fouc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=fouc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=fouc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222588.12067589167, 111322.31670069379}, - {222588.12067589167, -111322.31670069379}, - {-222588.12067589167, 111322.31670069379}, - {-222588.12067589167, -111322.31670069379}, - }; - - XY s_fwd_expect[] = { - {223351.10900341379, 111703.9077217125}, - {223351.10900341379, -111703.9077217125}, - {-223351.10900341379, 111703.9077217125}, - {-223351.10900341379, -111703.9077217125}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966305685702751, 0.00089831528410111959}, - {0.0017966305685702751, -0.00089831528410111959}, - {-0.0017966305685702751, 0.00089831528410111959}, - {-0.0017966305685702751, -0.00089831528410111959}, - }; - - LP s_inv_expect[] = { - {0.0017904931101116717, 0.00089524655487369749}, - {0.0017904931101116717, -0.00089524655487369749}, - {-0.0017904931101116717, 0.00089524655487369749}, - {-0.0017904931101116717, -0.00089524655487369749}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif - - - - - PJ *PROJECTION(kav5) { struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); @@ -146,65 +84,6 @@ PJ *PROJECTION(kav5) { } -#ifndef PJ_SELFTEST -int pj_kav5_selftest (void) {return 0;} -#else -int pj_kav5_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=kav5 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=kav5 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {200360.90530882866, 123685.08247699818}, - {200360.90530882866, -123685.08247699818}, - {-200360.90530882866, 123685.08247699818}, - {-200360.90530882866, -123685.08247699818}, - }; - - XY s_fwd_expect[] = { - {201047.7031108776, 124109.05062917093}, - {201047.7031108776, -124109.05062917093}, - {-201047.7031108776, 124109.05062917093}, - {-201047.7031108776, -124109.05062917093}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0019962591348533314, 0.00080848256185253912}, - {0.0019962591348533314, -0.00080848256185253912}, - {-0.0019962591348533314, 0.00080848256185253912}, - {-0.0019962591348533314, -0.00080848256185253912}, - }; - - LP s_inv_expect[] = { - {0.0019894397264987643, 0.00080572070962591153}, - {0.0019894397264987643, -0.00080572070962591153}, - {-0.0019894397264987643, 0.00080572070962591153}, - {-0.0019894397264987643, -0.00080572070962591153}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif - - - - PJ *PROJECTION(qua_aut) { struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque)); @@ -214,64 +93,6 @@ PJ *PROJECTION(qua_aut) { return setup(P, 2., 2., 0); } -#ifndef PJ_SELFTEST -int pj_qua_aut_selftest (void) {return 0;} -#else -int pj_qua_aut_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=qua_aut +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=qua_aut +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222613.54903309655, 111318.07788798446}, - {222613.54903309655, -111318.07788798446}, - {-222613.54903309655, 111318.07788798446}, - {-222613.54903309655, -111318.07788798446}, - }; - - XY s_fwd_expect[] = { - {223376.62452402918, 111699.65437918637}, - {223376.62452402918, -111699.65437918637}, - {-223376.62452402918, 111699.65437918637}, - {-223376.62452402918, -111699.65437918637}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966305684046586, 0.00089831528412872229}, - {0.0017966305684046586, -0.00089831528412872229}, - {-0.0017966305684046586, 0.00089831528412872229}, - {-0.0017966305684046586, -0.00089831528412872229}, - }; - - LP s_inv_expect[] = { - {0.0017904931099477471, 0.00089524655490101819}, - {0.0017904931099477471, -0.00089524655490101819}, - {-0.0017904931099477471, 0.00089524655490101819}, - {-0.0017904931099477471, -0.00089524655490101819}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif - - - PJ *PROJECTION(mbt_s) { @@ -282,58 +103,3 @@ PJ *PROJECTION(mbt_s) { return setup(P, 1.48875, 1.36509, 0); } -#ifndef PJ_SELFTEST -int pj_mbt_s_selftest (void) {return 0;} -#else -int pj_mbt_s_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=mbt_s +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=mbt_s +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {204131.51785027285, 121400.33022550763}, - {204131.51785027285, -121400.33022550763}, - {-204131.51785027285, 121400.33022550763}, - {-204131.51785027285, -121400.33022550763}, - }; - - XY s_fwd_expect[] = { - {204831.24057099217, 121816.46669603503}, - {204831.24057099217, -121816.46669603503}, - {-204831.24057099217, 121816.46669603503}, - {-204831.24057099217, -121816.46669603503}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0019593827209883237, 0.00082369854658027549}, - {0.0019593827209883237, -0.00082369854658027549}, - {-0.0019593827209883237, 0.00082369854658027549}, - {-0.0019593827209883237, -0.00082369854658027549}, - }; - - LP s_inv_expect[] = { - {0.0019526892859206603, 0.00082088471512331508}, - {0.0019526892859206603, -0.00082088471512331508}, - {-0.0019526892859206603, 0.00082088471512331508}, - {-0.0019526892859206603, -0.00082088471512331508}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif diff --git a/src/PJ_tcc.c b/src/PJ_tcc.c index 26cf67b6..c6600ae0 100644 --- a/src/PJ_tcc.c +++ b/src/PJ_tcc.c @@ -30,30 +30,3 @@ PJ *PROJECTION(tcc) { return P; } - -#ifndef PJ_SELFTEST -int pj_tcc_selftest (void) {return 0;} -#else -int pj_tcc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=tcc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223458.84419245756, 111769.14504058579}, - {223458.84419245756, -111769.14504058579}, - {-223458.84419245756, 111769.14504058579}, - {-223458.84419245756, -111769.14504058579}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif diff --git a/src/PJ_tcea.c b/src/PJ_tcea.c index 65b3c604..415b42de 100644 --- a/src/PJ_tcea.c +++ b/src/PJ_tcea.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" PROJ_HEAD(tcea, "Transverse Cylindrical Equal Area") "\n\tCyl, Sph"; @@ -32,44 +32,3 @@ PJ *PROJECTION(tcea) { return P; } - -#ifndef PJ_SELFTEST -int pj_tcea_selftest (void) {return 0;} -#else -int pj_tcea_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=tcea +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223322.76057672748, 111769.14504058579}, - { 223322.76057672748, -111769.14504058579}, - {-223322.76057672748, 111769.14504058579}, - {-223322.76057672748, -111769.14504058579}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931102938101, 0.00089524655445477922}, - { 0.0017904931102938101, -0.00089524655445477922}, - {-0.0017904931102938101, 0.00089524655445477922}, - {-0.0017904931102938101, -0.00089524655445477922}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} -#endif diff --git a/src/PJ_times.c b/src/PJ_times.c index a8d6e67a..74b79393 100644 --- a/src/PJ_times.c +++ b/src/PJ_times.c @@ -75,47 +75,3 @@ PJ *PROJECTION(times) { return P; } - -#ifndef PJ_SELFTEST -int pj_times_selftest (void) {return 0;} -#else - -int pj_times_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - int result; - int n = 5; - - char s_args[] = {"+proj=times +ellps=sphere"}; - - XY *inv_in = malloc(n*sizeof(XY)); - LP *s_inv_expect = malloc(n*sizeof(LP)); - - LP fwd_in[] = { - { 0, 0}, - { 80, 70}, - { 25, -10}, - {-35, 20}, - {-45, -30} - }; - - XY s_fwd_expect[] = { - { 0.0, 0.0}, - { 5785183.5760670956, 7615452.0661204215}, - { 2065971.5301078814, -951526.0648494592}, - {-2873054.0454850947, 1917730.9530005211}, - {-3651383.2035214868, -2914213.4578159209}, - }; - - memcpy(inv_in, &s_fwd_expect, n*sizeof(XY)); - memcpy(s_inv_expect, &fwd_in, n*sizeof(LP)); - - result = pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, n, n, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); - free(inv_in); - free(s_inv_expect); - - return result; -} - - -#endif diff --git a/src/PJ_tmerc.c b/src/PJ_tmerc.c index b3ec0030..77fb5826 100644 --- a/src/PJ_tmerc.c +++ b/src/PJ_tmerc.c @@ -204,59 +204,3 @@ PJ *PROJECTION(tmerc) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_tmerc_selftest (void) {return 0;} -#else -int pj_tmerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=tmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=tmerc +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222650.79679577847, 110642.22941192707}, - { 222650.79679577847, -110642.22941192707}, - {-222650.79679577847, 110642.22941192707}, - {-222650.79679577847, -110642.22941192707}, - }; - - XY s_fwd_expect[] = { - { 223413.46640632232, 111769.14504059685}, - { 223413.46640632232, -111769.14504059685}, - {-223413.46640632208, 111769.14504059685}, - {-223413.46640632208, -111769.14504059685}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305681649396, 0.00090436947663183841}, - { 0.0017966305681649396, -0.00090436947663183841}, - {-0.0017966305681649396, 0.00090436947663183841}, - {-0.0017966305681649396, -0.00090436947663183841}, - }; - - LP s_inv_expect[] = { - { 0.0017904931097048034, 0.00089524670602767842}, - { 0.0017904931097048034, -0.00089524670602767842}, - {-0.001790493109714345, 0.00089524670602767842}, - {-0.001790493109714345, -0.00089524670602767842}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} -#endif diff --git a/src/PJ_tpeqd.c b/src/PJ_tpeqd.c index 6bea3968..eee5b3c3 100644 --- a/src/PJ_tpeqd.c +++ b/src/PJ_tpeqd.c @@ -104,62 +104,3 @@ PJ *PROJECTION(tpeqd) { return P; } - -#ifndef PJ_SELFTEST -int pj_tpeqd_selftest (void) {return 0;} -#else - -int pj_tpeqd_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=tpeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5"}; - char s_args[] = {"+proj=tpeqd +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {-27750.758831679042, -222599.40369177726}, - {-250434.93702403645, -222655.93819326628}, - {-27750.758831679042, 222599.40369177726}, - {-250434.93702403645, 222655.93819326628}, - }; - - XY s_fwd_expect[] = { - {-27845.882978485075, -223362.43069526015}, - {-251293.37876465076, -223419.15898590829}, - {-27845.882978485075, 223362.43069526015}, - {-251293.37876465076, 223419.15898590829}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-0.00089855554821257374, 1.2517966304145272}, - {0.0008985555481998515, 1.2517966304145272}, - {-0.00089855431859741167, 1.2482033692781642}, - {0.00089855431859741167, 1.2482033692781642}, - }; - - LP s_inv_expect[] = { - {-0.00089548606640108474, 1.2517904929571837}, - {0.0008954860663883625, 1.2517904929571837}, - {-0.000895484845182587, 1.248209506737604}, - {0.00089548484516986475, 1.248209506737604}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, s_fwd_expect, inv_in, e_inv_expect, s_inv_expect); -} - - -#endif diff --git a/src/PJ_unitconvert.c b/src/PJ_unitconvert.c index c5cf93ae..523d8897 100644 --- a/src/PJ_unitconvert.c +++ b/src/PJ_unitconvert.c @@ -19,7 +19,7 @@ date. A time unit conversion is performed like distance units are converted in the same manner, with meter being the central unit. -The modified Julian date is chosen as the pivout unit since it has a +The modified Julian date is chosen as the pivot unit since it has a fairly high precision, goes sufficiently long backwards in time, has no danger of hitting the upper limit in the near future and it is a fairly common time unit in astronomy and geodesy. Note that we are using the @@ -266,47 +266,47 @@ static LPZ reverse_3d(XYZ xyz, PJ *P) { /***********************************************************************/ -static PJ_OBS forward_obs(PJ_OBS obs, PJ *P) { +static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) { /************************************************************************ Forward conversion of time units ************************************************************************/ struct pj_opaque_unitconvert *Q = (struct pj_opaque_unitconvert *) P->opaque; - PJ_OBS out; + PJ_COORD out; /* delegate unit conversion of physical dimensions to the 3D function */ - out.coo.xyz = forward_3d(obs.coo.lpz, P); + out.xyz = forward_3d(obs.lpz, P); if (Q->t_in_id >= 0) - out.coo.xyzt.t = time_units[Q->t_in_id].t_in( obs.coo.xyzt.t ); + out.xyzt.t = time_units[Q->t_in_id].t_in( obs.xyzt.t ); if (Q->t_out_id >= 0) - out.coo.xyzt.t = time_units[Q->t_out_id].t_out( out.coo.xyzt.t ); + out.xyzt.t = time_units[Q->t_out_id].t_out( out.xyzt.t ); return out; } /***********************************************************************/ -static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) { +static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) { /************************************************************************ Reverse conversion of time units ************************************************************************/ struct pj_opaque_unitconvert *Q = (struct pj_opaque_unitconvert *) P->opaque; - PJ_OBS out; + PJ_COORD out; /* delegate unit conversion of physical dimensions to the 3D function */ - out.coo.lpz = reverse_3d(obs.coo.xyz, P); + out.lpz = reverse_3d(obs.xyz, P); if (Q->t_out_id >= 0) - out.coo.xyzt.t = time_units[Q->t_out_id].t_in( obs.coo.xyzt.t ); + out.xyzt.t = time_units[Q->t_out_id].t_in( obs.xyzt.t ); if (Q->t_in_id >= 0) - out.coo.xyzt.t = time_units[Q->t_in_id].t_out( out.coo.xyzt.t ); + out.xyzt.t = time_units[Q->t_in_id].t_out( out.xyzt.t ); return out; } /***********************************************************************/ -PJ *PROJECTION(unitconvert) { +PJ *CONVERSION(unitconvert,0) { /***********************************************************************/ struct pj_opaque_unitconvert *Q = pj_calloc (1, sizeof (struct pj_opaque_unitconvert)); char *s, *name; @@ -316,8 +316,8 @@ PJ *PROJECTION(unitconvert) { return pj_default_destructor (P, ENOMEM); P->opaque = (void *) Q; - P->fwdobs = forward_obs; - P->invobs = reverse_obs; + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; P->fwd3d = forward_3d; P->inv3d = reverse_3d; P->fwd = forward_2d; @@ -389,95 +389,3 @@ PJ *PROJECTION(unitconvert) { return P; } -#ifndef PJ_SELFTEST - -int pj_unitconvert_selftest (void) {return 0;} - -#else - -static int test_time(char* args, double tol, double t_in, double t_exp) { - PJ_OBS in, out; - PJ *P = proj_create(PJ_DEFAULT_CTX, args); - int ret = 0; - - if (P == 0) - return 5; - - in.coo.xyzt.t = t_in; - - out = proj_trans_obs(P, PJ_FWD, in); - if (fabs(out.coo.xyzt.t - t_exp) > tol) { - proj_log_error(P, "out: %10.10g, expect: %10.10g", out.coo.xyzt.t, t_exp); - ret = 1; - } - out = proj_trans_obs(P, PJ_INV, out); - if (fabs(out.coo.xyzt.t - t_in) > tol) { - proj_log_error(P, "out: %10.10g, expect: %10.10g", out.coo.xyzt.t, t_in); - ret = 2; - } - pj_free(P); - - proj_log_level(NULL, 0); - return ret; -} - -static int test_xyz(char* args, double tol, PJ_TRIPLET in, PJ_TRIPLET exp) { - PJ_OBS out, obs_in; - PJ *P = proj_create(PJ_DEFAULT_CTX, args); - int ret = 0; - - if (P == 0) - return 5; - - obs_in.coo.xyz = in.xyz; - out = proj_trans_obs(P, PJ_FWD, obs_in); - if (proj_xyz_dist(out.coo.xyz, exp.xyz) > tol) { - printf("exp: %10.10g, %10.10g, %10.10g\n", exp.xyz.x, exp.xyz.y, exp.xyz.z); - printf("out: %10.10g, %10.10g, %10.10g\n", out.coo.xyz.x, out.coo.xyz.y, out.coo.xyz.z); - ret = 1; - } - - out = proj_trans_obs(P, PJ_INV, out); - if (proj_xyz_dist(out.coo.xyz, in.xyz) > tol) { - printf("exp: %g, %g, %g\n", in.xyz.x, in.xyz.y, in.xyz.z); - printf("out: %g, %g, %g\n", out.coo.xyz.x, out.coo.xyz.y, out.coo.xyz.z); - ret += 2; - } - proj_destroy(P); - proj_log_level(NULL, 0); - return ret; -} - - -int pj_unitconvert_selftest (void) { - int ret = 0; - char args1[] = "+proj=unitconvert +t_in=decimalyear +t_out=decimalyear"; - double in1 = 2004.25; - - char args2[] = "+proj=unitconvert +t_in=gps_week +t_out=gps_week"; - double in2 = 1782.0; - - char args3[] = "+proj=unitconvert +t_in=mjd +t_out=mjd"; - double in3 = 57390.0; - - char args4[] = "+proj=unitconvert +t_in=gps_week +t_out=decimalyear"; - double in4 = 1877.71428, exp4 = 2016.0; - - char args5[] = "+proj=unitconvert +xy_in=m +xy_out=dm +z_in=cm +z_out=mm"; - PJ_TRIPLET in5 = {{55.25, 23.23, 45.5}}, exp5 = {{552.5, 232.3, 455.0}}; - - char args6[] = "+proj=unitconvert +xy_in=m +xy_out=m +z_in=m +z_out=m"; - PJ_TRIPLET in6 = {{12.3, 45.6, 7.89}}; - - ret = test_time(args1, 1e-6, in1, in1); if (ret) return ret + 10; - ret = test_time(args2, 1e-6, in2, in2); if (ret) return ret + 20; - ret = test_time(args3, 1e-6, in3, in3); if (ret) return ret + 30; - ret = test_time(args4, 1e-6, in4, exp4); if (ret) return ret + 40; - ret = test_xyz (args5, 1e-10, in5, exp5); if (ret) return ret + 50; - ret = test_xyz (args6, 1e-10, in6, in6); if (ret) return ret + 50; - - return 0; - -} - -#endif diff --git a/src/PJ_urm5.c b/src/PJ_urm5.c index bd073459..9960f501 100644 --- a/src/PJ_urm5.c +++ b/src/PJ_urm5.c @@ -29,7 +29,7 @@ PJ *PROJECTION(urm5) { if (0==Q) return pj_default_destructor(P, ENOMEM); P->opaque = Q; - + if (pj_param(P->ctx, P->params, "tn").i) { Q->n = pj_param(P->ctx, P->params, "dn").f; if (Q->n <= 0. || Q->n > 1.) @@ -50,30 +50,3 @@ PJ *PROJECTION(urm5) { return P; } - -#ifndef PJ_SELFTEST -int pj_urm5_selftest (void) {return 0;} -#else -int pj_urm5_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=urm5 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223393.6384339639, 111696.81878511712}, - { 223393.6384339639, -111696.81878511712}, - {-223393.6384339639, 111696.81878511712}, - {-223393.6384339639, -111696.81878511712}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif diff --git a/src/PJ_urmfps.c b/src/PJ_urmfps.c index 64eb5c80..19719a26 100644 --- a/src/PJ_urmfps.c +++ b/src/PJ_urmfps.c @@ -70,87 +70,3 @@ PJ *PROJECTION(wag1) { return setup(P); } - -#ifndef PJ_SELFTEST -int pj_urmfps_selftest (void) {return 0;} -#else -int pj_urmfps_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=urmfps +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 196001.70813419219, 127306.84332999329}, - { 196001.70813419219, -127306.84332999329}, - {-196001.70813419219, 127306.84332999329}, - {-196001.70813419219, -127306.84332999329}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.002040720839642371, 0.00078547381740438178}, - { 0.002040720839642371, -0.00078547381740438178}, - {-0.002040720839642371, 0.00078547381740438178}, - {-0.002040720839642371, -0.00078547381740438178}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} -#endif - - -#ifndef PJ_SELFTEST -int pj_wag1_selftest (void) {return 0;} -#else -int pj_wag1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 195986.78156115755, 127310.07506065986}, - { 195986.78156115755, -127310.07506065986}, - {-195986.78156115755, 127310.07506065986}, - {-195986.78156115755, -127310.07506065986}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.002040720839738254, 0.00078547381739207999}, - { 0.002040720839738254, -0.00078547381739207999}, - {-0.002040720839738254, 0.00078547381739207999}, - {-0.002040720839738254, -0.00078547381739207999}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} -#endif - diff --git a/src/PJ_vandg.c b/src/PJ_vandg.c index e19d01b8..b6b84bd0 100644 --- a/src/PJ_vandg.c +++ b/src/PJ_vandg.c @@ -105,47 +105,3 @@ PJ *PROJECTION(vandg) { return P; } - -#ifndef PJ_SELFTEST -int pj_vandg_selftest (void) {return 0;} -#else - -int pj_vandg_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=vandg +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223395.24954340671, 111704.59663367498}, - { 223395.24954340671, -111704.59663367498}, - {-223395.24954340671, 111704.59663367498}, - {-223395.24954340671, -111704.59663367498}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.001790493715929761, 0.00089524655486993867}, - { 0.001790493715929761, -0.00089524655486993867}, - {-0.001790493715929761, 0.00089524655486993867}, - {-0.001790493715929761, -0.00089524655486993867}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_vandg2.c b/src/PJ_vandg2.c index 3f11e289..81f28a74 100644 --- a/src/PJ_vandg2.c +++ b/src/PJ_vandg2.c @@ -70,63 +70,3 @@ PJ *PROJECTION(vandg3) { return P; } - -#ifndef PJ_SELFTEST -int pj_vandg2_selftest (void) {return 0;} -#else - -int pj_vandg2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=vandg2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223395.24785043663, 111718.49103722633}, - { 223395.24785043663, -111718.49103722633}, - {-223395.24785043663, 111718.49103722633}, - {-223395.24785043663, -111718.49103722633}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif - -#ifndef PJ_SELFTEST -int pj_vandg3_selftest (void) {return 0;} -#else - -int pj_vandg3_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=vandg3 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223395.24955283134, 111704.51990442065}, - { 223395.24955283134, -111704.51990442065}, - {-223395.24955283134, 111704.51990442065}, - {-223395.24955283134, -111704.51990442065}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_vandg4.c b/src/PJ_vandg4.c index f7f48b43..afffe41f 100644 --- a/src/PJ_vandg4.c +++ b/src/PJ_vandg4.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" PROJ_HEAD(vandg4, "van der Grinten IV") "\n\tMisc Sph, no inv."; @@ -51,33 +51,3 @@ PJ *PROJECTION(vandg4) { return P; } - -#ifndef PJ_SELFTEST -int pj_vandg4_selftest (void) {return 0;} -#else - -int pj_vandg4_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=vandg4 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223374.57729435508, 111701.19548415358
}, - { 223374.57729435508, -111701.19548415358
}, - {-223374.57729435508, 111701.19548415358
}, - {-223374.57729435508, -111701.19548415358
}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} - - -#endif diff --git a/src/PJ_vgridshift.c b/src/PJ_vgridshift.c index ededd544..97faa240 100644 --- a/src/PJ_vgridshift.c +++ b/src/PJ_vgridshift.c @@ -9,14 +9,10 @@ static XYZ forward_3d(LPZ lpz, PJ *P) { PJ_TRIPLET point; point.lpz = lpz; - if (P->gridlist != NULL) { + if (P->vgridlist_geoid != NULL) { /* Only try the gridshift if at least one grid is loaded, * otherwise just pass the coordinate through unchanged. */ - pj_apply_vgridshift( P, "sgrids", - &(P->gridlist), - &(P->gridlist_count), - 1, 1, 0, - &point.xyz.x, &point.xyz.y, &point.xyz.z ); + point.xyz.z -= proj_vgrid_value(P, point.lp); } return point.xyz; @@ -27,52 +23,47 @@ static LPZ reverse_3d(XYZ xyz, PJ *P) { PJ_TRIPLET point; point.xyz = xyz; - if (P->gridlist != NULL) { + if (P->vgridlist_geoid != NULL) { /* Only try the gridshift if at least one grid is loaded, * otherwise just pass the coordinate through unchanged. */ - pj_apply_vgridshift( P, "sgrids", - &(P->gridlist), - &(P->gridlist_count), - 0, 1, 0, - &point.xyz.x, &point.xyz.y, &point.xyz.z ); + point.xyz.z += proj_vgrid_value(P, point.lp); } return point.lpz; } -static PJ_OBS forward_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.xyz = forward_3d (obs.coo.lpz, P); +static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) { + PJ_COORD point; + point.xyz = forward_3d (obs.lpz, P); return point; } -static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) { - PJ_OBS point; - point.coo.lpz = reverse_3d (obs.coo.xyz, P); +static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) { + PJ_COORD point; + point.lpz = reverse_3d (obs.xyz, P); return point; } -PJ *PROJECTION(vgridshift) { +PJ *TRANSFORMATION(vgridshift,0) { if (!pj_param(P->ctx, P->params, "tgrids").i) { proj_log_error(P, "vgridshift: +grids parameter missing."); return pj_default_destructor(P, PJD_ERR_NO_ARGS); } - /* Build gridlist. P->gridlist can be empty if +grids only ask for optional grids. */ - P->gridlist = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, "sgrids").s, - &(P->gridlist_count) ); + /* Build gridlist. P->vgridlist_geoid can be empty if +grids only ask for optional grids. */ + proj_vgrid_init(P, "grids"); /* Was gridlist compiled properly? */ - if ( pj_ctx_get_errno(P->ctx) ) { + if ( proj_errno(P) ) { proj_log_error(P, "vgridshift: could not find required grid(s)."); - return pj_default_destructor(P, -38); + return pj_default_destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID); } - P->fwdobs = forward_obs; - P->invobs = reverse_obs; + P->fwd4d = forward_4d; + P->inv4d = reverse_4d; P->fwd3d = forward_3d; P->inv3d = reverse_3d; P->fwd = 0; @@ -84,61 +75,3 @@ PJ *PROJECTION(vgridshift) { return P; } - -#ifndef PJ_SELFTEST -/* selftest stub */ -int pj_vgridshift_selftest (void) {return 0;} -#else -int pj_vgridshift_selftest (void) { - PJ *P; - PJ_OBS expect, a, b; - double dist; - int failures = 0; - - /* fail on purpose: +grids parameter is mandatory*/ - P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift"); - if (0!=P) { - proj_destroy (P); - return 99; - } - - /* fail on purpose: open non-existing grid */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift +grids=nonexistinggrid.gtx"); - if (0!=P) { - proj_destroy (P); - return 999; - } - - /* Failure most likely means the grid is missing */ - P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift +grids=egm96_15.gtx +ellps=GRS80"); - if (0==P) - return 10; - - a = proj_obs_null; - a.coo.lpz.lam = PJ_TORAD(12.5); - a.coo.lpz.phi = PJ_TORAD(55.5); - - dist = proj_roundtrip (P, PJ_FWD, 1, a.coo); - if (dist > 0.00000001) - return 1; - - expect = a; - /* Appears there is a difference between the egm96_15.gtx distributed by OSGeo4W, */ - /* and the one from http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx */ - /* Was: expect.coo.lpz.z = -36.021305084228515625; (download.osgeo.org) */ - /* Was: expect.coo.lpz.z = -35.880001068115234000; (OSGeo4W) */ - /* This is annoying, but must be handled elsewhere. So for now, we check for both. */ - expect.coo.lpz.z = -36.021305084228516; - failures = 0; - b = proj_trans_obs(P, PJ_FWD, a); - if (proj_xyz_dist(expect.coo.xyz, b.coo.xyz) > 1e-4) failures++; - expect.coo.lpz.z = -35.880001068115234000; - if (proj_xyz_dist(expect.coo.xyz, b.coo.xyz) > 1e-4) failures++; - if (failures > 1) - return 2; - - proj_destroy (P); - - return 0; -} -#endif diff --git a/src/PJ_wag2.c b/src/PJ_wag2.c index 0588167e..059494d7 100644 --- a/src/PJ_wag2.c +++ b/src/PJ_wag2.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -# include <projects.h> +#include "projects.h" PROJ_HEAD(wag2, "Wagner II") "\n\tPCyl., Sph."; #define C_x 0.92483 #define C_y 1.38725 @@ -32,47 +32,3 @@ PJ *PROJECTION(wag2) { return P; } - -#ifndef PJ_SELFTEST -int pj_wag2_selftest (void) {return 0;} -#else - -int pj_wag2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 206589.88809996162, 120778.04035754716}, - { 206589.88809996162, -120778.04035754716}, - {-206589.88809996162, 120778.04035754716}, - {-206589.88809996162, -120778.04035754716}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0019360240367390709, 0.00082795765763814082}, - { 0.0019360240367390709, -0.00082795765763814082}, - {-0.0019360240367390709, 0.00082795765763814082}, - {-0.0019360240367390709, -0.00082795765763814082}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_wag3.c b/src/PJ_wag3.c index 7f300add..5db1e50f 100644 --- a/src/PJ_wag3.c +++ b/src/PJ_wag3.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" #include <errno.h> PROJ_HEAD(wag3, "Wagner III") "\n\tPCyl., Sph.\n\tlat_ts="; @@ -44,47 +44,3 @@ PJ *PROJECTION(wag3) { return P; } - -#ifndef PJ_SELFTEST -int pj_wag3_selftest (void) {return 0;} -#else - -int pj_wag3_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag3 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - {223387.02171816575, 111701.07212763709}, - {223387.02171816575, -111701.07212763709}, - {-223387.02171816575, 111701.07212763709}, - {-223387.02171816575, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - {0.001790493109880963, 0.00089524655489191132}, - {0.001790493109880963, -0.00089524655489191132}, - {-0.001790493109880963, 0.00089524655489191132}, - {-0.001790493109880963, -0.00089524655489191132}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_wag7.c b/src/PJ_wag7.c index 9152fdea..a820b2cd 100644 --- a/src/PJ_wag7.c +++ b/src/PJ_wag7.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" PROJ_HEAD(wag7, "Wagner VII") "\n\tMisc Sph, no inv."; @@ -26,31 +26,3 @@ PJ *PROJECTION(wag7) { return P; } - -#ifndef PJ_SELFTEST -int pj_wag7_selftest (void) {return 0;} -#else - -int pj_wag7_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wag7 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 198601.87695731167, 125637.0457141714}, - { 198601.87695731167, -125637.0457141714}, - {-198601.87695731167, 125637.0457141714}, - {-198601.87695731167, -125637.0457141714}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif diff --git a/src/PJ_wink1.c b/src/PJ_wink1.c index c1e2e909..f64f97d2 100644 --- a/src/PJ_wink1.c +++ b/src/PJ_wink1.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -#include <projects.h> +#include "projects.h" #include <errno.h> PROJ_HEAD(wink1, "Winkel I") "\n\tPCyl., Sph.\n\tlat_ts="; @@ -40,47 +40,3 @@ PJ *PROJECTION(wink1) { return P; } - -#ifndef PJ_SELFTEST -int pj_wink1_selftest (void) {return 0;} -#else - -int pj_wink1_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wink1 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223385.13164095284, 111701.07212763709}, - { 223385.13164095284, -111701.07212763709}, - {-223385.13164095284, 111701.07212763709}, - {-223385.13164095284, -111701.07212763709}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP s_inv_expect[] = { - { 0.0017904931098931057, 0.00089524655489191132}, - { 0.0017904931098931057, -0.00089524655489191132}, - {-0.0017904931098931057, 0.00089524655489191132}, - {-0.0017904931098931057, -0.00089524655489191132}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect); -} - - -#endif diff --git a/src/PJ_wink2.c b/src/PJ_wink2.c index 43b6cfce..d715074e 100644 --- a/src/PJ_wink2.c +++ b/src/PJ_wink2.c @@ -1,5 +1,5 @@ #define PJ_LIB__ -# include <projects.h> +#include "projects.h" #include <errno.h> PROJ_HEAD(wink2, "Winkel II") "\n\tPCyl., Sph., no inv.\n\tlat_1="; @@ -48,31 +48,3 @@ PJ *PROJECTION(wink2) { return P; } - -#ifndef PJ_SELFTEST -int pj_wink2_selftest (void) {return 0;} -#else - -int pj_wink2_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char s_args[] = {"+proj=wink2 +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY s_fwd_expect[] = { - { 223387.39643378611, 124752.03279744535}, - { 223387.39643378611, -124752.03279744535}, - {-223387.39643378611, 124752.03279744535}, - {-223387.39643378611, -124752.03279744535}, - }; - - return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, 0, 0, 0); -} -#endif diff --git a/src/adjlon.c b/src/adjlon.c index 09b3b14b..784a90aa 100644 --- a/src/adjlon.c +++ b/src/adjlon.c @@ -1,15 +1,20 @@ /* reduce argument to range +/- PI */ #include <math.h> -#include <projects.h> - -#define SPI 3.14159265359 -#define TWOPI 6.2831853071795864769 -#define ONEPI 3.14159265358979323846 +#include "projects.h" double adjlon (double lon) { - if (fabs(lon) <= SPI) return( lon ); - lon += ONEPI; /* adjust to 0..2pi rad */ - lon -= TWOPI * floor(lon / TWOPI); /* remove integral # of 'revolutions'*/ - lon -= ONEPI; /* adjust back to -pi..pi rad */ - return( lon ); + /* Let lon slightly overshoot, to avoid spurious sign switching at the date line */ + if (fabs (lon) < M_PI + 1e-12) + return lon; + + /* adjust to 0..2pi range */ + lon += M_PI; + + /* remove integral # of 'revolutions'*/ + lon -= M_TWOPI * floor(lon / M_TWOPI); + + /* adjust back to -pi..pi range */ + lon -= M_PI; + + return lon; } diff --git a/src/bch2bps.c b/src/bch2bps.c index 68a4737d..c0a357c1 100644 --- a/src/bch2bps.c +++ b/src/bch2bps.c @@ -30,12 +30,14 @@ dadd(projUV *a, projUV *b, double m, int n) { a++->v -= m * b++->v; } } - static void /* convert row to pover series */ + static int /* convert row to power series */ rows(projUV *c, projUV *d, int n) { projUV sv, *dd; int j, k; dd = (projUV *)vector1(n-1, sizeof(projUV)); + if (!dd) + return 0; sv.u = sv.v = 0.; for (j = 0; j < n; ++j) d[j] = dd[j] = sv; d[0] = c[n-1]; @@ -58,14 +60,21 @@ rows(projUV *c, projUV *d, int n) { d[0].u = -dd[0].u + .5 * c[0].u; d[0].v = -dd[0].v + .5 * c[0].v; pj_dalloc(dd); + return 1; } - static void /* convert columns to power series */ + static int /* convert columns to power series */ cols(projUV **c, projUV **d, int nu, int nv) { projUV *sv, **dd; int j, k; dd = (projUV **)vector2(nu, nv, sizeof(projUV)); + if (!dd) + return 0; sv = (projUV *)vector1(nv, sizeof(projUV)); + if (!sv) { + freev2((void **)dd, nu); + return 0; + } bclear(d, nu, nv); bclear(dd, nu, nv); bmove(d[0], c[nu-1], nv); @@ -84,6 +93,7 @@ cols(projUV **c, projUV **d, int nu, int nv) { submop(d[0], .5, c[0], dd[0], nv); freev2((void **) dd, nu); pj_dalloc(sv); + return 1; } static void /* row adjust for range -1 to 1 to a to b */ rowshft(double a, double b, projUV *d, int n) { @@ -129,11 +139,13 @@ bch2bps(projUV a, projUV b, projUV **c, int nu, int nv) { return 0; /* do rows to power series */ for (i = 0; i < nu; ++i) { - rows(c[i], d[i], nv); + if (!rows(c[i], d[i], nv)) + return 0; rowshft(a.v, b.v, d[i], nv); } /* do columns to power series */ - cols(d, c, nu, nv); + if (!cols(d, c, nu, nv)) + return 0; colshft(a.u, b.u, c, nu, nv); freev2((void **) d, nu); return 1; diff --git a/src/bin_gie.cmake b/src/bin_gie.cmake new file mode 100644 index 00000000..ca6dde0e --- /dev/null +++ b/src/bin_gie.cmake @@ -0,0 +1,9 @@ +set(GIE_SRC gie.c proj_strtod.c) +set(GIE_INCLUDE optargpm.h) + +source_group("Source Files\\Bin" FILES ${GIE_SRC}) + +add_executable(gie ${GIE_SRC} ${GIE_INCLUDE}) +target_link_libraries(gie ${PROJ_LIBRARIES}) +install(TARGETS gie + RUNTIME DESTINATION ${BINDIR}) @@ -44,7 +44,7 @@ Hence, in honour of cct (the geodesist) this is cct (the program). ************************************************************************ -Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-09-19 +Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26 ************************************************************************ @@ -72,22 +72,22 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-09-19 ***********************************************************************/ #include "optargpm.h" +#include "proj_internal.h" #include <proj.h> -#include <projects.h> +#include "projects.h" #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <math.h> + double proj_strtod(const char *str, char **endptr); double proj_atof(const char *str); char *column (char *buf, int n); PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time); -int print_output_line (FILE *fout, char *buf, PJ_COORD point); -int main(int argc, char **argv); - + static const char usage[] = { @@ -101,6 +101,7 @@ static const char usage[] = { " Defaults to 1,2,3,4\n" " -z value Provide a fixed z value for all input data (e.g. -z 0)\n" " -t value Provide a fixed t value for all input data (e.g. -t 0)\n" + " -I Do the inverse transformation\n" " -v Verbose: Provide non-essential informational output.\n" " Repeat -v for more verbosity (e.g. -vv)\n" "--------------------------------------------------------------------------------\n" @@ -111,6 +112,7 @@ static const char usage[] = { " --height Alias for -z\n" " --time Alias for -t\n" " --verbose Alias for -v\n" + " --inverse Alias for -I\n" " --help Alias for -h\n" "--------------------------------------------------------------------------------\n" "Operator Specs:\n" @@ -140,7 +142,7 @@ static const char usage[] = { " cct -c 5,2,1,4 +proj=utm +ellps=GRS80 +zone=32\n" "4. as (1) but specify fixed height and time, hence needing only 2 cols in input:\n" " cct -t 0 -z 0 +proj=utm +ellps=GRS80 +zone=32\n" - "--------------------------------------------------------------------------------\n" + "--------------------------------------------------------------------------------\n" }; int main(int argc, char **argv) { @@ -149,13 +151,13 @@ int main(int argc, char **argv) { OPTARGS *o; FILE *fout = stdout; char *buf; - int input_unit, output_unit, nfields = 4, direction = 1, verbose; + int nfields = 4, direction = 1, verbose; double fixed_z = HUGE_VAL, fixed_time = HUGE_VAL; int columns_xyzt[] = {1, 2, 3, 4}; - const char *longflags[] = {"v=verbose", "h=help", 0}; + const char *longflags[] = {"v=verbose", "h=help", "I=inverse", 0}; const char *longkeys[] = {"o=output", "c=columns", "z=height", "t=time", 0}; - - o = opt_parse (argc, argv, "hv", "cozt", longflags, longkeys); + + o = opt_parse (argc, argv, "hvI", "cozt", longflags, longkeys); if (0==o) return 0; @@ -177,14 +179,14 @@ int main(int argc, char **argv) { } if (verbose > 3) fprintf (fout, "%s: Running in very verbose mode\n", o->progname); - - + + if (opt_given (o, "z")) { fixed_z = proj_atof (opt_arg (o, "z")); nfields--; } - + if (opt_given (o, "t")) { fixed_time = proj_atof (opt_arg (o, "t")); nfields--; @@ -200,7 +202,7 @@ int main(int argc, char **argv) { return 1; } } - + /* Setup transformation */ P = proj_create_argv (0, o->pargc, o->pargv); if ((0==P) || (0==o->pargc)) { @@ -211,17 +213,10 @@ int main(int argc, char **argv) { return 1; } - input_unit = P->left; - output_unit = P->right; - if (PJ_IO_UNITS_CLASSIC==P->left) - input_unit = PJ_IO_UNITS_RADIANS; - if (PJ_IO_UNITS_CLASSIC==P->right) - output_unit = PJ_IO_UNITS_METERS; - if (direction==-1) { - enum pj_io_units swap = input_unit; - input_unit = output_unit; - output_unit = swap; - } + /* We have no API call for inverting an operation, so we brute force it. */ + if (direction==-1) + P->inverted = !(P->inverted); + direction = 1; /* Allocate input buffer */ buf = calloc (1, 10000); @@ -235,32 +230,51 @@ int main(int argc, char **argv) { } - /* Loop over all lines of all input files */ + /* Loop over all records of all input files */ while (opt_input_loop (o, optargs_file_format_text)) { void *ret = fgets (buf, 10000, o->input); - int res; opt_eof_handler (o); if (0==ret) { fprintf (stderr, "Read error in record %d\n", (int) o->record_index); continue; } point = parse_input_line (buf, columns_xyzt, fixed_z, fixed_time); - if (PJ_IO_UNITS_RADIANS==input_unit) { + if (HUGE_VAL==point.xyzt.x) { + char *c = column (buf, 1); + + /* if it's a comment or blank line, we reflect it */ + if (c && ((*c=='\0') || (*c=='#'))) { + fprintf (fout, "%s\n", buf); + continue; + } + + /* otherwise, it must be a syntax error */ + fprintf (fout, "# Record %d UNREADABLE: %s", (int) o->record_index, buf); + if (verbose) + fprintf (stderr, "%s: Could not parse file '%s' line %d\n", o->progname, opt_filename (o), opt_record (o)); + continue; + } + + if (proj_angular_input (P, direction)) { point.lpzt.lam = proj_torad (point.lpzt.lam); point.lpzt.phi = proj_torad (point.lpzt.phi); } - point = proj_trans_coord (P, direction, point); - if (PJ_IO_UNITS_RADIANS==output_unit) { + point = proj_trans (P, direction, point); + if (proj_angular_output (P, direction)) { point.lpzt.lam = proj_todeg (point.lpzt.lam); point.lpzt.phi = proj_todeg (point.lpzt.phi); } - res = print_output_line (fout, buf, point); - if (0==res) { - fprintf (fout, "# UNREADABLE: %s", buf); - if (verbose) - fprintf (stderr, "%s: Could not parse file '%s' line %d\n", o->progname, opt_filename (o), opt_record (o)); + + if (HUGE_VAL==point.xyzt.x) { + /* transformation error (TODO provide existing internal errmsg here) */ + fprintf (fout, "# Record %d TRANSFORMATION ERROR: %s", (int) o->record_index, buf); + continue; } + + /* Time to print the result */ + fprintf (fout, "%20.15f %20.15f %20.15f %20.15f\n", point.xyzt.x, point.xyzt.y, point.xyzt.z, point.xyzt.t); } + if (stdout != fout) fclose (fout); free (o); @@ -287,22 +301,32 @@ char *column (char *buf, int n) { return buf; } +/* column to double */ +static double cold (char *args, int col) { + char *endp; + char *target; + double d; + target = column (args, col); + d = proj_strtod (target, &endp); + if (endp==target) + return HUGE_VAL; + return d; +} PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time) { PJ_COORD err = proj_coord (HUGE_VAL, HUGE_VAL, HUGE_VAL, HUGE_VAL); PJ_COORD result = err; int prev_errno = errno; - char *endptr = 0; errno = 0; result.xyzt.z = fixed_height; result.xyzt.t = fixed_time; - result.xyzt.x = proj_strtod (column (buf, columns[0]), &endptr); - result.xyzt.y = proj_strtod (column (buf, columns[1]), &endptr); + result.xyzt.x = cold (buf, columns[0]); + result.xyzt.y = cold (buf, columns[1]); if (result.xyzt.z==HUGE_VAL) - result.xyzt.z = proj_strtod (column (buf, columns[2]), &endptr); + result.xyzt.z = cold (buf, columns[2]); if (result.xyzt.t==HUGE_VAL) - result.xyzt.t = proj_strtod (column (buf, columns[3]), &endptr); + result.xyzt.t = cold (buf, columns[3]); if (0!=errno) return err; @@ -310,15 +334,3 @@ PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double errno = prev_errno; return result; } - - -int print_output_line (FILE *fout, char *buf, PJ_COORD point) { - char *c; - if (HUGE_VAL!=point.xyzt.x) - return fprintf (fout, "%20.15f %20.15f %20.15f %20.15f\n", point.xyzt.x, point.xyzt.y, point.xyzt.z, point.xyzt.t); - c = column (buf, 1); - /* reflect comments and blanks */ - if (c && ((*c=='\0') || (*c=='#'))) - return fprintf (fout, "%s\n", buf); - return 0; -} diff --git a/src/geocent.c b/src/geocent.c index e340e73d..a8cec043 100644 --- a/src/geocent.c +++ b/src/geocent.c @@ -430,7 +430,7 @@ void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo *gi, while (SDPHI*SDPHI > genau2 && iter < maxiter); /* ellipsoidal (geodetic) latitude */ - *Latitude=atan(SPHI/fabs(CPHI)); + *Latitude=atan2(SPHI, fabs(CPHI)); return; #endif /* defined(USE_ITERATIVE_METHOD) */ diff --git a/src/geod_set.c b/src/geod_set.c index 60f19990..16396a90 100644 --- a/src/geod_set.c +++ b/src/geod_set.c @@ -16,8 +16,12 @@ geod_set(int argc, char **argv) { if (argc <= 0) emess(1, "no arguments in initialization list"); start = curr = pj_mkparam(argv[0]); + if (!curr) + emess(1, "memory allocation failed"); for (i = 1; i < argc; ++i) { curr->next = pj_mkparam(argv[i]); + if (!curr->next) + emess(1, "memory allocation failed"); curr = curr->next; } /* set elliptical parameters */ diff --git a/src/gie.c b/src/gie.c new file mode 100644 index 00000000..4b89fe8f --- /dev/null +++ b/src/gie.c @@ -0,0 +1,1535 @@ +/*********************************************************************** + + gie - The Geospatial Integrity Investigation Environment + +************************************************************************ + +The Geospatial Integrity Investigation Environment "gie" is a modest +regression testing environment for the PROJ.4 transformation library. + +Its primary design goal was to be able to replace those thousands of +lines of regression testing code that are (at time of writing) part +of PROJ.4, while not requiring any other kind of tooling than the same +C compiler already employed for compiling the library. + +The basic functionality of the gie command language is implemented +through just 3 command verbs: + +OPERATION, which defines the PROJ.4 operation to test, +ACCEPT, which defines the input coordinate to read, and +EXPECT, which defines the result to expect. + +E.g: + +operation +proj=utm +zone=32 +ellps=GRS80 +accept 12 55 +expect 691_875.632_14 6_098_907.825_05 + +Note that gie accepts the underscore ("_") as a thousands separator. +It is not required (in fact, it is entirely ignored by the input +routine), but it significantly improves the readability of the very +long strings of numbers typically required in projected coordinates. + +By default, gie considers the EXPECTation met, if the result comes to +within 0.5 mm of the expected. This default can be changed using the +TOLERANCE command verb (and yes, I know, linguistically speaking, both +"operation" and "tolerance" are nouns, not verbs). See the first +few hundred lines of the "builtins.gie" test file for more details of +the command verbs available (verbs of both the VERBal and NOUNistic +persuation). + +-- + +But more importantly than being an acronym for "Geospatial Integrity +Investigation Environment", gie were also the initials, user id, and +USGS email address of Gerald Ian Evenden (1935--2016), the geospatial +visionary, who, already in the 1980s, started what was to become the +PROJ.4 of today. + +Gerald's clear vision was that map projections are *just special +functions*. Some of them rather complex, most of them of two variables, +but all of them *just special functions*, and not particularly more +special than the sin(), cos(), tan(), and hypot() already available in +the C standard library. + +And hence, according to Gerald, *they should not be particularly much +harder to use*, for a programmer, than the sin()s, tan()s and hypot()s +so readily available. + +Gerald's ingenuity also showed in the implementation of the vision, +where he devised a comprehensive, yet simple, system of key-value +pairs for parameterising a map projection, and the highly flexible +PJ struct, storing run-time compiled versions of those key-value pairs, +hence making a map projection function call, pj_fwd(PJ, point), as easy +as a traditional function call like hypot(x,y). + +While today, we may have more formally well defined metadata systems +(most prominent the OGC WKT representation), nothing comes close being +as easily readable ("human compatible") as Gerald's key-value system. +This system in particular, and the PROJ.4 system in general, was +Gerald's great gift to anyone using and/or communicating about geodata. + +It is only reasonable to name a program keeping an eye on the integrity +of the PROJ.4 system in honour of Gerald. So in honour, and hopefully +also in the spirit, of Gerald Ian Evenden (1935--2016), this is the +Geospatial Integrity Investigation Environment. + +************************************************************************ + +Thomas Knudsen, thokn@sdfe.dk, 2017-10-01/2017-10-08 + +************************************************************************ + +* Copyright (c) 2017 Thomas Knudsen +* Copyright (c) 2017, SDFE +* +* 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 "optargpm.h" + +#include <proj.h> +#include "proj_internal.h" +#include "projects.h" + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> + +#include <string.h> +#include <ctype.h> + +#include <math.h> +#include <errno.h> + + + +/* from proj_strtod.c */ +double proj_strtod(const char *str, char **endptr); +double proj_atof(const char *str); + +int main(int argc, char **argv); + +static int process_file (char *fname); +static int errmsg (int errlev, char *msg, ...); +static int get_inp (FILE *f, char *inp, int size); +static int get_cmnd (char *inp, char *cmnd, int len); +static char *get_args (char *inp); +static int dispatch (char *cmnd, char *args); +static char *column (char *buf, int n); + + + +#define SKIP -1 + +typedef struct { + char operation[10000]; + PJ *P; + PJ_COORD a, b, c, e; + PJ_DIRECTION dir; + int verbosity; + int nargs; + int op_id; + int op_ok, op_ko; + int total_ok, total_ko; + int grand_ok, grand_ko; + size_t operation_lineno; + double tolerance; + char *curr_file; + FILE *fout; +} gie_ctx; + +gie_ctx T = {{""}, 0, {{0,0,0,0}}, {{0,0,0,0}}, {{0,0,0,0}}, {{0,0,0,0}}, PJ_FWD, 1, 0, 0,0,0,0,0,0,0,0, 0.0005, 0, 0}; + +OPTARGS *o; + + + +size_t tol_lineno = 0; +size_t lineno = 0; +size_t level = 0; +char delim[] = {"-------------------------------------------------------------------------------\n"}; +char DELIM[] = {"===============================================================================\n"}; + + +#define CMDLEN 25000 + +int nfiles = 0; + + +static const char usage[] = { + "--------------------------------------------------------------------------------\n" + "Usage: %s [-options]... infile...\n" + "--------------------------------------------------------------------------------\n" + "Options:\n" + "--------------------------------------------------------------------------------\n" + " -h Help: print this usage information\n" + " -o /path/to/file Specify output file name\n" + " -v Verbose: Provide non-essential informational output.\n" + " Repeat -v for more verbosity (e.g. -vv)\n" + " -q Quiet: Opposite of verbose. In quiet mode not even errors\n" + " are reported. Only interaction is through the return code\n" + " (0 on success, non-zero indicates number of FAILED tests)\n" + "--------------------------------------------------------------------------------\n" + "Long Options:\n" + "--------------------------------------------------------------------------------\n" + " --output Alias for -o\n" + " --verbose Alias for -v\n" + " --help Alias for -h\n" + "--------------------------------------------------------------------------------\n" + "Examples:\n" + "--------------------------------------------------------------------------------\n" + "1. Run all tests in file \"corner-cases.gie\", providing much extra information\n" + " gie -vvvv corner-cases.gie\n" + "2. Run all tests in files \"foo\" and \"bar\", providing info on failures only\n" + " gie foo bar\n" + "--------------------------------------------------------------------------------\n" +}; + +int main (int argc, char **argv) { + int i; + const char *longflags[] = {"v=verbose", "q=quiet", "h=help", 0}; + const char *longkeys[] = {"o=output", 0}; + + o = opt_parse (argc, argv, "hvq", "o", longflags, longkeys); + if (0==o) + return 0; + + if (opt_given (o, "h")) { + printf (usage, o->progname); + return 0; + } + + + + T.verbosity = opt_given (o, "q"); + if (T.verbosity) + T.verbosity = -1; + if (T.verbosity != -1) + T.verbosity = opt_given (o, "v") + 1; + + T.fout = stdout; + if (opt_given (o, "o")) + T.fout = fopen (opt_arg (o, "output"), "rt"); + if (0==T.fout) { + fprintf (stderr, "%s: Cannot open '%s' for output\n", o->progname, opt_arg (o, "output")); + free (o); + return 1; + } + + if (0==o->fargc) { + if (T.verbosity==-1) + return -1; + fprintf (T.fout, "Nothing to do\n"); + return 0; + } + + for (i = 0; i < o->fargc; i++) + process_file (o->fargv[i]); + + if (T.verbosity > 0) { + if (o->fargc > 1) + fprintf (T.fout, "%sGrand total: %d. Success: %d, Failure: %d\n", delim, T.grand_ok+T.grand_ko, T.grand_ok, T.grand_ko); + fprintf (T.fout, "%s", delim); + } + else + if (T.grand_ko) + fprintf (T.fout, "Failures: %d", T.grand_ko); + + if (stdout != T.fout) + fclose (T.fout); + + free (o); + return T.grand_ko; +} + +static int another_failure (void) { + T.op_ko++; + T.total_ko++; + return 0; +} + +static int another_success (void) { + T.op_ok++; + T.total_ok++; + return 0; +} + + +static int process_file (char *fname) { + FILE *f; + char inp[CMDLEN]; + char cmnd[1000]; + char *args; + + lineno = level = 0; + T.op_ok = T.total_ok = 0; + T.op_ko = T.total_ko = 0; + + f = fopen (fname, "rt"); + if (0==f) { + if (T.verbosity > 0) { + fprintf (T.fout, "%sCannot open spec'd input file '%s' - bye!\n", delim, fname); + return 2; + } + errmsg (2, "Cannot open spec'd input file '%s' - bye!\n", fname); + } + if (T.verbosity > 0) + fprintf (T.fout, "%sReading file '%s'\n", delim, fname); + T.curr_file = fname; + while (get_inp(f, inp, CMDLEN)) { + int len; + + if (feof(f)) + break; + len = get_cmnd (inp, cmnd, 1000); + if (len>=999) { + errmsg (2, "Command verb too long: '%s' - bye!\n", cmnd); + proj_destroy (T.P); + T.P = 0; + return 0; + + } + args = get_args (inp); + if (SKIP==dispatch (cmnd, args)) + return proj_destroy (T.P), T.P = 0, 0; + } + fclose (f); + + T.grand_ok += T.total_ok; + T.grand_ko += T.total_ko; + if (T.verbosity > 0) + fprintf (T.fout, "%stotal: %2d tests succeeded, %2d tests %s\n", delim, T.total_ok, T.total_ko, T.total_ko? "FAILED!": "failed."); + + if (level==0) + return errmsg (-3, "File '%s':Missing 'BEGIN' cmnd - bye!\n", fname); + if (level && level%2) + return errmsg (-4, "File '%s':Missing 'END' cmnd - bye!\n", fname); + return 0; +} + + +/* return a pointer to the n'th column of buf */ +char *column (char *buf, int n) { + int i; + if (n <= 0) + return buf; + for (i = 0; i < n; i++) { + while (isspace(*buf)) + buf++; + if (i == n - 1) + break; + while ((0 != *buf) && !isspace(*buf)) + buf++; + } + return buf; +} + + +/* interpret <args> as a numeric followed by a linear decadal prefix - return the properly scaled numeric */ +static double strtod_scaled (char *args, double default_scale) { + double s; + char *endp = args; + s = proj_strtod (args, &endp); + if (args==endp) + return HUGE_VAL; + + endp = column (args, 2); + + if (0==strcmp(endp, "km")) + s *= 1000; + else if (0==strcmp(endp, "m")) + s *= 1; + else if (0==strcmp(endp, "dm")) + s /= 10; + else if (0==strcmp(endp, "cm")) + s /= 100; + else if (0==strcmp(endp, "mm")) + s /= 1000; + else if (0==strcmp(endp, "um")) + s /= 1e6; + else if (0==strcmp(endp, "nm")) + s /= 1e9; + else + s *= default_scale; + return s; +} + + + + + +static int banner (char *args) { + char dots[] = {"..."}, nodots[] = {""}, *thedots = nodots; + if (strlen(args) > 70) + thedots = dots; + fprintf (T.fout, "%s%-70.70s%s\n", delim, args, thedots); + return 0; +} + + + + + + +static int tolerance (char *args) { + T.tolerance = strtod_scaled (args, 1); + if (HUGE_VAL==T.tolerance) { + T.tolerance = 0.0005; + return 1; + } + return 0; +} + + +static int direction (char *args) { + char *endp = args; + while (isspace (*endp)) + endp++; + switch (*endp) { + case 'F': + case 'f': + T.dir = PJ_FWD; + break; + case 'I': + case 'i': + case 'R': + case 'r': + T.dir = PJ_INV; + break; + default: + return 1; + } + return 0; +} + + + + +static void finish_previous_operation (char *args) { + if (T.verbosity > 1 && T.op_id > 1 && T.op_ok+T.op_ko) + fprintf (T.fout, "%s %d tests succeeded, %d tests %s\n", delim, T.op_ok, T.op_ko, T.op_ko? "FAILED!": "failed."); + (void) args; +} + +/*****************************************************************************/ +static int operation (char *args) { +/***************************************************************************** + Define the operation to apply to the input data (in ISO 19100 lingo, + an operation is the general term describing something that can be + either a conversion or a transformation) +******************************************************************************/ + int i, j, n; + T.op_id++; + + T.operation_lineno = lineno; + + /* compactify the args, so we can fit more info on a line in verbose mode */ + n = (int) strlen (args); + for (i = j = 0; i < n; ) { + /* skip prefix whitespace */ + while (isspace (args[i])) + i++; + /* move a whitespace delimited text string to the left, skipping over superfluous whitespace */ + while ((0!=args[i]) && (!isspace (args[i]))) + args[j++] = args[i++]; + if (args[j+1]!=0) + args[j++] = ' '; + i++; + } + args[j++] = 0; + strcpy (&(T.operation[0]), args); + + if (T.verbosity > 1) { + finish_previous_operation (args); + banner (args); + } + + T.op_ok = 0; + T.op_ko = 0; + + direction ("forward"); + tolerance ("0.5 mm"); + + + if (T.P) + proj_destroy (T.P); + T.P = proj_create (0, args); + + return 0; +} + + + + +static int pj_unitconvert_selftest (void); +static int pj_cart_selftest (void); +static int pj_horner_selftest (void); +/*****************************************************************************/ +static int builtins (char *args) { +/***************************************************************************** + There are still a few tests that cannot be described using gie + primitives. Instead, they are implemented as builtins, and invoked + using the "builtins" command verb. +******************************************************************************/ + int i; + if (T.verbosity > 1) { + finish_previous_operation (args); + banner ("builtins: unitconvert, horner, cart"); + } + T.op_ok = 0; + T.op_ko = 0; + + i = pj_unitconvert_selftest (); + if (i!=0) { + printf ("pj_unitconvert_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + + i = pj_cart_selftest (); + if (i!=0) { + printf ("pj_cart_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + i = pj_horner_selftest (); + if (i!=0) { + printf ("pj_horner_selftest fails with %d\n", i); + another_failure(); + } + else + another_success (); + + return 0; +} + + + + + +static PJ_COORD torad_coord (PJ_COORD a) { + PJ_COORD c = a; + c.lpz.lam = proj_torad (a.lpz.lam); + c.lpz.phi = proj_torad (a.lpz.phi); + return c; +} + +static PJ_COORD todeg_coord (PJ_COORD a) { + PJ_COORD c = a; + c.lpz.lam = proj_todeg (a.lpz.lam); + c.lpz.phi = proj_todeg (a.lpz.phi); + return c; +} + +/* try to parse args as a PJ_COORD */ +static PJ_COORD parse_coord (char *args) { + int i; + char *endp, *prev = args; + PJ_COORD a = proj_coord (0,0,0,0); + + for (i = 0; i < 4; i++) { + double d = proj_strtod (prev, &endp); + if (prev==endp) + return i > 1? a: proj_coord_error (); + a.v[i] = d; + prev = endp; + } + + return a; +} + + +/*****************************************************************************/ +static int accept (char *args) { +/***************************************************************************** + Read ("ACCEPT") a 2, 3, or 4 dimensional input coordinate. +******************************************************************************/ + T.a = parse_coord (args); + if (T.verbosity > 3) + printf ("# %s\n", args); + return 0; +} + + + +/*****************************************************************************/ +static int roundtrip (char *args) { +/***************************************************************************** + Check how far we go from the ACCEPTed point when doing successive + back/forward transformation pairs. +******************************************************************************/ + int ntrips; + double d, r, ans; + char *endp; + PJ_COORD coo; + + if (0==T.P) + return another_failure (); + + ans = proj_strtod (args, &endp); + ntrips = (int) (endp==args? 100: fabs(ans)); + d = strtod_scaled (endp, 1); + d = d==HUGE_VAL? T.tolerance: d; + coo = T.a; + + /* input ("accepted") values - probably in degrees */ + coo = proj_angular_input (T.P, T.dir)? torad_coord (T.a): T.a; + + r = proj_roundtrip (T.P, T.dir, ntrips, &coo); + if (r <= d) + return another_success (); + + if (T.verbosity > -1) { + if (0==T.op_ko && T.verbosity < 2) + 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) lineno); + fprintf (T.fout, " roundtrip deviation: %.3f mm, expected: %.3f mm\n", 1000*r, 1000*d); + } + return another_failure (); +} + + + +static int expect_message (double d, char *args) { + another_failure (); + + if (T.verbosity < 0) + return 1; + if (d > 1e6) + d = 999999.999999; + if (0==T.op_ko && T.verbosity < 2) + 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) lineno); + fprintf (T.fout, " expected: %s\n", args); + fprintf (T.fout, " got: %.9f %.9f", T.b.xy.x, T.b.xy.y); + if (T.b.xyzt.t!=0 || T.b.xyzt.z!=0) + fprintf (T.fout, " %.9f", T.b.xyz.z); + if (T.b.xyzt.t!=0) + fprintf (T.fout, " %.9f", T.b.xyzt.t); + fprintf (T.fout, "\n"); + fprintf (T.fout, " deviation: %.3f mm, expected: %.3f mm\n", 1000*d, 1000*T.tolerance); + return 1; +} + +static int expect_message_cannot_parse (char *args) { + another_failure (); + if (T.verbosity > -1) { + if (0==T.op_ko && T.verbosity < 2) + banner (T.operation); + fprintf (T.fout, "%s", T.op_ko? " -----\n": delim); + fprintf (T.fout, " FAILURE in %s(%d):\n Too few args: %s\n", opt_strip_path (T.curr_file), (int) lineno, args); + } + return 1; +} + + +/*****************************************************************************/ +static int expect (char *args) { +/***************************************************************************** + Tell GIE what to expect, when transforming the ACCEPTed input +******************************************************************************/ + PJ_COORD ci, co, ce; + double d; + int expect_failure = 0; + + if (0==strcmp (args, "failure")) + expect_failure = 1; + + if (0==T.P && !expect_failure) { + banner (T.operation); + errmsg(3, "%sInvalid operation definition in line no. %d\n", delim, (int) T.operation_lineno); + return another_failure (); + } + + + if (expect_failure) { + /* If we expect failure, and fail, then it's a success... */ + if (0==T.P) + return another_success (); + /* We may still successfully fail even if the proj_create succeeded */ + ci = proj_angular_input (T.P, T.dir)? torad_coord (T.a): T.a; + co = proj_trans (T.P, T.dir, ci); + if (co.xyz.x==HUGE_VAL) + return another_success (); + /* no - we didn't manage to purportedly fail */ + return another_failure (); + } + + + if (T.verbosity > 3) { + puts (T.P->inverted? "INVERTED": "NOT INVERTED"); + puts (T.dir== 1? "forward": "reverse"); + puts (proj_angular_input (T.P, T.dir)? "angular in": "linear in"); + puts (proj_angular_output (T.P, T.dir)? "angular out": "linear out"); + } + + T.e = parse_coord (args); + if (HUGE_VAL==T.e.v[0]) + return expect_message_cannot_parse (args); + + /* expected angular values, probably in degrees */ + ce = proj_angular_output (T.P, T.dir)? torad_coord (T.e): T.e; + if (T.verbosity > 3) + printf ("EXPECTS %.4f %.4f %.4f %.4f\n", ce.v[0],ce.v[1],ce.v[2],ce.v[3]); + + /* input ("accepted") values, also probably in degrees */ + ci = proj_angular_input (T.P, T.dir)? torad_coord (T.a): T.a; + if (T.verbosity > 3) + printf ("ACCEPTS %.4f %.4f %.4f %.4f\n", ci.v[0],ci.v[1],ci.v[2],ci.v[3]); + + + /* angular output from proj_trans comes in radians */ + co = proj_trans (T.P, T.dir, ci); + T.b = proj_angular_output (T.P, T.dir)? todeg_coord (co): co; + if (T.verbosity > 3) + printf ("GOT %.4f %.4f %.4f %.4f\n", ci.v[0],ci.v[1],ci.v[2],ci.v[3]); + + /* but there are a few more possible input conventions... */ + if (proj_angular_output (T.P, T.dir)) { + double e = HUGE_VAL; + d = proj_lpz_dist (T.P, ce.lpz, co.lpz); + /* check whether input was already in radians */ + if (d > T.tolerance) + e = proj_lpz_dist (T.P, T.e.lpz, co.lpz); + if (e < d) + d = e; + + /* or the tolerance may be based on euclidean distance */ + if (d > T.tolerance) + e = proj_xyz_dist (T.b.xyz, T.e.xyz); + if (e < d) + d = e; + + } + else + d = proj_xyz_dist (T.b.xyz, T.e.xyz); + if (d > T.tolerance) + return expect_message (d, args); + + another_success (); + + return 0; +} + + + +/*****************************************************************************/ +static int verbose (char *args) { +/***************************************************************************** + Tell the system how noisy it should be +******************************************************************************/ + int i = (int) proj_atof (args); + + /* if -q/--quiet flag has been given, we do nothing */ + if (T.verbosity < 0) + return 0; + + if (strlen (args)) + T.verbosity = i; + else + T.verbosity++; + return 0; +} + +/*****************************************************************************/ +static int comment (char *args) { +/***************************************************************************** + in line comment. Equivalent to # +******************************************************************************/ + (void) args; + return 0; +} + + +/*****************************************************************************/ +static int echo (char *args) { +/***************************************************************************** + Add user defined noise to the output stream +******************************************************************************/ +fprintf (T.fout, "%s\n", args); + return 0; +} + + + +static int dispatch (char *cmnd, char *args) { + int last_errno = proj_errno_reset (T.P); + + if (0==level%2) { + if (0==strcmp (cmnd, "BEGIN")) + level++; + return 0; + } + + if (0==strcmp (cmnd, "OPERATION")) return operation (args); + if (0==strcmp (cmnd, "operation")) return operation (args); + if (0==strcmp (cmnd, "ACCEPT")) return accept (args); + if (0==strcmp (cmnd, "accept")) return accept (args); + if (0==strcmp (cmnd, "EXPECT")) return expect (args); + if (0==strcmp (cmnd, "expect")) return expect (args); + if (0==strcmp (cmnd, "ROUNDTRIP")) return roundtrip (args); + if (0==strcmp (cmnd, "roundtrip")) return roundtrip (args); + if (0==strcmp (cmnd, "BANNER")) return banner (args); + if (0==strcmp (cmnd, "banner")) return banner (args); + if (0==strcmp (cmnd, "VERBOSE")) return verbose (args); + if (0==strcmp (cmnd, "verbose")) return verbose (args); + if (0==strcmp (cmnd, "DIRECTION")) return direction (args); + if (0==strcmp (cmnd, "direction")) return direction (args); + if (0==strcmp (cmnd, "TOLERANCE")) return tolerance (args); + if (0==strcmp (cmnd, "tolerance")) return tolerance (args); + if (0==strcmp (cmnd, "BUILTINS")) return builtins (args); + if (0==strcmp (cmnd, "builtins")) return builtins (args); + if (0==strcmp (cmnd, "ECHO")) return echo (args); + if (0==strcmp (cmnd, "echo")) return echo (args); + if (0==strcmp (cmnd, "END")) return finish_previous_operation (args), level++, 0; + if ('#'==cmnd[0]) return comment (args); + + if (proj_errno(T.P)) + printf ("#####***** ERRNO=%d\n", proj_errno(T.P)); + proj_errno_restore (T.P, last_errno); + return 0; +} + + + + + + + + +static int errmsg (int errlev, char *msg, ...) { + va_list args; + va_start(args, msg); + vfprintf(stdout, msg, args); + va_end(args); + if (errlev) + errno = errlev; + return errlev; +} + +#define skipspace(f, c) \ + do { \ + while (isspace (c=fgetc(f)) && !feof(f)){ \ + if ('\n'==c) lineno++; \ + } \ + if (feof(f)) \ + break; \ + } while (ungetc(c, f), 0) + +#define skipline(f, c) \ + do { \ + while ((c=fgetc(f)) && !feof(f)) { \ + if ((c=='\r') || (c=='\n')) \ + break; \ + } \ + skipspace (f, c); \ + } while (0) + + +/* skip whitespace at continuation line */ +#define continuation(f, buf, c) \ + if ((c=='\r')||(c=='\n')) { \ + if (c=='\n') lineno++; \ + next--; \ + while (isspace (c=fgetc(f)) && !feof(f)); \ + } + +static int get_inp (FILE *f, char *inp, int size) { + char *next; + int c = 0, esc; + char *endp = inp + size - 2; + + skipspace (f, c); + + for (c = esc = 0, next = inp; !feof(f); ) { + c = fgetc(f); + if (esc) { + continuation (f, next, c); + esc = 0; + /* handle escape sequences here */ + switch (c) { + case '\\': c = '\\'; break; + default: (void) c; + } + } + if (c=='\r') + break; + if (c=='\n') { + lineno++; + break; + } + + *next++ = (char) c; + if ('\\'==c) + esc = 1; + if (feof(f) || (next==endp)) + break; + } + *(next) = 0; + return (int) strlen(inp); +} + +static int get_cmnd (char *inp, char *cmnd, int len) { + cmnd[0] = 0; + while (isspace(*inp++)); + inp--; + while (len-- && !isspace(*inp) && *inp) + *cmnd++ = *inp++; + *cmnd = 0; + return len; +} + +static char *get_args (char *inp) { + char *args = inp; + while (isspace(*args++)) + if (0==*args) + return args; + while (!isspace(*++args)) + if (0==*args) + return args; + while (isspace(*args++)) + if (0==*args) + return args; + return --args; +} + + + + + + + + + + + + + + + + + + + +char tc32_utm32[] = { + " +proj=horner" + " +ellps=intl" + " +range=500000" + " +fwd_origin=877605.269066,6125810.306769" + " +inv_origin=877605.760036,6125811.281773" + " +deg=4" + " +fwd_v=6.1258112678e+06,9.9999971567e-01,1.5372750011e-10,5.9300860915e-15,2.2609497633e-19,4.3188227445e-05,2.8225130416e-10,7.8740007114e-16,-1.7453997279e-19,1.6877465415e-10,-1.1234649773e-14,-1.7042333358e-18,-7.9303467953e-15,-5.2906832535e-19,3.9984284847e-19" + " +fwd_u=8.7760574982e+05,9.9999752475e-01,2.8817299305e-10,5.5641310680e-15,-1.5544700949e-18,-4.1357045890e-05,4.2106213519e-11,2.8525551629e-14,-1.9107771273e-18,3.3615590093e-10,2.4380247154e-14,-2.0241230315e-18,1.2429019719e-15,5.3886155968e-19,-1.0167505000e-18" + " +inv_v=6.1258103208e+06,1.0000002826e+00,-1.5372762184e-10,-5.9304261011e-15,-2.2612705361e-19,-4.3188331419e-05,-2.8225549995e-10,-7.8529116371e-16,1.7476576773e-19,-1.6875687989e-10,1.1236475299e-14,1.7042518057e-18,7.9300735257e-15,5.2881862699e-19,-3.9990736798e-19" + " +inv_u=8.7760527928e+05,1.0000024735e+00,-2.8817540032e-10,-5.5627059451e-15,1.5543637570e-18,4.1357152105e-05,-4.2114813612e-11,-2.8523713454e-14,1.9109017837e-18,-3.3616407783e-10,-2.4382678126e-14,2.0245020199e-18,-1.2441377565e-15,-5.3885232238e-19,1.0167203661e-18" +}; + + +char sb_utm32[] = { + " +proj=horner" + " +ellps=intl" + " +range=500000" + " +tolerance=0.0005" + " +fwd_origin=4.94690026817276e+05,6.13342113183056e+06" + " +inv_origin=6.19480258923588e+05,6.13258568148837e+06" + " +deg=3" + " +fwd_c=6.13258562111350e+06,6.19480105709997e+05,9.99378966275206e-01,-2.82153291753490e-02,-2.27089979140026e-10,-1.77019590701470e-09,1.08522286274070e-14,2.11430298751604e-15" + " +inv_c=6.13342118787027e+06,4.94690181709311e+05,9.99824464710368e-01,2.82279070814774e-02,7.66123542220864e-11,1.78425334628927e-09,-1.05584823306400e-14,-3.32554258683744e-15" +}; + +static int pj_horner_selftest (void) { + PJ *P; + PJ_COORD a, b, c; + double dist; + + /* Real polynonia relating the technical coordinate system TC32 to "System 45 Bornholm" */ + P = proj_create (PJ_DEFAULT_CTX, tc32_utm32); + if (0==P) + return 10; + + a = b = proj_coord (0,0,0,0); + a.uv.v = 6125305.4245; + a.uv.u = 878354.8539; + c = a; + + /* Check roundtrip precision for 1 iteration each way, starting in forward direction */ + dist = proj_roundtrip (P, PJ_FWD, 1, &c); + if (dist > 0.01) + return 1; + + /* The complex polynomial transformation between the "System Storebaelt" and utm32/ed50 */ + P = proj_create (PJ_DEFAULT_CTX, sb_utm32); + if (0==P) + return 11; + + /* Test value: utm32_ed50(620000, 6130000) = sb_ed50(495136.8544, 6130821.2945) */ + a = b = c = proj_coord (0,0,0,0); + a.uv.v = 6130821.2945; + a.uv.u = 495136.8544; + c.uv.v = 6130000.0000; + c.uv.u = 620000.0000; + + /* Forward projection */ + b = proj_trans (P, PJ_FWD, a); + dist = proj_xy_dist (b.xy, c.xy); + if (dist > 0.001) + return 2; + + /* Inverse projection */ + b = proj_trans (P, PJ_INV, c); + dist = proj_xy_dist (b.xy, a.xy); + if (dist > 0.001) + return 3; + + /* Check roundtrip precision for 1 iteration each way */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 0.01) + return 4; + + proj_destroy(P); + return 0; +} + + + + + + + + + + + + +/* Testing quite a bit of the pj_obs_api as a side effect (inspired by pj_obs_api_test.c) */ +static int pj_cart_selftest (void) { + PJ_CONTEXT *ctx; + PJ *P; + PJ_COORD a, b, obs[2]; + PJ_COORD coord[2]; + + PJ_INFO info; + PJ_PROJ_INFO pj_info; + PJ_GRID_INFO grid_info; + PJ_INIT_INFO init_info; + + PJ_DERIVS derivs; + PJ_FACTORS factors; + + const PJ_OPERATIONS *oper_list; + const PJ_ELLPS *ellps_list; + const PJ_UNITS *unit_list; + const PJ_PRIME_MERIDIANS *pm_list; + + int err; + size_t n, sz; + double dist, h, t; + char *args[3] = {"proj=utm", "zone=32", "ellps=GRS80"}; + char *arg = {"+proj=utm +zone=32 +ellps=GRS80"}; + char buf[40]; + + /* An utm projection on the GRS80 ellipsoid */ + P = proj_create (PJ_DEFAULT_CTX, arg); + if (0==P) + return 1; + + + /* Clean up */ + proj_destroy (P); + + /* Same projection, now using argc/argv style initialization */ + P = proj_create_argv (PJ_DEFAULT_CTX, 3, args); + if (0==P) + return 2; + + /* zero initialize everything, then set (longitude, latitude) to (12, 55) */ + a = proj_coord (0,0,0,0); + /* a.lp: The coordinate part of a, interpreted as a classic LP pair */ + a.lp.lam = PJ_TORAD(12); + a.lp.phi = PJ_TORAD(55); + + /* Forward projection */ + b = proj_trans (P, PJ_FWD, a); + + /* Inverse projection */ + a = proj_trans (P, PJ_INV, b); + + /* Null projection */ + a = proj_trans (P, PJ_IDENT, a); + + /* Forward again, to get two linear items for comparison */ + a = proj_trans (P, PJ_FWD, a); + + dist = proj_xy_dist (a.xy, b.xy); + if (dist > 2e-9) + return 3; + + /* Clear any previous error */ + proj_errno_set (P, 0); + + /* Invalid projection */ + a = proj_trans (P, 42, a); + if (a.lpz.lam!=HUGE_VAL) + return 4; + err = proj_errno (P); + if (0==err) + return 5; + + /* Clear error again */ + proj_errno_set (P, 0); + + /* Clean up */ + proj_destroy (P); + + /* Now do some 3D transformations */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + if (0==P) + return 6; + + /* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 100) */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(12); + a.lpz.phi = PJ_TORAD(55); + a.lpz.z = 100; + + /* Forward projection: 3D-Cartesian-to-Ellipsoidal */ + b = proj_trans (P, PJ_FWD, a); + + /* Check roundtrip precision for 10000 iterations each way */ + dist = proj_roundtrip (P, PJ_FWD, 10000, &a); + dist = proj_roundtrip (P, PJ_INV, 10000, &b); + if (dist > 2e-9) + return 7; + + + /* Test at the North Pole */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(0); + a.lpz.phi = PJ_TORAD(90); + a.lpz.z = 100; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 1e-12) + return 8; + + /* Test at the South Pole */ + a = b = proj_coord (0,0,0,0); + a.lpz.lam = PJ_TORAD(0); + a.lpz.phi = PJ_TORAD(-90); + a.lpz.z = 100; + b = a; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip (P, PJ_FWD, 1, &a); + if (dist > 1e-12) + return 9; + + + /* Inverse projection: 3D-Cartesian-to-Ellipsoidal */ + b = proj_trans (P, PJ_INV, b); + + /* Move p to another context */ + ctx = proj_context_create (); + if (ctx==pj_get_default_ctx()) + return 10; + proj_context_set (P, ctx); + if (ctx != P->ctx) + return 11; + b = proj_trans (P, PJ_FWD, b); + + /* Move it back to the default context */ + proj_context_set (P, 0); + if (pj_get_default_ctx() != P->ctx) + return 12; + proj_context_destroy (ctx); + + /* We go on with the work - now back on the default context */ + b = proj_trans (P, PJ_INV, b); + proj_destroy (P); + + + /* Testing proj_trans_generic () */ + + /* An utm projection on the GRS80 ellipsoid */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=utm +zone=32 +ellps=GRS80"); + if (0==P) + return 13; + + obs[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + obs[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + sz = sizeof (PJ_COORD); + + /* Forward projection */ + a = proj_trans (P, PJ_FWD, obs[0]); + b = proj_trans (P, PJ_FWD, obs[1]); + + n = proj_trans_generic ( + P, PJ_FWD, + &(obs[0].lpz.lam), sz, 2, + &(obs[0].lpz.phi), sz, 2, + &(obs[0].lpz.z), sz, 2, + 0, sz, 0 + ); + if (2!=n) + return 14; + if (a.lpz.lam != obs[0].lpz.lam) return 15; + if (a.lpz.phi != obs[0].lpz.phi) return 16; + if (a.lpz.z != obs[0].lpz.z) return 17; + if (b.lpz.lam != obs[1].lpz.lam) return 18; + if (b.lpz.phi != obs[1].lpz.phi) return 19; + if (b.lpz.z != obs[1].lpz.z) return 20; + + /* now test the case of constant z */ + obs[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + obs[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + h = 27; + t = 33; + n = proj_trans_generic ( + P, PJ_FWD, + &(obs[0].lpz.lam), sz, 2, + &(obs[0].lpz.phi), sz, 2, + &h, 0, 1, + &t, 0, 1 + ); + if (2!=n) + return 21; + if (a.lpz.lam != obs[0].lpz.lam) return 22; + if (a.lpz.phi != obs[0].lpz.phi) return 23; + if (45 != obs[0].lpz.z) return 24; + if (b.lpz.lam != obs[1].lpz.lam) return 25; + if (b.lpz.phi != obs[1].lpz.phi) return 26; + if (50 != obs[1].lpz.z) return 27; /* NOTE: unchanged */ + if (50==h) return 28; + + /* test proj_trans_array () */ + + coord[0] = proj_coord (PJ_TORAD(12), PJ_TORAD(55), 45, 0); + coord[1] = proj_coord (PJ_TORAD(12), PJ_TORAD(56), 50, 0); + if (proj_trans_array (P, PJ_FWD, 2, coord)) + return 40; + + if (a.lpz.lam != coord[0].lpz.lam) return 41; + if (a.lpz.phi != coord[0].lpz.phi) return 42; + if (a.lpz.z != coord[0].lpz.z) return 43; + if (b.lpz.lam != coord[1].lpz.lam) return 44; + if (b.lpz.phi != coord[1].lpz.phi) return 45; + if (b.lpz.z != coord[1].lpz.z) return 46; + + /* Clean up after proj_trans_* tests */ + proj_destroy (P); + + /* test proj_create_crs_to_crs() */ + P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "epsg:25832", "epsg:25833", NULL); + if (P==0) + return 50; + + a.xy.x = 700000.0; + a.xy.y = 6000000.0; + b.xy.x = 307788.8761171057; + b.xy.y = 5999669.3036037628; + + a = proj_trans(P, PJ_FWD, a); + if (dist > 1e-7) + return 51; + proj_destroy(P); + + /* let's make sure that only entries in init-files results in a usable PJ */ + P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "proj=utm +zone=32 +datum=WGS84", "proj=utm +zone=33 +datum=WGS84", NULL); + if (P != 0) { + proj_destroy(P); + return 52; + } + proj_destroy(P); + + /* ********************************************************************** */ + /* Test info functions */ + /* ********************************************************************** */ + + /* proj_info() */ + /* this one is difficult to test, since the output changes with the setup */ + info = proj_info(); + if (info.version[0] != '\0' ) { + char tmpstr[64]; + sprintf(tmpstr, "%d.%d.%d", info.major, info.minor, info.patch); + if (strcmp(info.version, tmpstr)) return 55; + } + if (info.release[0] == '\0') return 56; + if (info.searchpath[0] == '\0') return 57; + + /* proj_pj_info() */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=august"); /* august has no inverse */ + if (proj_pj_info(P).has_inverse) { proj_destroy(P); return 60; } + proj_destroy(P); + + P = proj_create(PJ_DEFAULT_CTX, arg); + pj_info = proj_pj_info(P); + if ( !pj_info.has_inverse ) { proj_destroy(P); return 61; } + if ( strcmp(pj_info.definition, arg) ) { proj_destroy(P); return 62; } + if ( strcmp(pj_info.id, "utm") ) { proj_destroy(P); return 63; } + proj_destroy(P); + + /* proj_grid_info() */ + grid_info = proj_grid_info("egm96_15.gtx"); + if ( strlen(grid_info.filename) == 0 ) return 64; + if ( strcmp(grid_info.gridname, "egm96_15.gtx") ) return 65; + grid_info = proj_grid_info("nonexistinggrid"); + if ( strlen(grid_info.filename) > 0 ) return 66; + + /* proj_init_info() */ + init_info = proj_init_info("unknowninit"); + if ( strlen(init_info.filename) != 0 ) return 67; + + init_info = proj_init_info("epsg"); + /* Need to allow for "Unknown" until all commonly distributed EPSG-files comes with a metadata section */ + if ( strcmp(init_info.origin, "EPSG") && strcmp(init_info.origin, "Unknown") ) return 69; + if ( strcmp(init_info.name, "epsg") ) return 68; + + + + /* test proj_rtodms() and proj_dmstor() */ + if (strcmp("180dN", proj_rtodms(buf, M_PI, 'N', 'S'))) + return 70; + + if (proj_dmstor(&buf[0], NULL) != M_PI) + return 71; + + if (strcmp("114d35'29.612\"S", proj_rtodms(buf, -2.0, 'N', 'S'))) + return 72; + + /* we can't expect perfect numerical accuracy so testing with a tolerance */ + if (fabs(-2.0 - proj_dmstor(&buf[0], NULL)) > 1e-7) + return 73; + + + /* test proj_derivatives_retrieve() and proj_factors_retrieve() */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=merc"); + a = proj_coord (0,0,0,0); + a.lp.lam = PJ_TORAD(12); + a.lp.phi = PJ_TORAD(55); + + derivs = proj_derivatives(P, a.lp); + if (proj_errno(P)) + return 80; /* derivs not created correctly */ + + if ( fabs(derivs.x_l - 1.0) > 1e-5 ) return 81; + if ( fabs(derivs.x_p - 0.0) > 1e-5 ) return 82; + if ( fabs(derivs.y_l - 0.0) > 1e-5 ) return 83; + if ( fabs(derivs.y_p - 1.73959) > 1e-5 ) return 84; + + + factors = proj_factors(P, a.lp); + if (proj_errno(P)) + return 85; /* factors not created correctly */ + + /* check a few key characteristics of the Mercator projection */ + if (factors.omega != 0.0) return 86; /* angular distortion should be 0 */ + if (factors.thetap != M_PI_2) return 87; /* Meridian/parallel angle should be 90 deg */ + if (factors.conv != 0.0) return 88; /* meridian convergence should be 0 */ + + + proj_destroy(P); + + /* Check that proj_list_* functions work by looping through them */ + n = 0; + for (oper_list = proj_list_operations(); oper_list->id; ++oper_list) n++; + if (n == 0) return 90; + + n = 0; + for (ellps_list = proj_list_ellps(); ellps_list->id; ++ellps_list) n++; + if (n == 0) return 91; + + n = 0; + for (unit_list = proj_list_units(); unit_list->id; ++unit_list) n++; + if (n == 0) return 92; + + n = 0; + for (pm_list = proj_list_prime_meridians(); pm_list->id; ++pm_list) n++; + if (n == 0) return 93; + + + /* check io-predicates */ + + /* angular in on fwd, linear out */ + P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + if (0==P) return 0; + if (!proj_angular_input (P, PJ_FWD)) return 100; + if ( proj_angular_input (P, PJ_INV)) return 101; + if ( proj_angular_output (P, PJ_FWD)) return 102; + if (!proj_angular_output (P, PJ_INV)) return 103; + P->inverted = 1; + if ( proj_angular_input (P, PJ_FWD)) return 104; + if (!proj_angular_input (P, PJ_INV)) return 105; + if (!proj_angular_output (P, PJ_FWD)) return 106; + if ( proj_angular_output (P, PJ_INV)) return 107; + proj_destroy(P); + + /* angular in and out */ + P = proj_create(PJ_DEFAULT_CTX, + "+proj=molodensky +a=6378160 +rf=298.25 " + "+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 " + "+abridged " + ); + if (0==P) return 0; + if (!proj_angular_input (P, PJ_FWD)) return 108; + if (!proj_angular_input (P, PJ_INV)) return 109; + if (!proj_angular_output (P, PJ_FWD)) return 110; + if (!proj_angular_output (P, PJ_INV)) return 111; + P->inverted = 1; + if (!proj_angular_input (P, PJ_FWD)) return 112; + if (!proj_angular_input (P, PJ_INV)) return 113; + if (!proj_angular_output (P, PJ_FWD)) return 114; + if (!proj_angular_output (P, PJ_INV)) return 115; + proj_destroy(P); + + /* linear in and out */ + P = proj_create(PJ_DEFAULT_CTX, + " +proj=helmert +ellps=GRS80" + " +x=0.0127 +y=0.0065 +z=-0.0209 +s=0.00195" + " +rx=-0.00039 +ry=0.00080 +rz=-0.00114" + " +dx=-0.0029 +dy=-0.0002 +dz=-0.0006 +ds=0.00001" + " +drx=-0.00011 +dry=-0.00019 +drz=0.00007" + " +epoch=1988.0 +transpose" + ); + if (0==P) return 0; + if (proj_angular_input (P, PJ_FWD)) return 116; + if (proj_angular_input (P, PJ_INV)) return 117; + if (proj_angular_output (P, PJ_FWD)) return 118; + if (proj_angular_output (P, PJ_INV)) return 119; + P->inverted = 1; + if (proj_angular_input (P, PJ_FWD)) return 120; + if (proj_angular_input (P, PJ_INV)) return 121; + if (proj_angular_output (P, PJ_FWD)) return 122; + if (proj_angular_output (P, PJ_INV)) return 123; + proj_destroy(P); + + + return 0; +} + + + + + + + + + + + + + + + +static int test_time(char* args, double tol, double t_in, double t_exp) { + PJ_COORD in, out; + PJ *P = proj_create(PJ_DEFAULT_CTX, args); + int ret = 0; + + if (P == 0) + return 5; + + in.xyzt.t = t_in; + + out = proj_trans(P, PJ_FWD, in); + if (fabs(out.xyzt.t - t_exp) > tol) { + proj_log_error(P, "out: %10.10g, expect: %10.10g", out.xyzt.t, t_exp); + ret = 1; + } + out = proj_trans(P, PJ_INV, out); + if (fabs(out.xyzt.t - t_in) > tol) { + proj_log_error(P, "out: %10.10g, expect: %10.10g", out.xyzt.t, t_in); + ret = 2; + } + pj_free(P); + + proj_log_level(NULL, 0); + return ret; +} + +static int test_xyz(char* args, double tol, PJ_TRIPLET in, PJ_TRIPLET exp) { + PJ_COORD out, obs_in; + PJ *P = proj_create(PJ_DEFAULT_CTX, args); + int ret = 0; + + if (P == 0) + return 5; + + obs_in.xyz = in.xyz; + out = proj_trans(P, PJ_FWD, obs_in); + if (proj_xyz_dist(out.xyz, exp.xyz) > tol) { + printf("exp: %10.10g, %10.10g, %10.10g\n", exp.xyz.x, exp.xyz.y, exp.xyz.z); + printf("out: %10.10g, %10.10g, %10.10g\n", out.xyz.x, out.xyz.y, out.xyz.z); + ret = 1; + } + + out = proj_trans(P, PJ_INV, out); + if (proj_xyz_dist(out.xyz, in.xyz) > tol) { + printf("exp: %g, %g, %g\n", in.xyz.x, in.xyz.y, in.xyz.z); + printf("out: %g, %g, %g\n", out.xyz.x, out.xyz.y, out.xyz.z); + ret += 2; + } + proj_destroy(P); + proj_log_level(NULL, 0); + return ret; +} + + +static int pj_unitconvert_selftest (void) { + int ret = 0; + char args1[] = "+proj=unitconvert +t_in=decimalyear +t_out=decimalyear"; + double in1 = 2004.25; + + char args2[] = "+proj=unitconvert +t_in=gps_week +t_out=gps_week"; + double in2 = 1782.0; + + char args3[] = "+proj=unitconvert +t_in=mjd +t_out=mjd"; + double in3 = 57390.0; + + char args4[] = "+proj=unitconvert +t_in=gps_week +t_out=decimalyear"; + double in4 = 1877.71428, exp4 = 2016.0; + + char args5[] = "+proj=unitconvert +xy_in=m +xy_out=dm +z_in=cm +z_out=mm"; + PJ_TRIPLET in5 = {{55.25, 23.23, 45.5}}, exp5 = {{552.5, 232.3, 455.0}}; + + char args6[] = "+proj=unitconvert +xy_in=m +xy_out=m +z_in=m +z_out=m"; + PJ_TRIPLET in6 = {{12.3, 45.6, 7.89}}; + + ret = test_time(args1, 1e-6, in1, in1); if (ret) return ret + 10; + ret = test_time(args2, 1e-6, in2, in2); if (ret) return ret + 20; + ret = test_time(args3, 1e-6, in3, in3); if (ret) return ret + 30; + ret = test_time(args4, 1e-6, in4, exp4); if (ret) return ret + 40; + ret = test_xyz (args5, 1e-10, in5, exp5); if (ret) return ret + 50; + ret = test_xyz (args6, 1e-10, in6, in6); if (ret) return ret + 50; + + return 0; + +} + + + diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake index 1be10362..81de451e 100644 --- a/src/lib_proj.cmake +++ b/src/lib_proj.cmake @@ -45,6 +45,7 @@ SET(SRC_LIBPROJ_PJ PJ_airy.c PJ_aitoff.c PJ_august.c + PJ_axisswap.c PJ_bacon.c PJ_bipc.c PJ_boggs.c @@ -58,6 +59,7 @@ SET(SRC_LIBPROJ_PJ PJ_collg.c PJ_comill.c PJ_crast.c + PJ_deformation.c PJ_denoy.c PJ_eck1.c PJ_eck2.c @@ -184,7 +186,6 @@ SET(SRC_LIBPROJ_CORE pj_fwd3d.c pj_gauss.c pj_gc_reader.c - pj_generic_selftest.c pj_geocent.c pj_gridcatalog.c pj_gridinfo.c @@ -201,7 +202,7 @@ SET(SRC_LIBPROJ_CORE pj_mlfn.c pj_msfn.c pj_mutex.c - pj_obs_api.c + proj_4D_api.c pj_internal.c proj_internal.h pj_open_lib.c @@ -210,7 +211,6 @@ SET(SRC_LIBPROJ_CORE pj_pr_list.c pj_qsfn.c pj_release.c - pj_run_selftests.c pj_strerrno.c pj_transform.c pj_tsfn.c diff --git a/src/makefile.vc b/src/makefile.vc index ac5acf15..6bc06bd1 100644 --- a/src/makefile.vc +++ b/src/makefile.vc @@ -56,12 +56,12 @@ support = \ pj_utils.obj pj_gridlist.obj pj_gridinfo.obj \ proj_mdist.obj pj_mutex.obj pj_initcache.obj \ pj_ctx.obj pj_fileapi.obj pj_log.obj pj_apply_vgridshift.obj \ - pj_strtod.obj pj_run_selftests.obj pj_generic_selftest.obj \ - pj_internal.obj + pj_strtod.obj pj_internal.obj pipeline = \ - pj_obs_api.obj PJ_cart.obj PJ_pipeline.obj PJ_horner.obj PJ_helmert.obj \ - PJ_vgridshift.obj PJ_hgridshift.obj PJ_unitconvert.obj PJ_molodensky.obj + proj_4D_api.obj PJ_cart.obj PJ_pipeline.obj PJ_horner.obj PJ_helmert.obj \ + PJ_vgridshift.obj PJ_hgridshift.obj PJ_unitconvert.obj PJ_molodensky.obj \ + PJ_deformation.obj PJ_axisswap.obj geodesic = geodesic.obj @@ -71,12 +71,15 @@ PROJEXE_OBJ = proj.obj gen_cheb.obj p_series.obj emess.obj CS2CSEXE_OBJ = cs2cs.obj gen_cheb.obj p_series.obj emess.obj GEODEXE_OBJ = geod.obj geod_set.obj geod_interface.obj emess.obj CCTEXE_OBJ = cct.obj proj_strtod.obj +GIEEXE_OBJ = gie.obj proj_strtod.obj + MULTISTRESSTEST_OBJ = multistresstest.obj PROJ_DLL = proj$(VERSION).dll PROJ_EXE = proj.exe CS2CS_EXE = cs2cs.exe GEOD_EXE = geod.exe CCT_EXE = cct.exe +GIE_EXE = gie.exe NAD2BIN_EXE = nad2bin.exe MULTISTRESSTEST_EXE = multistresstest.exe @@ -85,7 +88,7 @@ CFLAGS = /nologo -I. -DPROJ_LIB=\"$(PROJ_LIB_DIR)\" \ default: all -all: proj.lib $(PROJ_EXE) $(CS2CS_EXE) $(GEOD_EXE) $(CCT_EXE) $(NAD2BIN_EXE) +all: proj.lib $(PROJ_EXE) $(CS2CS_EXE) $(GEOD_EXE) $(CCT_EXE) $(GIE_EXE) $(NAD2BIN_EXE) proj.lib: $(LIBOBJ) if exist proj.lib del proj.lib @@ -114,6 +117,10 @@ $(CCT_EXE): $(CCTEXE_OBJ) $(EXE_PROJ) cl $(CCTEXE_OBJ) $(EXE_PROJ) if exist $(CCT_EXE).manifest mt -manifest $(CCT_EXE).manifest -outputresource:$(CCT_EXE);1 +$(GIE_EXE): $(GIEEXE_OBJ) $(EXE_PROJ) + cl $(GIEEXE_OBJ) $(EXE_PROJ) + if exist $(GIE_EXE).manifest mt -manifest $(GIE_EXE).manifest -outputresource:$(GIE_EXE);1 + $(NAD2BIN_EXE): nad2bin.obj emess.obj $(EXE_PROJ) cl nad2bin.obj emess.obj $(EXE_PROJ) diff --git a/src/mk_cheby.c b/src/mk_cheby.c index a7cd75c5..b074650a 100644 --- a/src/mk_cheby.c +++ b/src/mk_cheby.c @@ -19,18 +19,23 @@ makeT(int nru, int nrv) { Tseries *T; int i; - if ((T = (Tseries *)pj_malloc(sizeof(Tseries))) && - (T->cu = (struct PW_COEF *)pj_malloc( - sizeof(struct PW_COEF) * nru)) && - (T->cv = (struct PW_COEF *)pj_malloc( - sizeof(struct PW_COEF) * nrv))) { - for (i = 0; i < nru; ++i) - T->cu[i].c = 0; - for (i = 0; i < nrv; ++i) - T->cv[i].c = 0; - return T; - } else + if (!(T = (Tseries *)pj_malloc(sizeof(Tseries)))) return 0; + if (!(T->cu = (struct PW_COEF *)pj_malloc(sizeof(struct PW_COEF) * nru))) { + pj_dalloc(T); + return 0; + } + if (!(T->cv = (struct PW_COEF *)pj_malloc(sizeof(struct PW_COEF) * nrv))) { + pj_dalloc(T->cu); + pj_dalloc(T); + return 0; + } + + for (i = 0; i < nru; ++i) + T->cu[i].c = 0; + for (i = 0; i < nrv; ++i) + T->cv[i].c = 0; + return T; } Tseries * mk_cheby(projUV a, projUV b, double res, projUV *resid, projUV (*func)(projUV), @@ -40,9 +45,12 @@ mk_cheby(projUV a, projUV b, double res, projUV *resid, projUV (*func)(projUV), projUV **w; double cutres; - if (!(w = (projUV **)vector2(nu, nv, sizeof(projUV))) || - !(ncu = (int *)vector1(nu + nv, sizeof(int)))) + if (!(w = (projUV **)vector2(nu, nv, sizeof(projUV)))) return 0; + if (!(ncu = (int *)vector1(nu + nv, sizeof(int)))) { + freev2((void **)w, nu); + return 0; + } ncv = ncu + nu; if (!bchgen(a, b, nu, nv, w, func)) { projUV *s; diff --git a/src/nad_cvt.c b/src/nad_cvt.c index f48f9e0d..c913511f 100644 --- a/src/nad_cvt.c +++ b/src/nad_cvt.c @@ -1,68 +1,70 @@ #define PJ_LIB__ -#include <projects.h> -#define MAX_TRY 9 +#include "projects.h" +#define MAX_ITERATIONS 10 #define TOL 1e-12 - LP -nad_cvt(LP in, int inverse, struct CTABLE *ct) { - LP t, tb; - if (in.lam == HUGE_VAL) - return in; - /* normalize input to ll origin */ - tb = in; - tb.lam -= ct->ll.lam; - tb.phi -= ct->ll.phi; - tb.lam = adjlon(tb.lam - M_PI) + M_PI; - t = nad_intr(tb, ct); - if (inverse) { - LP del, dif; - int i = MAX_TRY; +LP nad_cvt(LP in, int inverse, struct CTABLE *ct) { + LP t, tb,del, dif; + int i = MAX_ITERATIONS; + const double toltol = TOL*TOL; - if (t.lam == HUGE_VAL) return t; - t.lam = tb.lam + t.lam; - t.phi = tb.phi - t.phi; + if (in.lam == HUGE_VAL) + return in; - do { - del = nad_intr(t, ct); + /* normalize input to ll origin */ + tb = in; + tb.lam -= ct->ll.lam; + tb.phi -= ct->ll.phi; + tb.lam = adjlon (tb.lam - M_PI) + M_PI; - /* This case used to return failure, but I have - changed it to return the first order approximation - of the inverse shift. This avoids cases where the - grid shift *into* this grid came from another grid. - While we aren't returning optimally correct results - I feel a close result in this case is better than - no result. NFW - To demonstrate use -112.5839956 49.4914451 against - the NTv2 grid shift file from Canada. */ - if (del.lam == HUGE_VAL) - { - if( getenv( "PROJ_DEBUG" ) != NULL ) - fprintf( stderr, - "Inverse grid shift iteration failed, presumably at grid edge.\n" - "Using first approximation.\n" ); - /* return del */; - break; - } + t = nad_intr (tb, ct); + if (t.lam == HUGE_VAL) + return t; - t.lam -= dif.lam = t.lam - del.lam - tb.lam; - t.phi -= dif.phi = t.phi + del.phi - tb.phi; - } while (i-- && fabs(dif.lam) > TOL && fabs(dif.phi) > TOL); - if (i < 0) { - if( getenv( "PROJ_DEBUG" ) != NULL ) - fprintf( stderr, - "Inverse grid shift iterator failed to converge.\n" ); - t.lam = t.phi = HUGE_VAL; - return t; - } - in.lam = adjlon(t.lam + ct->ll.lam); - in.phi = t.phi + ct->ll.phi; - } else { - if (t.lam == HUGE_VAL) - in = t; - else { - in.lam -= t.lam; - in.phi += t.phi; - } - } - return in; + if (!inverse) { + in.lam -= t.lam; + in.phi += t.phi; + return in; + } + + t.lam = tb.lam + t.lam; + t.phi = tb.phi - t.phi; + + do { + del = nad_intr(t, ct); + + /* This case used to return failure, but I have + changed it to return the first order approximation + of the inverse shift. This avoids cases where the + grid shift *into* this grid came from another grid. + While we aren't returning optimally correct results + I feel a close result in this case is better than + no result. NFW + To demonstrate use -112.5839956 49.4914451 against + the NTv2 grid shift file from Canada. */ + if (del.lam == HUGE_VAL) + break; + + dif.lam = t.lam - del.lam - tb.lam; + dif.phi = t.phi + del.phi - tb.phi; + t.lam -= dif.lam; + t.phi -= dif.phi; + + } while (--i && (dif.lam*dif.lam + dif.phi*dif.phi > toltol)); /* prob. slightly faster than hypot() */ + + if (i==0) { + /* If we had access to a context, this should go through pj_log, and we should set ctx->errno */ + if (getenv ("PROJ_DEBUG")) + fprintf( stderr, "Inverse grid shift iterator failed to converge.\n" ); + t.lam = t.phi = HUGE_VAL; + return t; + } + + /* and again: pj_log and ctx->errno */ + if (del.lam==HUGE_VAL && getenv ("PROJ_DEBUG")) + fprintf (stderr, "Inverse grid shift iteration failed, presumably at grid edge.\nUsing first approximation.\n"); + + in.lam = adjlon (t.lam + ct->ll.lam); + in.phi = t.phi + ct->ll.phi; + return in; } diff --git a/src/nad_init.c b/src/nad_init.c index 0a28e200..a9082f8f 100644 --- a/src/nad_init.c +++ b/src/nad_init.c @@ -224,7 +224,7 @@ struct CTABLE *nad_ctable2_init( projCtx ctx, PAFile fid ) ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE)); if( ct == NULL ) { - pj_ctx_set_errno( ctx, -38 ); + pj_ctx_set_errno( ctx, ENOMEM ); return NULL; } @@ -241,6 +241,7 @@ struct CTABLE *nad_ctable2_init( projCtx ctx, PAFile fid ) || ct->lim.phi < 1 || ct->lim.phi > 100000 ) { pj_ctx_set_errno( ctx, -38 ); + pj_dalloc( ct ); return NULL; } diff --git a/src/optargpm.h b/src/optargpm.h index 6be2c9ef..23e375f8 100644 --- a/src/optargpm.h +++ b/src/optargpm.h @@ -1,6 +1,6 @@ /*********************************************************************** - OPTARGPM - a header-only library for decoding + OPTARGPM - a header-only library for decoding PROJ.4 style command line options Thomas Knudsen, 2017-09-10 @@ -10,15 +10,15 @@ For PROJ.4 command line programs, we have a somewhat complex option decoding situation, since we have to navigate in a cocktail of classic single letter style options, prefixed by "-", GNU style long options -prefixwd by "--", transformation specification elements prefixed by "+", -and input file names prefixed by "" nothing. +prefixed by "--", transformation specification elements prefixed by "+", +and input file names prefixed by "" (i.e. nothing). Hence, classic getopt.h style decoding does not cut the mustard, so this is an attempt to catch up and chop the ketchup. Since optargpm (for "optarg plus minus") does not belong, in any obvious way, in any systems development library, it is provided as -a "header only" library. +a "header only" library. While this is conventional in C++, it is frowned at in plain C. But frown away - "header only" has its places, and this is one of @@ -48,15 +48,15 @@ Operator specs are +proj=utm +zone=32 +ellps=GRS80 Operands are bar baz -While claiming neither to save the world, nor to hint at the "shape of -jazz to come", at least optargpm has shown useful in constructing cs2cs +While neither claiming to save the world, nor to hint at the "shape of +jazz to come", at least optargpm has shown useful in constructing cs2cs style transformation filters. Supporting a wide range of option syntax, the getoptpm API is somewhat quirky, but also compact, consisting of one data type, 3(+2) functions, and one enumeration: -OPTARGS +OPTARGS Housekeeping data type. An instance of OPTARGS is conventionally called o or opt opt_parse (opt, argc, argv ...): @@ -105,7 +105,7 @@ int main(int argc, char **argv) { FILE *out = stdout; char *longflags[] = {"v=verbose", "h=help", 0}; char *longkeys[] = {"o=output", "hello", 0}; - + o = opt_parse (argc, argv, "hv", "o", longflags, longkeys); if (0==o) return 0; @@ -116,7 +116,7 @@ int main(int argc, char **argv) { exit (0); } - if (opt_given (o, "v")) + if (opt_given (o, "v")) puts ("Feeling chatty today?"); if (opt_given (o, "hello")) { @@ -126,8 +126,8 @@ int main(int argc, char **argv) { if (opt_given (o, "o")) out = fopen (opt_arg (o, "output"), "rt"); // Note: "output" translates to "o" internally - - // Setup transformation + + // Setup transformation P = proj_create_argv (0, o->pargc, o->pargv); // Loop over all lines of all input files @@ -207,6 +207,7 @@ static int opt_raise_flag (OPTARGS *opt, int ordinal); static int opt_ordinal (OPTARGS *opt, char *option); int opt_given (OPTARGS *opt, char *option); char *opt_arg (OPTARGS *opt, char *option); +char *opt_strip_path (char *full_name); OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, const char **longflags, const char **longkeys); #define opt_eof_handler(opt) if (opt_eof (opt)) {continue;} else {;} @@ -223,7 +224,7 @@ struct OPTARGS { char *optarg[256]; /* optarg[(int) 'f'] holds a pointer to the argument of option "-f" */ char *flags; /* a list of flag style options supported, e.g. "hv" (help and verbose) */ char *keys; /* a list of key/value style options supported, e.g. "o" (output) */ - const char **longflags; /* long flags, {"help", "verbose"}, or {"h=help", "v=verbose"}, to indicate homologous short options */ + const char **longflags; /* long flags, {"help", "verbose"}, or {"h=help", "v=verbose"}, to indicate homologous short options */ const char **longkeys; /* e.g. {"output"} or {o=output"} to support --output=/path/to/output-file. In the latter case, */ /* all operations on "--output" gets redirected to "-o", so user code need handle arguments to "-o" only */ }; @@ -264,7 +265,7 @@ int opt_input_loop (OPTARGS *opt, int binary) { } opt->record_index = 0; - + /* no input files specified - read from stdin */ if ((0==opt->fargc) && (0==opt->input)) { opt->input = stdin; @@ -372,7 +373,8 @@ static int opt_ordinal (OPTARGS *opt, char *option) { } } - + /* kill some potential compiler warnings about unused functions */ + (void) opt_eof (0); return 0; } @@ -397,27 +399,31 @@ char *opt_arg (OPTARGS *opt, char *option) { return opt->optarg[ordinal]; } +char *opt_strip_path (char *full_name) { + char *last_path_delim, *stripped_name = full_name; + + last_path_delim = strrchr (stripped_name, '\\'); + if (last_path_delim > stripped_name) + stripped_name = last_path_delim + 1; + + last_path_delim = strrchr (stripped_name, '/'); + if (last_path_delim > stripped_name) + stripped_name = last_path_delim + 1; + return stripped_name; +} /* split command line options into options/flags ("-" style), projdefs ("+" style) and input file args */ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, const char **longflags, const char **longkeys) { int i, j; OPTARGS *o; - char *last_path_delim; - + o = (OPTARGS *) calloc (1, sizeof(OPTARGS)); if (0==o) return 0; o->argc = argc; o->argv = argv; - o->progname = argv[0]; - last_path_delim = strrchr (argv[0], '\\'); - if (last_path_delim > o->progname) - o->progname = last_path_delim; - last_path_delim = strrchr (argv[0], '/'); - if (last_path_delim > o->progname) - o->progname = last_path_delim; - + o->progname = opt_strip_path (argv[0]); /* Reset all flags */ for (i = 0; i < (int) strlen (flags); i++) @@ -426,7 +432,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, /* Flag args for all argument taking options as "unset" */ for (i = 0; i < (int) strlen (keys); i++) o->optarg[(int) keys[i]] = argv[0]; - + /* Hence, undefined/illegal options have an argument of 0 */ /* long opts are handled similarly, but are mapped to the high bit character range (above 128) */ @@ -444,7 +450,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, if (0==strchr (flags, longflags[i][0])) { fprintf (stderr, "%s: Invalid alias - '%s'. Valid short flags are '%s'\n", o->progname, longflags[i], flags); free (o); - return 0; + return 0; } } for (i = 0; longkeys && longkeys[i]; i++) { @@ -456,7 +462,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, if (0==strchr (keys, longkeys[i][0])) { fprintf (stderr, "%s: Invalid alias - '%s'. Valid short flags are '%s'\n", o->progname, longkeys[i], keys); free (o); - return 0; + return 0; } } @@ -501,7 +507,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, char cstring[2], *crepr = cstring; cstring[0] = (char) c; cstring[1] = 0; - + /* Long style flags and options (--long_opt_name, --long_opt_namr arg, --long_opt_name=arg) */ if (c== (int)'-') { @@ -524,7 +530,7 @@ OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, o->optarg[c] = equals + 1; break; } - + /* "outline" --foo bar style arg */ if (!opt_is_flag (o, c)) { if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0])) diff --git a/src/pj_apply_gridshift.c b/src/pj_apply_gridshift.c index 91e2de26..a2267cbd 100644 --- a/src/pj_apply_gridshift.c +++ b/src/pj_apply_gridshift.c @@ -2,7 +2,7 @@ * Project: PROJ.4 * Purpose: Apply datum shifts based on grid shift files (normally NAD27 to * NAD83 or the reverse). This module is responsible for keeping - * a list of loaded grids, and calling with each one that is + * a list of loaded grids, and calling with each one that is * allowed for a given datum (expressed as the nadgrids= parameter). * Author: Frank Warmerdam, warmerdam@pobox.com * @@ -30,9 +30,10 @@ #define PJ_LIB__ -#include <projects.h> #include <string.h> #include <math.h> +#include "proj_internal.h" +#include "projects.h" /************************************************************************/ /* pj_apply_gridshift() */ @@ -43,7 +44,7 @@ /* it to honour our public api. */ /************************************************************************/ -int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse, +int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse, long point_count, int point_offset, double *x, double *y, double *z ) @@ -51,16 +52,16 @@ int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse, PJ_GRIDINFO **gridlist; int grid_count; int ret; - + gridlist = pj_gridlist_from_nadgrids( ctx, nadgrids, &grid_count ); if( gridlist == NULL || grid_count == 0 ) return ctx->last_errno; - ret = pj_apply_gridshift_3( ctx, gridlist, grid_count, inverse, + ret = pj_apply_gridshift_3( ctx, gridlist, grid_count, inverse, point_count, point_offset, x, y, z ); - /* + /* ** Note this frees the array of grid list pointers, but not the grids ** which is as intended. The grids themselves live on. */ @@ -72,13 +73,13 @@ int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse, /************************************************************************/ /* pj_apply_gridshift_2() */ /* */ -/* This implementation takes uses the gridlist from a coordinate */ +/* This implementation uses the gridlist from a coordinate */ /* system definition. If the gridlist has not yet been */ /* populated in the coordinate system definition we set it up */ /* now. */ /************************************************************************/ -int pj_apply_gridshift_2( PJ *defn, int inverse, +int pj_apply_gridshift_2( PJ *defn, int inverse, long point_count, int point_offset, double *x, double *y, double *z ) @@ -86,10 +87,10 @@ int pj_apply_gridshift_2( PJ *defn, int inverse, if( defn->catalog_name != NULL ) return pj_gc_apply_gridshift( defn, inverse, point_count, point_offset, x, y, z ); - + if( defn->gridlist == NULL ) { - defn->gridlist = + defn->gridlist = pj_gridlist_from_nadgrids( pj_get_ctx( defn ), pj_param(defn->ctx, defn->params,"snadgrids").s, &(defn->gridlist_count) ); @@ -97,12 +98,75 @@ int pj_apply_gridshift_2( PJ *defn, int inverse, if( defn->gridlist == NULL || defn->gridlist_count == 0 ) return defn->ctx->last_errno; } - + return pj_apply_gridshift_3( pj_get_ctx( defn ), - defn->gridlist, defn->gridlist_count, inverse, + defn->gridlist, defn->gridlist_count, inverse, point_count, point_offset, x, y, z ); } +/************************************************************************/ +/* find_ctable() */ +/* */ +/* Determine which grid is the correct given an input coordinate. */ +/************************************************************************/ + +static struct CTABLE* find_ctable(projCtx ctx, LP input, int grid_count, PJ_GRIDINFO **tables) { + int itable; + + /* keep trying till we find a table that works */ + for( itable = 0; itable < grid_count; itable++ ) + { + + PJ_GRIDINFO *gi = tables[itable]; + struct CTABLE *ct = gi->ct; + double epsilon = (fabs(ct->del.phi)+fabs(ct->del.lam))/10000.0; + /* skip tables that don't match our point at all. */ + if ( ct->ll.phi - epsilon > input.phi + || ct->ll.lam - epsilon > input.lam + || (ct->ll.phi + (ct->lim.phi-1) * ct->del.phi + epsilon < input.phi) + || (ct->ll.lam + (ct->lim.lam-1) * ct->del.lam + epsilon < input.lam) ) { + continue; + } + + /* If we have child nodes, check to see if any of them apply. */ + while( gi->child ) + { + PJ_GRIDINFO *child; + + for( child = gi->child; child != NULL; child = child->next ) + { + struct CTABLE *ct1 = child->ct; + epsilon = (fabs(ct1->del.phi)+fabs(ct1->del.lam))/10000.0; + + if( ct1->ll.phi - epsilon > input.phi + || ct1->ll.lam - epsilon > input.lam + || (ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi + epsilon < input.phi) + || (ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam + epsilon < input.lam) ) { + continue; + } + break; + } + + /* If we didn't find a child then nothing more to do */ + if( child == NULL ) break; + + /* Otherwise use the child, first checking it's children */ + gi = child; + ct = child->ct; + } + /* load the grid shift info if we don't have it. */ + if( ct->cvs == NULL) { + if (!pj_gridinfo_load( ctx, gi ) ) { + pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); + return NULL; + } + } + /* if we get this far we have found a suitable grid */ + return ct; + } + + return NULL; +} /************************************************************************/ /* pj_apply_gridshift_3() */ @@ -113,16 +177,16 @@ int pj_apply_gridshift_2( PJ *defn, int inverse, int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **tables, int grid_count, int inverse, long point_count, int point_offset, double *x, double *y, double *z ) - { int i; + struct CTABLE *ct; static int debug_count = 0; (void) z; if( tables == NULL || grid_count == 0 ) { - pj_ctx_set_errno( ctx, -38); - return -38; + pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + return PJD_ERR_FAILED_TO_LOAD_GRID; } ctx->last_errno = 0; @@ -138,100 +202,42 @@ int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **tables, int grid_count, output.phi = HUGE_VAL; output.lam = HUGE_VAL; - /* keep trying till we find a table that works */ - for( itable = 0; itable < grid_count; itable++ ) + ct = find_ctable(ctx, input, grid_count, tables); + if( ct != NULL ) { - PJ_GRIDINFO *gi = tables[itable]; - struct CTABLE *ct = gi->ct; - double epsilon = (fabs(ct->del.phi)+fabs(ct->del.lam))/10000.0; - - /* skip tables that don't match our point at all. */ - if( ct->ll.phi - epsilon > input.phi - || ct->ll.lam - epsilon > input.lam - || (ct->ll.phi + (ct->lim.phi-1) * ct->del.phi + epsilon - < input.phi) - || (ct->ll.lam + (ct->lim.lam-1) * ct->del.lam + epsilon - < input.lam) ) - continue; - - /* If we have child nodes, check to see if any of them apply. */ - while( gi->child ) - { - PJ_GRIDINFO *child; - - for( child = gi->child; child != NULL; child = child->next ) - { - struct CTABLE *ct1 = child->ct; - epsilon = - (fabs(ct1->del.phi)+fabs(ct1->del.lam))/10000.0; - - if( ct1->ll.phi - epsilon > input.phi - || ct1->ll.lam - epsilon > input.lam - || (ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi + epsilon - < input.phi) - || (ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam + epsilon - < input.lam) ) - continue; - - break; - } - - /* If we didn't find a child then nothing more to do */ - - if( child == NULL ) break; - - /* Otherwise use the child, first checking it's children */ - - gi = child; - ct = child->ct; - } - - /* load the grid shift info if we don't have it. */ - if( ct->cvs == NULL && !pj_gridinfo_load( ctx, gi ) ) - { - pj_ctx_set_errno( ctx, -38 ); - return -38; - } - output = nad_cvt( input, inverse, ct ); - if( output.lam != HUGE_VAL ) - { - if( debug_count++ < 20 ) - pj_log( ctx, PJ_LOG_DEBUG_MINOR, - "pj_apply_gridshift(): used %s", ct->id ); - break; - } } - if( output.lam == HUGE_VAL ) + if ( output.lam != HUGE_VAL && debug_count++ < 20 ) + pj_log( ctx, PJ_LOG_DEBUG_MINOR, "pj_apply_gridshift(): used %s", ct->id ); + + if ( output.lam == HUGE_VAL ) { if( ctx->debug_level >= PJ_LOG_DEBUG_MAJOR ) { pj_log( ctx, PJ_LOG_DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for\n" " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, + x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG ); for( itable = 0; itable < grid_count; itable++ ) { PJ_GRIDINFO *gi = tables[itable]; if( itable == 0 ) - pj_log( ctx, PJ_LOG_DEBUG_MAJOR, - " tried: %s", gi->gridname ); + pj_log( ctx, PJ_LOG_DEBUG_MAJOR, " tried: %s", gi->gridname ); else - pj_log( ctx, PJ_LOG_DEBUG_MAJOR, - ",%s", gi->gridname ); + pj_log( ctx, PJ_LOG_DEBUG_MAJOR, ",%s", gi->gridname ); } } - /* - * We don't actually have any machinery currently to set the - * following macro, so this is mostly kept here to make it clear - * how we ought to operate if we wanted to make it super clear + /* + * We don't actually have any machinery currently to set the + * following macro, so this is mostly kept here to make it clear + * how we ought to operate if we wanted to make it super clear * that an error has occurred when points are outside our available - * datum shift areas. But if this is on, we will find that "low - * value" points on the fringes of some datasets will completely - * fail causing lots of problems when it is more or less ok to + * datum shift areas. But if this is on, we will find that "low + * value" points on the fringes of some datasets will completely + * fail causing lots of problems when it is more or less ok to * just not apply a datum shift. So rather than deal with * that we just fallback to no shift. (see also bug #45). */ @@ -252,3 +258,92 @@ int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **tables, int grid_count, return 0; } +/**********************************************/ +int proj_hgrid_init(PJ* P, const char *grids) { +/********************************************** + + Initizalize and populate list of horizontal + grids. + + Takes a PJ-object and the plus-parameter + name that is used in the proj-string to + specify the grids to load, e.g. "+grids". + The + should be left out here. + + Returns the number of loaded grids. + +***********************************************/ + + /* prepend "s" to the "grids" string to allow usage with pj_param */ + char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) ); + sprintf(sgrids, "%s%s", "s", grids); + + if (P->gridlist == NULL) { + P->gridlist = pj_gridlist_from_nadgrids( + P->ctx, + pj_param(P->ctx, P->params, sgrids).s, + &(P->gridlist_count) + ); + + if( P->gridlist == NULL || P->gridlist_count == 0 ) { + pj_dealloc(sgrids); + return 0; + } + } + + if (P->gridlist_count == 0) { + proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID); + } + + pj_dealloc(sgrids); + return P->gridlist_count; +} + +/********************************************/ +/* proj_hgrid_value() */ +/* */ +/* Return coordinate offset in grid */ +/********************************************/ +LP proj_hgrid_value(PJ *P, LP lp) { + struct CTABLE *ct; + LP out; + + ct = find_ctable(P->ctx, lp, P->gridlist_count, P->gridlist); + + /* normalize input to ll origin */ + lp.lam -= ct->ll.lam; + lp.phi -= ct->ll.phi; + lp.lam = adjlon(lp.lam - M_PI) + M_PI; + + out = nad_intr(lp, ct); + + if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) { + pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA); + } + + return out; +} + +LP proj_hgrid_apply(PJ *P, LP lp, PJ_DIRECTION direction) { + struct CTABLE *ct; + int inverse; + LP out; + + out.lam = HUGE_VAL; out.phi = HUGE_VAL; + + ct = find_ctable(P->ctx, lp, P->gridlist_count, P->gridlist); + + if (ct == NULL || ct->cvs == NULL) { + pj_ctx_set_errno( P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); + return out; + } + + inverse = direction == PJ_FWD ? 0 : 1; + out = nad_cvt(lp, inverse, ct); + + if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) + pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + + return out; + +} diff --git a/src/pj_apply_vgridshift.c b/src/pj_apply_vgridshift.c index 35047a19..6435b954 100644 --- a/src/pj_apply_vgridshift.c +++ b/src/pj_apply_vgridshift.c @@ -28,23 +28,120 @@ #define PJ_LIB__ -#include <projects.h> #include <string.h> #include <math.h> +#include "proj_internal.h" +#include "projects.h" + +static double pj_read_vgrid_value( PJ *defn, LP input, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) { + int itable = 0; + double value = HUGE_VAL; + double grid_x, grid_y; + int grid_ix, grid_iy; + int grid_ix2, grid_iy2; + float *cvs; + /* do not deal with NaN coordinates */ + if( input.phi != input.phi || input.lam != input.lam ) + itable = *gridlist_count_p; + + /* keep trying till we find a table that works */ + for ( ; itable < *gridlist_count_p; itable++ ) + { + PJ_GRIDINFO *gi = tables[itable]; + + ct = gi->ct; + + /* skip tables that don't match our point at all. */ + if( ct->ll.phi > input.phi || ct->ll.lam > input.lam + || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi + || ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam ) + continue; + + /* If we have child nodes, check to see if any of them apply. */ + while( gi->child != NULL ) + { + PJ_GRIDINFO *child; + + for( child = gi->child; child != NULL; child = child->next ) + { + struct CTABLE *ct1 = child->ct; + + if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam + || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi + || ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam) + continue; + + break; + } + + /* we didn't find a more refined child node to use, so go with current grid */ + if( child == NULL ) + { + break; + } + + /* Otherwise let's try for childrens children .. */ + gi = child; + ct = child->ct; + } + + /* load the grid shift info if we don't have it. */ + if( ct->cvs == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) ) + { + pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); + return PJD_ERR_FAILED_TO_LOAD_GRID; + } + + + /* Interpolation a location within the grid */ + grid_x = (input.lam - ct->ll.lam) / ct->del.lam; + grid_y = (input.phi - ct->ll.phi) / ct->del.phi; + grid_ix = (int) floor(grid_x); + grid_iy = (int) floor(grid_y); + grid_x -= grid_ix; + grid_y -= grid_iy; + + grid_ix2 = grid_ix + 1; + if( grid_ix2 >= ct->lim.lam ) + grid_ix2 = ct->lim.lam - 1; + grid_iy2 = grid_iy + 1; + if( grid_iy2 >= ct->lim.phi ) + grid_iy2 = ct->lim.phi - 1; + + cvs = (float *) ct->cvs; + value = cvs[grid_ix + grid_iy * ct->lim.lam] + * (1.0-grid_x) * (1.0-grid_y) + + cvs[grid_ix2 + grid_iy * ct->lim.lam] + * (grid_x) * (1.0-grid_y) + + cvs[grid_ix + grid_iy2 * ct->lim.lam] + * (1.0-grid_x) * (grid_y) + + cvs[grid_ix2 + grid_iy2 * ct->lim.lam] + * (grid_x) * (grid_y); + + } + /* nodata? */ + /* GTX official nodata value if -88.88880f, but some grids also */ + /* use other big values for nodata (e.g naptrans2008.gtx has */ + /* nodata values like -2147479936), so test them too */ + if( value > 1000 || value < -1000 || value == -88.88880f ) + value = HUGE_VAL; + + + return value; +} /************************************************************************/ /* pj_apply_vgridshift() */ /* */ -/* This implementation takes uses the gridlist from a coordinate */ +/* This implementation takes uses the gridlist from a coordinate */ /* system definition. If the gridlist has not yet been */ /* populated in the coordinate system definition we set it up */ /* now. */ /************************************************************************/ - int pj_apply_vgridshift( PJ *defn, const char *listname, - PJ_GRIDINFO ***gridlist_p, + PJ_GRIDINFO ***gridlist_p, int *gridlist_count_p, - int inverse, + int inverse, long point_count, int point_offset, double *x, double *y, double *z ) @@ -52,22 +149,23 @@ int pj_apply_vgridshift( PJ *defn, const char *listname, int i; static int debug_count = 0; PJ_GRIDINFO **tables; + struct CTABLE ct; if( *gridlist_p == NULL ) { - *gridlist_p = - pj_gridlist_from_nadgrids( pj_get_ctx(defn), + *gridlist_p = + pj_gridlist_from_nadgrids( pj_get_ctx(defn), pj_param(defn->ctx,defn->params,listname).s, gridlist_count_p ); if( *gridlist_p == NULL || *gridlist_count_p == 0 ) return defn->ctx->last_errno; } - + if( *gridlist_count_p == 0 ) { - pj_ctx_set_errno( defn->ctx, -38); - return -38; + pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + return PJD_ERR_FAILED_TO_LOAD_GRID; } tables = *gridlist_p; @@ -75,127 +173,37 @@ int pj_apply_vgridshift( PJ *defn, const char *listname, for( i = 0; i < point_count; i++ ) { + double value; long io = i * point_offset; LP input; - int itable = 0; - double value = HUGE_VAL; input.phi = y[io]; input.lam = x[io]; - /* do not deal with NaN coordinates */ - if( input.phi != input.phi || input.lam != input.lam ) - itable = *gridlist_count_p; + value = pj_read_vgrid_value(defn, input, gridlist_count_p, tables, &ct); - /* keep trying till we find a table that works */ - for( ; itable < *gridlist_count_p; itable++ ) + if( inverse ) + z[io] -= value; + else + z[io] += value; + if( value != HUGE_VAL ) { - PJ_GRIDINFO *gi = tables[itable]; - struct CTABLE *ct = gi->ct; - double grid_x, grid_y; - int grid_ix, grid_iy; - int grid_ix2, grid_iy2; - float *cvs; - - /* skip tables that don't match our point at all. */ - if( ct->ll.phi > input.phi || ct->ll.lam > input.lam - || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi - || ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam ) - continue; - - /* If we have child nodes, check to see if any of them apply. */ - while( gi->child != NULL ) - { - PJ_GRIDINFO *child; - - for( child = gi->child; child != NULL; child = child->next ) - { - struct CTABLE *ct1 = child->ct; - - if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam - || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi - || ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam) - continue; - - break; - } - - /* we didn't find a more refined child node to use, so go with current grid */ - if( child == NULL ) - { - break; - } - - /* Otherwise let's try for childrens children .. */ - gi = child; - ct = child->ct; - } - - /* load the grid shift info if we don't have it. */ - if( ct->cvs == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) ) - { - pj_ctx_set_errno( defn->ctx, -38 ); - return -38; - } - - /* Interpolation a location within the grid */ - grid_x = (input.lam - ct->ll.lam) / ct->del.lam; - grid_y = (input.phi - ct->ll.phi) / ct->del.phi; - grid_ix = (int) floor(grid_x); - grid_iy = (int) floor(grid_y); - grid_x -= grid_ix; - grid_y -= grid_iy; - - grid_ix2 = grid_ix + 1; - if( grid_ix2 >= ct->lim.lam ) - grid_ix2 = ct->lim.lam - 1; - grid_iy2 = grid_iy + 1; - if( grid_iy2 >= ct->lim.phi ) - grid_iy2 = ct->lim.phi - 1; - - cvs = (float *) ct->cvs; - value = cvs[grid_ix + grid_iy * ct->lim.lam] - * (1.0-grid_x) * (1.0-grid_y) - + cvs[grid_ix2 + grid_iy * ct->lim.lam] - * (grid_x) * (1.0-grid_y) - + cvs[grid_ix + grid_iy2 * ct->lim.lam] - * (1.0-grid_x) * (grid_y) - + cvs[grid_ix2 + grid_iy2 * ct->lim.lam] - * (grid_x) * (grid_y); - - /* nodata? */ - /* GTX official nodata value if -88.88880f, but some grids also */ - /* use other big values for nodata (e.g naptrans2008.gtx has */ - /* nodata values like -2147479936), so test them too */ - if( value > 1000 || value < -1000 || value == -88.88880f ) - value = HUGE_VAL; - else - { - if( inverse ) - z[io] -= value; - else - z[io] += value; - } - - if( value != HUGE_VAL ) - { - if( debug_count++ < 20 ) - pj_log( defn->ctx, PJ_LOG_DEBUG_MINOR, - "pj_apply_gridshift(): used %s", - ct->id ); + if( debug_count++ < 20 ) { + proj_log_trace(defn, "pj_apply_gridshift(): used %s", ct.id); break; } } if( value == HUGE_VAL ) { + int itable; char gridlist[3000]; - pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR, - "pj_apply_vgridshift(): failed to find a grid shift table for\n" - " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, - y[io] * RAD_TO_DEG ); + proj_log_debug(defn, + "pj_apply_vgridshift(): failed to find a grid shift table for\n" + " location (%.7fdW,%.7fdN)", + x[io] * RAD_TO_DEG, + y[io] * RAD_TO_DEG ); gridlist[0] = '\0'; for( itable = 0; itable < *gridlist_count_p; itable++ ) @@ -212,10 +220,10 @@ int pj_apply_vgridshift( PJ *defn, const char *listname, else sprintf( gridlist+strlen(gridlist), ",%s", gi->gridname ); } - pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR, - "%s", gridlist ); - + + proj_log_debug(defn, "%s", gridlist); pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA ); + return PJD_ERR_GRID_AREA; } } @@ -223,3 +231,64 @@ int pj_apply_vgridshift( PJ *defn, const char *listname, return 0; } +/**********************************************/ +int proj_vgrid_init(PJ* P, const char *grids) { +/********************************************** + + Initizalize and populate gridlist. + + Takes a PJ-object and the plus-parameter + name that is used in the proj-string to + specify the grids to load, e.g. "+grids". + The + should be left out here. + + Returns the number of loaded grids. + +***********************************************/ + + /* prepend "s" to the "grids" string to allow usage with pj_param */ + char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) ); + sprintf(sgrids, "%s%s", "s", grids); + + if (P->vgridlist_geoid == NULL) { + P->vgridlist_geoid = pj_gridlist_from_nadgrids( + P->ctx, + pj_param(P->ctx, P->params, sgrids).s, + &(P->vgridlist_geoid_count) + ); + + if( P->vgridlist_geoid == NULL || P->vgridlist_geoid_count == 0 ) { + pj_dealloc(sgrids); + return 0; + } + } + + if (P->vgridlist_geoid_count == 0) { + proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID); + } + + pj_dealloc(sgrids); + return P->vgridlist_geoid_count; +} + +/***********************************************/ +double proj_vgrid_value(PJ *P, LP lp){ +/*********************************************** + + Read grid value at position lp in grids loaded + with proj_grid_init. + + Returns the grid value of the given coordinate. + +************************************************/ + + struct CTABLE used_grid; + double value; + memset(&used_grid, 0, sizeof(struct CTABLE)); + + value = pj_read_vgrid_value(P, lp, &(P->vgridlist_geoid_count), P->vgridlist_geoid, &used_grid); + proj_log_trace(P, "proj_vgrid_value: (%f, %f) = %f", lp.lam*RAD_TO_DEG, lp.phi*RAD_TO_DEG, value); + + return value; +} + diff --git a/src/pj_datum_set.c b/src/pj_datum_set.c index 3fba68f4..c2fb1608 100644 --- a/src/pj_datum_set.c +++ b/src/pj_datum_set.c @@ -25,6 +25,7 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ +#include <errno.h> #include <projects.h> #include <string.h> @@ -101,7 +102,11 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef) const char *date; projdef->datum_type = PJD_GRIDSHIFT; - projdef->catalog_name = strdup(catalog); + projdef->catalog_name = pj_strdup(catalog); + if (!projdef->catalog_name) { + pj_ctx_set_errno(ctx, ENOMEM); + return 1; + } date = pj_param(ctx, pl, "sdate").s; if( date != NULL) diff --git a/src/pj_ell_set.c b/src/pj_ell_set.c index 72892ac2..8a9b39a1 100644 --- a/src/pj_ell_set.c +++ b/src/pj_ell_set.c @@ -1,12 +1,94 @@ /* set ellipsoid parameters a and es */ -#include <projects.h> #include <string.h> +#include "proj_internal.h" +#include "projects.h" #define SIXTH .1666666666666666667 /* 1/6 */ #define RA4 .04722222222222222222 /* 17/360 */ #define RA6 .02215608465608465608 /* 67/3024 */ #define RV4 .06944444444444444444 /* 5/72 */ #define RV6 .04243827160493827160 /* 55/1296 */ +/* copy ellipsoidal parameters from src to dst */ +void pj_inherit_ellipsoid_defs(const PJ *src, PJ *dst) { + + /* The linear parameters */ + dst->a = src->a; + dst->b = src->b; + dst->ra = src->ra; + dst->rb = src->rb; + + /* The eccentricities */ + dst->alpha = src->alpha; + dst->e = src->e; + dst->es = src->es; + dst->e2 = src->e2; + dst->e2s = src->e2s; + dst->e3 = src->e3; + dst->e3s = src->e3s; + dst->one_es = src->one_es; + dst->rone_es = src->rone_es; + + /* The flattenings */ + dst->f = src->f; + dst->f2 = src->f2; + dst->n = src->n; + dst->rf = src->rf; + dst->rf2 = src->rf2; + dst->rn = src->rn; + + /* This one's for GRS80 */ + dst->J = src->J; + + /* es and a before any +proj related adjustment */ + dst->es_orig = src->es_orig; + dst->a_orig = src->a_orig; +} + +int pj_calc_ellps_params(PJ *P, double a, double es) { + + P->a = a; + P->es = es; + + /* Compute some ancillary ellipsoidal parameters */ + P->e = sqrt(P->es); /* eccentricity */ + P->alpha = asin (P->e); /* angular eccentricity */ + + /* second eccentricity */ + P->e2 = tan (P->alpha); + P->e2s = P->e2 * P->e2; + + /* third eccentricity */ + P->e3 = (0!=P->alpha)? sin (P->alpha) / sqrt(2 - sin (P->alpha)*sin (P->alpha)): 0; + P->e3s = P->e3 * P->e3; + + /* flattening */ + P->f = 1 - cos (P->alpha); /* = 1 - sqrt (1 - PIN->es); */ + P->rf = P->f != 0.0 ? 1.0/P->f: HUGE_VAL; + + /* second flattening */ + P->f2 = (cos(P->alpha)!=0)? 1/cos (P->alpha) - 1: 0; + P->rf2 = P->f2 != 0.0 ? 1/P->f2: HUGE_VAL; + + /* third flattening */ + P->n = pow (tan (P->alpha/2), 2); + P->rn = P->n != 0.0 ? 1/P->n: HUGE_VAL; + + /* ...and a few more */ + P->b = (1 - P->f)*P->a; + P->rb = 1. / P->b; + P->ra = 1. / P->a; + + P->one_es = 1. - P->es; + if (P->one_es == 0.) { + pj_ctx_set_errno( P->ctx, PJD_ERR_ECCENTRICITY_IS_ONE); + return PJD_ERR_ECCENTRICITY_IS_ONE; + } + + P->rone_es = 1./P->one_es; + + return 0; +} + /* initialize geographic shape parameters */ int pj_ell_set(projCtx ctx, paralist *pl, double *a, double *es) { int i; diff --git a/src/pj_ellps.c b/src/pj_ellps.c index 32fbbd42..2a2c5d3b 100644 --- a/src/pj_ellps.c +++ b/src/pj_ellps.c @@ -15,6 +15,7 @@ pj_ellps[] = { {"andrae", "a=6377104.43", "rf=300.0", "Andrae 1876 (Den., Iclnd.)"}, {"aust_SA", "a=6378160.0", "rf=298.25", "Australian Natl & S. Amer. 1969"}, {"GRS67", "a=6378160.0", "rf=298.2471674270", "GRS 67(IUGG 1967)"}, +{"GSK2011", "a=6378136.5", "rf=298.2564151", "GSK-2011"}, {"bessel", "a=6377397.155", "rf=299.1528128", "Bessel 1841"}, {"bess_nam", "a=6377483.865", "rf=299.1528128", "Bessel 1841 (Namibia)"}, {"clrk66", "a=6378206.4", "b=6356583.8", "Clarke 1866"}, @@ -40,6 +41,7 @@ pj_ellps[] = { {"mprts", "a=6397300.", "rf=191.", "Maupertius 1738"}, {"new_intl", "a=6378157.5", "b=6356772.2", "New International 1967"}, {"plessis", "a=6376523.", "b=6355863.", "Plessis 1817 (France)"}, +{"PZ90", "a=6378136.0", "rf=298.25784", "PZ-90"}, {"SEasia", "a=6378155.0", "b=6356773.3205", "Southeast Asia"}, {"walbeck", "a=6376896.0", "b=6355834.8467", "Walbeck"}, {"WGS60", "a=6378165.0", "rf=298.3", "WGS 60"}, diff --git a/src/pj_factors.c b/src/pj_factors.c index 6c1b4978..69d59e49 100644 --- a/src/pj_factors.c +++ b/src/pj_factors.c @@ -1,6 +1,8 @@ /* projection scale factors */ #define PJ_LIB__ -#include <projects.h> +#include <proj.h> +#include "projects.h" + #include <errno.h> #ifndef DEFAULT_H @@ -10,88 +12,85 @@ #define EPS 1.0e-12 int pj_factors(LP lp, PJ *P, double h, struct FACTORS *fac) { - struct DERIVS der; double cosphi, t, n, r; + int err; + + err = proj_errno_reset (P); + + if (0==fac) { + proj_errno_set (P, ENOMEM); + return 1; + } - der.x_l = 0.0; - der.x_p = 0.0; - der.y_l = 0.0; - der.y_p = 0.0; + /* Indicate that all factors are numerical approximations */ + fac->code = 0; - /* check for forward and latitude or longitude overange */ - if ((t = fabs(lp.phi)-M_HALFPI) > EPS || fabs(lp.lam) > 10.) { - pj_ctx_set_errno( P->ctx, -14); + /* Check for latitude or longitude overange */ + if ((fabs (lp.phi)-M_HALFPI) > EPS || fabs (lp.lam) > 10.) { + proj_errno_set (P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT); return 1; - } else { /* proceed */ - errno = pj_errno = 0; - P->ctx->last_errno = 0; - - if (h < EPS) - h = DEFAULT_H; - if (fabs(lp.phi) > (M_HALFPI - h)) - /* adjust to value around pi/2 where derived still exists*/ - lp.phi = lp.phi < 0. ? (-M_HALFPI+h) : (M_HALFPI-h); - else if (P->geoc) - lp.phi = atan(P->rone_es * tan(lp.phi)); - lp.lam -= P->lam0; /* compute del lp.lam */ - if (!P->over) - lp.lam = adjlon(lp.lam); /* adjust del longitude */ - if (P->spc) /* get what projection analytic values */ - P->spc(lp, P, fac); - if (((fac->code & (IS_ANAL_XL_YL+IS_ANAL_XP_YP)) != - (IS_ANAL_XL_YL+IS_ANAL_XP_YP)) && pj_deriv(lp, h, P, &der)) - return 1; - - if (!(fac->code & IS_ANAL_XL_YL)) { - fac->der.x_l = der.x_l; - fac->der.y_l = der.y_l; - } - if (!(fac->code & IS_ANAL_XP_YP)) { - fac->der.x_p = der.x_p; - fac->der.y_p = der.y_p; - } - cosphi = cos(lp.phi); - if (!(fac->code & IS_ANAL_HK)) { - fac->h = hypot(fac->der.x_p, fac->der.y_p); - fac->k = hypot(fac->der.x_l, fac->der.y_l) / cosphi; - if (P->es != 0.0) { - t = sin(lp.phi); - t = 1. - P->es * t * t; - n = sqrt(t); - fac->h *= t * n / P->one_es; - fac->k *= n; - r = t * t / P->one_es; - } else - r = 1.; - } else if (P->es != 0.0) { - r = sin(lp.phi); - r = 1. - P->es * r * r; - r = r * r / P->one_es; - } else - r = 1.; - - /* convergence */ - if (!(fac->code & IS_ANAL_CONV)) { - fac->conv = - atan2(fac->der.x_p, fac->der.y_p); - if (fac->code & IS_ANAL_XL_YL) - fac->code |= IS_ANAL_CONV; - } - /* areal scale factor */ - fac->s = (fac->der.y_p * fac->der.x_l - fac->der.x_p * fac->der.y_l) * r / cosphi; - - /* meridian-parallel angle theta prime */ - fac->thetap = aasin(P->ctx,fac->s / (fac->h * fac->k)); - - /* Tissot ellips axis */ - t = fac->k * fac->k + fac->h * fac->h; - fac->a = sqrt(t + 2. * fac->s); - t = (t = t - 2. * fac->s) <= 0. ? 0. : sqrt(t); - fac->b = 0.5 * (fac->a - t); - fac->a = 0.5 * (fac->a + t); - - /* omega */ - fac->omega = 2. * aasin(P->ctx,(fac->a - fac->b)/(fac->a + fac->b)); } + /* Set a reasonable step size for the numerical derivatives */ + h = fabs (h); + if (h < EPS) + h = DEFAULT_H; + + /* If input latitudes are geocentric, convert to geographic */ + if (P->geoc) + lp.phi = atan(P->rone_es * tan(lp.phi)); + + /* If latitude + one step overshoots the pole, move it slightly inside, */ + /* so the numerical derivative still exists */ + if (fabs (lp.phi) > (M_HALFPI - h)) + lp.phi = lp.phi < 0. ? -(M_HALFPI-h) : (M_HALFPI-h); + + /* Longitudinal distance from central meridian */ + lp.lam -= P->lam0; + if (!P->over) + lp.lam = adjlon(lp.lam); + + /* Derivatives */ + if (pj_deriv (lp, h, P, &(fac->der))) { + proj_errno_set (P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT); + return 1; + } + + /* Scale factors */ + cosphi = cos (lp.phi); + fac->h = hypot (fac->der.x_p, fac->der.y_p); + fac->k = hypot (fac->der.x_l, fac->der.y_l) / cosphi; + + if (P->es != 0.0) { + t = sin(lp.phi); + t = 1. - P->es * t * t; + n = sqrt(t); + fac->h *= t * n / P->one_es; + fac->k *= n; + r = t * t / P->one_es; + } else + r = 1.; + + /* Convergence */ + fac->conv = -atan2 (fac->der.x_p, fac->der.y_p); + + /* Areal scale factor */ + fac->s = (fac->der.y_p * fac->der.x_l - fac->der.x_p * fac->der.y_l) * r / cosphi; + + /* Meridian-parallel angle (theta prime) */ + fac->thetap = aasin(P->ctx,fac->s / (fac->h * fac->k)); + + /* Tissot ellipse axis */ + t = fac->k * fac->k + fac->h * fac->h; + fac->a = sqrt(t + 2. * fac->s); + t = t - 2. * fac->s; + t = t > 0? sqrt(t): 0; + fac->b = 0.5 * (fac->a - t); + fac->a = 0.5 * (fac->a + t); + + /* Angular distortion */ + fac->omega = 2. * aasin(P->ctx, (fac->a - fac->b) / (fac->a + fac->b) ); + + proj_errno_restore (P, err); return 0; } diff --git a/src/pj_fileapi.c b/src/pj_fileapi.c index 1e5bfa51..e223993e 100644 --- a/src/pj_fileapi.c +++ b/src/pj_fileapi.c @@ -26,6 +26,7 @@ * DEALINGS IN THE SOFTWARE. *****************************************************************************/ +#include <errno.h> #include <projects.h> #include <string.h> @@ -76,6 +77,13 @@ static PAFile pj_stdio_fopen(projCtx ctx, const char *filename, } pafile = (stdio_pafile *) malloc(sizeof(stdio_pafile)); + if (!pafile) + { + pj_ctx_set_errno(ctx, ENOMEM); + fclose(fp); + return NULL; + } + pafile->fp = fp; pafile->ctx = ctx; return (PAFile) pafile; diff --git a/src/pj_gc_reader.c b/src/pj_gc_reader.c index dc528b52..e49e56a4 100644 --- a/src/pj_gc_reader.c +++ b/src/pj_gc_reader.c @@ -27,6 +27,7 @@ #define PJ_LIB__ +#include <errno.h> #include <projects.h> #include <string.h> #include <ctype.h> @@ -56,15 +57,29 @@ PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name ) catalog = (PJ_GridCatalog *) calloc(1,sizeof(PJ_GridCatalog)); if( !catalog ) { + pj_ctx_set_errno(ctx, ENOMEM); pj_ctx_fclose(ctx, fid); return NULL; } - catalog->catalog_name = strdup(catalog_name); + catalog->catalog_name = pj_strdup(catalog_name); + if (!catalog->catalog_name) { + pj_ctx_set_errno(ctx, ENOMEM); + free(catalog); + pj_ctx_fclose(ctx, fid); + return NULL; + } entry_max = 10; catalog->entries = (PJ_GridCatalogEntry *) malloc(entry_max * sizeof(PJ_GridCatalogEntry)); + if (!catalog->entries) { + pj_ctx_set_errno(ctx, ENOMEM); + free(catalog->catalog_name); + free(catalog); + pj_ctx_fclose(ctx, fid); + return NULL; + } while( pj_gc_readentry( ctx, fid, catalog->entries+catalog->entry_count) == 0) @@ -83,6 +98,7 @@ PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name ) int i; for( i = 0; i < catalog->entry_count; i++ ) free( catalog->entries[i].definition ); + free( catalog->entries ); free( catalog->catalog_name ); free( catalog ); pj_ctx_fclose(ctx, fid); @@ -124,6 +140,7 @@ static int pj_gc_read_csv_line( projCtx ctx, PAFile fid, while( token_count < max_tokens && *next != '\0' ) { const char *start = next; + char* token; while( *next != '\0' && *next != ',' ) next++; @@ -134,7 +151,14 @@ static int pj_gc_read_csv_line( projCtx ctx, PAFile fid, next++; } - tokens[token_count++] = strdup(start); + token = pj_strdup(start); + if (!token) { + while (token_count > 0) + free(tokens[--token_count]); + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } + tokens[token_count++] = token; } return token_count; @@ -199,7 +223,8 @@ static int pj_gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry) } else { - entry->definition = strdup( tokens[0] ); + entry->definition = tokens[0]; + tokens[0] = NULL; /* We take ownership of tokens[0] */ entry->region.ll_long = dmstor_ctx( ctx, tokens[1], NULL ); entry->region.ll_lat = dmstor_ctx( ctx, tokens[2], NULL ); entry->region.ur_long = dmstor_ctx( ctx, tokens[3], NULL ); diff --git a/src/pj_generic_selftest.c b/src/pj_generic_selftest.c deleted file mode 100644 index 88b5c308..00000000 --- a/src/pj_generic_selftest.c +++ /dev/null @@ -1,197 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Generic regression test for PROJ.4 projection algorithms. - * Author: Thomas Knudsen - * - ****************************************************************************** - * Copyright (c) 2016, Thomas Knudsen - * - * 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 <stdio.h> -#define PJ_LIB__ -#include <projects.h> - - -static int deviates_xy (XY expected, XY got, double tolerance); -static int deviates_lp (LP expected, LP got, double tolerance); -static XY pj_fwd_deg (LP in, PJ *P); - - -/**********************************************************************/ -int pj_generic_selftest ( -/**********************************************************************/ - char *e_args, - char *s_args, - double tolerance_xy, - double tolerance_lp, - int n_fwd, - int n_inv, - LP *fwd_in, - XY *e_fwd_expect, - XY *s_fwd_expect, - XY *inv_in, - LP *e_inv_expect, - LP *s_inv_expect -) { -/*********************************************************************** - -Generic regression test for PROJ.4 projection algorithms, testing both -ellipsoidal ("e_") and spheroidal ("s_") versions of the projection -algorithms in both forward ("_fwd_") and inverse ("_inv_") mode. - -Compares the "known good" results in <e_fwd_expect> and <s_fwd_expect> -with the actual results obtained by transforming the forward input data -set in <fwd_in> with pj_fwd() using setup arguments <e_args> and -<s_args>, respectively. - -Then - -Compares the "known good" results in <e_inv_expect> and <s_inv_expect> -with the actual results obtained by transforming the inverse input data -set in <inv_in> with pj_inv() using setup arguments <e_args> and -<s_args>, respectively. - -Any of the pointers passed may be set to 0, indicating "don't test this -part". - -Returns 0 if all data agree to within the accuracy specified in -<tolerance_xy> and <tolerance_lp>. Non-zero otherwise. - -***********************************************************************/ - int i; - - PJ *P; - - if (e_args) { - P = pj_init_plus(e_args); - if (0==P) - return 2; - - /* Test forward ellipsoidal */ - if (e_fwd_expect) { - for (i = 0; i < n_fwd; i++) - if (deviates_xy (e_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) - break; - if ( i != n_fwd ) - return 100 + i; - } - - /* Test inverse ellipsoidal */ - if (e_inv_expect) { - for (i = 0; i < n_inv; i++) - if (deviates_lp (e_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) - break; - if ( i != n_inv ) - return 200 + i; - } - - pj_free (P); - } - - - if (s_args) { - P = pj_init_plus(s_args); - if (0==P) - return 3; - - /* Test forward spherical */ - if (s_fwd_expect) { - for (i = 0; i < n_fwd; i++) - if (deviates_xy (s_fwd_expect[i], pj_fwd_deg ( fwd_in[i], P ), tolerance_xy)) - break; - if ( i != n_fwd ) - return 300 + i; - } - - /* Test inverse spherical */ - if (s_inv_expect) { - for (i = 0; i < n_inv; i++) - if (deviates_lp (s_inv_expect[i], pj_inv ( inv_in[i], P ), tolerance_lp)) - break; - if ( i != n_inv ) - return 400 + i; - } - - pj_free (P); - } - - return 0; -} - - - -/**********************************************************************/ -static int deviates_xy (XY expected, XY got, double tolerance) { -/*********************************************************************** - - Determine whether two XYs deviate by more than <tolerance>. - - The test material ("expected" values) may contain coordinates that - are indeterminate. For those cases, we test the other coordinate - only by forcing expected and actual ("got") coordinates to 0. - -***********************************************************************/ - if (HUGE_VAL== expected.x) - return 0; - if (HUGE_VAL== expected.y) - return 0; - if (hypot ( expected.x - got.x, expected.y - got.y ) > tolerance) - return 1; - return 0; -} - - -/**********************************************************************/ -static int deviates_lp (LP expected, LP got, double tolerance) { -/*********************************************************************** - - Determine whether two LPs deviate by more than <tolerance>. - - This one is slightly tricky, since the <expected> LP is - supposed to be represented as degrees (since it was at some - time written down by a real human), whereas the <got> LP is - represented in radians (since it is supposed to be the result - output from pj_inv) - -***********************************************************************/ - if (HUGE_VAL== expected.lam) - return 0; - if (HUGE_VAL== expected.phi) - return 0; - if (hypot ( DEG_TO_RAD * expected.lam - got.lam, DEG_TO_RAD * expected.phi - got.phi ) > tolerance) - return 1; - return 0; -} - - -/**********************************************************************/ -static XY pj_fwd_deg (LP in, PJ *P) { -/*********************************************************************** - - Wrapper for pj_fwd, accepting input in degrees. - -***********************************************************************/ - LP in_rad; - in_rad.lam = DEG_TO_RAD * in.lam; - in_rad.phi = DEG_TO_RAD * in.phi; - return pj_fwd (in_rad, P); -} diff --git a/src/pj_geocent.c b/src/pj_geocent.c index 667c29bd..eca62080 100644 --- a/src/pj_geocent.c +++ b/src/pj_geocent.c @@ -58,49 +58,3 @@ PJ *PROJECTION(geocent) { return P; } - -#ifndef PJ_SELFTEST -int pj_geocent_selftest (void) {return 0;} -#else - -int pj_geocent_selftest (void) { - - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=geocent +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - char s_args[] = {"+proj=geocent +a=6400000 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222638.98158654713, 111319.49079327357}, - { 222638.98158654713, -111319.49079327357}, - {-222638.98158654713, 111319.49079327357}, - {-222638.98158654713, -111319.49079327357}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305682390426, 0.00089831528411952132}, - { 0.0017966305682390426, -0.00089831528411952132}, - {-0.0017966305682390426, 0.00089831528411952132}, - {-0.0017966305682390426, -0.00089831528411952132}, - }; - - return pj_generic_selftest (e_args, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - -#endif - diff --git a/src/pj_gridinfo.c b/src/pj_gridinfo.c index 458f0f2b..ad4695ca 100644 --- a/src/pj_gridinfo.c +++ b/src/pj_gridinfo.c @@ -212,7 +212,9 @@ int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi ) ct_tmp.cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP)); if( row_buf == NULL || ct_tmp.cvs == NULL ) { - pj_ctx_set_errno( ctx, -38 ); + pj_dalloc( row_buf ); + pj_dalloc( ct_tmp.cvs ); + pj_ctx_set_errno( ctx, ENOMEM ); pj_release_lock(); return 0; } @@ -230,6 +232,7 @@ int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi ) pj_dalloc( row_buf ); pj_dalloc( ct_tmp.cvs ); pj_ctx_set_errno( ctx, -38 ); + pj_release_lock(); return 0; } @@ -290,7 +293,9 @@ int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi ) ct_tmp.cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP)); if( row_buf == NULL || ct_tmp.cvs == NULL ) { - pj_ctx_set_errno( ctx, -38 ); + pj_dalloc( row_buf ); + pj_dalloc( ct_tmp.cvs ); + pj_ctx_set_errno( ctx, ENOMEM ); pj_release_lock(); return 0; } @@ -362,7 +367,7 @@ int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi ) ct_tmp.cvs = (FLP *) pj_malloc(words*sizeof(float)); if( ct_tmp.cvs == NULL ) { - pj_ctx_set_errno( ctx, -38 ); + pj_ctx_set_errno( ctx, ENOMEM ); pj_release_lock(); return 0; } @@ -371,6 +376,7 @@ int pj_gridinfo_load( projCtx ctx, PJ_GRIDINFO *gi ) != (size_t)words ) { pj_dalloc( ct_tmp.cvs ); + pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); pj_release_lock(); return 0; } @@ -519,6 +525,10 @@ static int pj_gridinfo_init_ntv2( projCtx ctx, PAFile fid, PJ_GRIDINFO *gilist ) /* Initialize a corresponding "ct" structure. */ /* -------------------------------------------------------------------- */ ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE)); + if (!ct) { + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } strncpy( ct->id, (const char *) header + 8, 8 ); ct->id[8] = '\0'; @@ -553,6 +563,7 @@ static int pj_gridinfo_init_ntv2( projCtx ctx, PAFile fid, PJ_GRIDINFO *gilist ) "GS_COUNT(%d) does not match expected cells (%dx%d=%d)\n", gs_count, ct->lim.lam, ct->lim.phi, ct->lim.lam * ct->lim.phi ); + pj_dalloc(ct); pj_ctx_set_errno( ctx, -38 ); return 0; } @@ -567,11 +578,23 @@ static int pj_gridinfo_init_ntv2( projCtx ctx, PAFile fid, PJ_GRIDINFO *gilist ) gi = gilist; else { - gi = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO)); - memset( gi, 0, sizeof(PJ_GRIDINFO) ); + gi = (PJ_GRIDINFO *) pj_calloc(1, sizeof(PJ_GRIDINFO)); + if (!gi) { + pj_dalloc(ct); + pj_gridinfo_free(ctx, gilist); + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } - gi->gridname = strdup( gilist->gridname ); - gi->filename = strdup( gilist->filename ); + gi->gridname = pj_strdup( gilist->gridname ); + gi->filename = pj_strdup( gilist->filename ); + if (!gi->gridname || gi->filename) { + pj_gridinfo_free(ctx, gi); + pj_dalloc(ct); + pj_gridinfo_free(ctx, gilist); + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } gi->next = NULL; } @@ -699,6 +722,10 @@ static int pj_gridinfo_init_ntv1( projCtx ctx, PAFile fid, PJ_GRIDINFO *gi ) /* Fill in CTABLE structure. */ /* -------------------------------------------------------------------- */ ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE)); + if (!ct) { + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } strcpy( ct->id, "NTv1 Grid Shift File" ); ct->ll.lam = - *((double *) (header+72)); @@ -799,6 +826,10 @@ static int pj_gridinfo_init_gtx( projCtx ctx, PAFile fid, PJ_GRIDINFO *gi ) /* Fill in CTABLE structure. */ /* -------------------------------------------------------------------- */ ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE)); + if (!ct) { + pj_ctx_set_errno(ctx, ENOMEM); + return 0; + } strcpy( ct->id, "GTX Vertical Grid Shift File" ); ct->ll.lam = xorigin; @@ -863,10 +894,18 @@ PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname ) /* Initialize a GRIDINFO with stub info we would use if it */ /* cannot be loaded. */ /* -------------------------------------------------------------------- */ - gilist = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO)); - memset( gilist, 0, sizeof(PJ_GRIDINFO) ); + gilist = (PJ_GRIDINFO *) pj_calloc(1, sizeof(PJ_GRIDINFO)); + if (!gilist) { + pj_ctx_set_errno(ctx, ENOMEM); + return NULL; + } - gilist->gridname = strdup( gridname ); + gilist->gridname = pj_strdup( gridname ); + if (!gilist->gridname) { + pj_dalloc(gilist); + pj_ctx_set_errno(ctx, ENOMEM); + return NULL; + } gilist->filename = NULL; gilist->format = "missing"; gilist->grid_offset = 0; @@ -882,7 +921,13 @@ PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname ) return gilist; } - gilist->filename = strdup(fname); + gilist->filename = pj_strdup(fname); + if (!gilist->filename) { + pj_dalloc(gilist->gridname); + pj_dalloc(gilist); + pj_ctx_set_errno(ctx, ENOMEM); + return NULL; + } /* -------------------------------------------------------------------- */ /* Load a header, to determine the file type. */ diff --git a/src/pj_gridlist.c b/src/pj_gridlist.c index 1123274e..4617591c 100644 --- a/src/pj_gridlist.c +++ b/src/pj_gridlist.c @@ -28,6 +28,7 @@ #define PJ_LIB__ +#include <errno.h> #include <projects.h> #include <string.h> #include <math.h> @@ -103,6 +104,10 @@ static int pj_gridlist_merge_gridfile( projCtx ctx, int new_max = *p_gridmax + 20; new_list = (PJ_GRIDINFO **) pj_calloc(new_max, sizeof(void *)); + if (!new_list) { + pj_ctx_set_errno( ctx, ENOMEM ); + return 0; + } if( *p_gridlist != NULL ) { memcpy( new_list, *p_gridlist, @@ -132,8 +137,6 @@ static int pj_gridlist_merge_gridfile( projCtx ctx, if( this_grid == NULL ) { - /* we should get at least a stub grid with a missing "ct" member */ - assert( FALSE ); return 0; } diff --git a/src/pj_init.c b/src/pj_init.c index 951f1cfb..534f0827 100644 --- a/src/pj_init.c +++ b/src/pj_init.c @@ -28,12 +28,13 @@ *****************************************************************************/ #define PJ_LIB__ -#include <projects.h> #include <geodesic.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <ctype.h> +#include "proj_internal.h" +#include "projects.h" /* Maximum size of files using the "escape carriage return" feature */ #define MAX_CR_ESCAPE 65537 @@ -129,7 +130,6 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, int *found_def) { pj_read_state *state = (pj_read_state*) calloc(1,sizeof(pj_read_state)); char sword[MAX_CR_ESCAPE]; - char *pipeline; int len; int in_target = 0; const char *next_char = NULL; @@ -220,10 +220,7 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, sword[word_len+1] = '\0'; /* do not override existing parameter value of same name - unless in pipeline definition */ - pipeline = pj_param(ctx, *start, "sproj").s; - if (pipeline && strcmp (pipeline, "pipeline")) - pipeline = 0; - if (pipeline || !pj_param(ctx, *start, sword).i) { + if (!pj_param(ctx, *start, sword).i) { /* don't default ellipse if datum, ellps or any earth model information is set. */ if( strncmp(sword+1,"ellps=",6) != 0 @@ -260,8 +257,7 @@ get_opt(projCtx ctx, paralist **start, PAFile fid, char *name, paralist *next, /************************************************************************/ /* get_defaults() */ /************************************************************************/ -static paralist * -get_defaults(projCtx ctx, paralist **start, paralist *next, char *name) { +static paralist *get_defaults(projCtx ctx, paralist **start, paralist *next, char *name) { PAFile fid; if ( (fid = pj_open_lib(ctx,"proj_def.dat", "rt")) != NULL) { @@ -359,6 +355,8 @@ pj_init_plus_ctx( projCtx ctx, const char *definition ) /* make a copy that we can manipulate */ defn_copy = (char *) pj_malloc( strlen(definition)+1 ); + if (!defn_copy) + return NULL; strcpy( defn_copy, definition ); /* split into arguments based on '+' and trim white space */ @@ -379,8 +377,9 @@ pj_init_plus_ctx( projCtx ctx, const char *definition ) if( argc+1 == MAX_ARG ) { - pj_ctx_set_errno( ctx, -44 ); - goto bum_call; + pj_dalloc( defn_copy ); + pj_ctx_set_errno( ctx, PJD_ERR_UNPARSEABLE_CS_DEF ); + return 0; } argv[argc++] = defn_copy + i + 1; @@ -408,9 +407,7 @@ pj_init_plus_ctx( projCtx ctx, const char *definition ) /* perform actual initialization */ result = pj_init_ctx( ctx, argc, argv ); -bum_call: pj_dalloc( defn_copy ); - return result; } @@ -439,6 +436,8 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { int i; int found_def = 0; PJ *PIN = 0; + int n_pipelines = 0; + int n_inits = 0; if (0==ctx) ctx = pj_get_default_ctx (); @@ -450,32 +449,44 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS); return 0; } - + + /* count occurrences of pipelines and inits */ + for (i = 0; i < argc; ++i) { + if (!strcmp (argv[i], "+proj=pipeline") || !strcmp(argv[i], "proj=pipeline") ) + n_pipelines++; + if (!strncmp (argv[i], "+init=", 6) || !strncmp(argv[i], "init=", 5)) + n_inits++; + } + + /* can't have nested pipeline directly */ + if (n_pipelines > 1) { + pj_ctx_set_errno (ctx, PJD_ERR_MALFORMED_PIPELINE); + return 0; + } + + /* don't allow more than one +init in non-pipeline operations */ + if (n_pipelines == 0 && n_inits > 1) { + pj_ctx_set_errno (ctx, PJD_ERR_TOO_MANY_INITS); + return 0; + } + /* put arguments into internal linked list */ start = curr = pj_mkparam(argv[0]); + if (!curr) + return pj_dealloc_params (ctx, start, ENOMEM); - /* build parameter list and expand +init's. Does not take care of a single +init. */ for (i = 1; i < argc; ++i) { curr->next = pj_mkparam(argv[i]); - - /* check if +init present */ - if (pj_param(ctx, curr, "tinit").i) { - found_def = 0; - curr = get_init(ctx, &curr, curr->next, pj_param(ctx, curr, "sinit").s, &found_def); - if (!curr) - return pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS); - - if (!found_def) - return pj_dealloc_params (ctx, start, PJD_ERR_NO_OPTION_IN_INIT_FILE); - - } else { - curr = curr->next; - } + if (!curr->next) + return pj_dealloc_params (ctx, start, ENOMEM); + curr = curr->next; } - /* in case the parameter list only consist of a +init parameter - it is expanded here (will not be handled in the above loop). */ - if (pj_param(ctx, start, "tinit").i && argc == 1) { + /* Only expand +init's in non-pipeline operations. +init's in pipelines are */ + /* expanded in the individual pipeline steps during pipeline initialization. */ + /* Potentially this leads to many nested pipelines, which shouldn't be a */ + /* problem when +inits are expanded as late as possible. */ + if (pj_param(ctx, start, "tinit").i && n_pipelines == 0) { found_def = 0; curr = get_init(ctx, &start, curr, pj_param(ctx, start, "sinit").s, &found_def); if (!curr) @@ -483,21 +494,22 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { if (!found_def) return pj_dealloc_params (ctx, start, PJD_ERR_NO_OPTION_IN_INIT_FILE); } - + if (ctx->last_errno) return pj_dealloc_params (ctx, start, ctx->last_errno); - + /* find projection selection */ if (!(name = pj_param(ctx, start, "sproj").s)) - return pj_default_destructor (PIN, PJD_ERR_PROJ_NOT_NAMED); + return pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED); for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ; if (!s) return pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID); - - /* set defaults, unless inhibited */ - if (!(pj_param(ctx, start, "bno_defs").i)) - curr = get_defaults(ctx,&start, curr, name); + + /* set defaults, unless inhibited or we are initializing a pipeline */ + if (!(pj_param(ctx, start, "bno_defs").i) && n_pipelines == 0) + curr = get_defaults(ctx,&start, curr, name); + proj = (PJ *(*)(PJ *)) pj_list[i].proj; /* allocate projection structure */ @@ -520,53 +532,20 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { PIN->vgridlist_geoid_count = 0; /* set datum parameters */ - if (pj_datum_set(ctx, start, PIN)) - return pj_default_destructor (PIN, PJD_ERR_MISSING_ARGS); - - /* set ellipsoid/sphere parameters */ - if (pj_ell_set(ctx, start, &PIN->a, &PIN->es)) { - pj_log (ctx, PJ_LOG_DEBUG_MINOR, "pj_init_ctx: Must specify ellipsoid or sphere"); + if (pj_datum_set(ctx, start, PIN)) return pj_default_destructor (PIN, PJD_ERR_MISSING_ARGS); - } - - PIN->a_orig = PIN->a; - PIN->es_orig = PIN->es; - - /* Compute some ancillary ellipsoidal parameters */ - PIN->e = sqrt(PIN->es); /* eccentricity */ - PIN->alpha = asin (PIN->e); /* angular eccentricity */ - - /* second eccentricity */ - PIN->e2 = tan (PIN->alpha); - PIN->e2s = PIN->e2 * PIN->e2; - - /* third eccentricity */ - PIN->e3 = (0!=PIN->alpha)? sin (PIN->alpha) / sqrt(2 - sin (PIN->alpha)*sin (PIN->alpha)): 0; - PIN->e3s = PIN->e3 * PIN->e3; - - /* flattening */ - PIN->f = 1 - cos (PIN->alpha); /* = 1 - sqrt (1 - PIN->es); */ - PIN->rf = PIN->f != 0.0 ? 1.0/PIN->f: HUGE_VAL; - - /* second flattening */ - PIN->f2 = (cos(PIN->alpha)!=0)? 1/cos (PIN->alpha) - 1: 0; - PIN->rf2 = PIN->f2 != 0.0 ? 1/PIN->f2: HUGE_VAL; - - /* third flattening */ - PIN->n = pow (tan (PIN->alpha/2), 2); - PIN->rn = PIN->n != 0.0 ? 1/PIN->n: HUGE_VAL; - - /* ...and a few more */ - PIN->b = (1 - PIN->f)*PIN->a; - PIN->rb = 1. / PIN->b; - PIN->ra = 1. / PIN->a; - - PIN->one_es = 1. - PIN->es; - if (PIN->one_es == 0.) - return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE); - PIN->rone_es = 1./PIN->one_es; + if (PIN->need_ellps) { + if (pj_ell_set(ctx, start, &PIN->a, &PIN->es)) { + pj_log (ctx, PJ_LOG_DEBUG_MINOR, "pj_init_ctx: Must specify ellipsoid or sphere"); + return pj_default_destructor (PIN, PJD_ERR_MISSING_ARGS); + } + PIN->a_orig = PIN->a; + PIN->es_orig = PIN->es; + if (pj_calc_ellps_params(PIN, PIN->a, PIN->es)) + return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE); + } /* Now that we have ellipse information check for WGS84 datum */ if( PIN->datum_type == PJD_3PARAM @@ -600,7 +579,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { if( !(fabs(PIN->long_wrap_center) < 10 * M_TWOPI) ) return pj_default_destructor (PIN, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT); } - + /* axis orientation */ if( (pj_param(ctx, start,"saxis").s) != NULL ) { @@ -613,7 +592,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { || strchr( axis_legal, axis_arg[1] ) == NULL || strchr( axis_legal, axis_arg[2] ) == NULL) return pj_default_destructor (PIN, PJD_ERR_AXIS); - + /* it would be nice to validate we don't have on axis repeated */ strcpy( PIN->axis, axis_arg ); } @@ -637,7 +616,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { PIN->k0 = pj_param(ctx, start, "dk").f; else PIN->k0 = 1.; - if (PIN->k0 <= 0.) + if (PIN->k0 <= 0.) return pj_default_destructor (PIN, PJD_ERR_K_LESS_THAN_ZERO); /* set units */ @@ -698,7 +677,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { && *next_str == '\0' ) value = name; - if (!value) + if (!value) return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_PRIME_MERIDIAN); PIN->from_greenwich = dmstor_ctx(ctx,value,NULL); } @@ -714,7 +693,10 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) { /* projection specific initialization */ PIN = proj(PIN); if ((0==PIN) || ctx->last_errno) + { + pj_free(PIN); return 0; + } return PIN; } diff --git a/src/pj_internal.c b/src/pj_internal.c index 31c299ac..efa9bd1f 100644 --- a/src/pj_internal.c +++ b/src/pj_internal.c @@ -1,8 +1,9 @@ /****************************************************************************** * Project: PROJ.4 - * Purpose: This is primarily material originating from pj_obs_api.c, - * that does not fit into the API category. Hence this pile of - * tubings and fittings for PROJ.4 internal plumbing. + * Purpose: This is primarily material originating from pj_obs_api.c + * (now proj_4D_api.c), that does not fit into the API + * category. Hence this pile of tubings and fittings for + * PROJ.4 internal plumbing. * * Author: Thomas Knudsen, thokn@sdfe.dk, 2017-07-05 * @@ -29,7 +30,7 @@ *****************************************************************************/ #define PJ_INTERNAL_C #include "proj_internal.h" -#include <projects.h> +#include "projects.h" #include <geodesic.h> #include <stddef.h> @@ -37,15 +38,19 @@ #include <errno.h> +enum pj_io_units pj_left (PJ *P) { + enum pj_io_units u = P->inverted? P->right: P->left; + if (u==PJ_IO_UNITS_RADIANS) + return PJ_IO_UNITS_RADIANS; + return PJ_IO_UNITS_METERS; +} - -/* Used for zero-initializing new objects */ -const PJ_COORD proj_coord_null = {{0, 0, 0, 0}}; -const PJ_OBS proj_obs_null = { - {{0, 0, 0, 0}}, - {{0, 0, 0}}, - 0, 0 -}; +enum pj_io_units pj_right (PJ *P) { + enum pj_io_units u = P->inverted? P->left: P->right; + if (u==PJ_IO_UNITS_RADIANS) + return PJ_IO_UNITS_RADIANS; + return PJ_IO_UNITS_METERS; +} /* Work around non-constness of MSVC HUGE_VAL by providing functions rather than constants */ @@ -55,62 +60,10 @@ PJ_COORD proj_coord_error (void) { return c; } -PJ_OBS proj_obs_error (void) { - PJ_OBS obs; - obs.coo = proj_coord_error (); - obs.anc.v[0] = obs.anc.v[1] = obs.anc.v[2] = HUGE_VAL; - obs.id = obs.flags = 0; - return obs; -} - - -PJ_OBS pj_fwdobs (PJ_OBS obs, PJ *P) { - if (0!=P->fwdobs) { - obs = P->fwdobs (obs, P); - return obs; - } - if (0!=P->fwd3d) { - obs.coo.xyz = pj_fwd3d (obs.coo.lpz, P); - return obs; - } - if (0!=P->fwd) { - obs.coo.xy = pj_fwd (obs.coo.lp, P); - return obs; - } - proj_errno_set (P, EINVAL); - return proj_obs_error (); -} - - -PJ_OBS pj_invobs (PJ_OBS obs, PJ *P) { - if (0!=P->invobs) { - obs = P->invobs (obs, P); - return obs; - } - if (0!=P->inv3d) { - obs.coo.lpz = pj_inv3d (obs.coo.xyz, P); - return obs; - } - if (0!=P->inv) { - obs.coo.lp = pj_inv (obs.coo.xy, P); - return obs; - } - proj_errno_set (P, EINVAL); - return proj_obs_error (); -} - - - -PJ_COORD pj_fwdcoord (PJ_COORD coo, PJ *P) { - if (0!=P->fwdcoord) - return P->fwdcoord (coo, P); - if (0!=P->fwdobs) { - PJ_OBS obs = proj_obs_null; - obs.coo = coo; - obs = P->fwdobs (obs, P); - return obs.coo; - } +PJ_COORD pj_fwd4d (PJ_COORD coo, PJ *P) { + if (0!=P->fwd4d) + return P->fwd4d (coo, P); if (0!=P->fwd3d) { coo.xyz = pj_fwd3d (coo.lpz, P); return coo; @@ -124,15 +77,9 @@ PJ_COORD pj_fwdcoord (PJ_COORD coo, PJ *P) { } -PJ_COORD pj_invcoord (PJ_COORD coo, PJ *P) { - if (0!=P->invcoord) - return P->invcoord (coo, P); - if (0!=P->invobs) { - PJ_OBS obs = proj_obs_null; - obs.coo = coo; - obs = P->invobs (obs, P); - return obs.coo; - } +PJ_COORD pj_inv4d (PJ_COORD coo, PJ *P) { + if (0!=P->inv4d) + return P->inv4d (coo, P); if (0!=P->inv3d) { coo.lpz = pj_inv3d (coo.xyz, P); return coo; diff --git a/src/pj_list.c b/src/pj_list.c index 9fde000f..2bdd3053 100644 --- a/src/pj_list.c +++ b/src/pj_list.c @@ -6,26 +6,16 @@ #include "projects.h" - -#define PASTE(a,b) a##b - /* Generate prototypes for projection functions */ #define PROJ_HEAD(id, name) struct PJconsts *pj_##id(struct PJconsts*); #include "pj_list.h" #undef PROJ_HEAD -/* Generate prototypes for projection selftest functions */ -#define PROJ_HEAD(id, name) int PASTE(pj_##id, _selftest) (void); -#include "pj_list.h" -#undef PROJ_HEAD - - /* Generate extern declarations for description strings */ #define PROJ_HEAD(id, name) extern char * const pj_s_##id; #include "pj_list.h" #undef PROJ_HEAD - /* Generate the null-terminated list of projection functions with associated mnemonics and descriptions */ #define PROJ_HEAD(id, name) {#id, pj_##id, &pj_s_##id}, struct PJ_LIST pj_list[] = { @@ -35,21 +25,6 @@ struct PJ_LIST pj_list[] = { #undef PROJ_HEAD -/* Generate the null-terminated list of projection selftest functions with associated mnemonics */ -#define PROJ_HEAD(id, name) {#id, PASTE(pj_##id, _selftest)}, -struct PJ_SELFTEST_LIST pj_selftest_list[] = { -#include "pj_list.h" - {0, 0}, - }; -#undef PROJ_HEAD -#undef PASTE - - struct PJ_LIST *pj_get_list_ref (void) { return pj_list; } - - -struct PJ_SELFTEST_LIST *pj_get_selftest_list_ref (void) { - return pj_selftest_list; -} diff --git a/src/pj_list.h b/src/pj_list.h index bf287219..0720b456 100644 --- a/src/pj_list.h +++ b/src/pj_list.h @@ -12,6 +12,7 @@ PROJ_HEAD(aitoff, "Aitoff") PROJ_HEAD(alsk, "Mod. Stererographics of Alaska") PROJ_HEAD(apian, "Apian Globular I") PROJ_HEAD(august, "August Epicycloidal") +PROJ_HEAD(axisswap, "Axis ordering") PROJ_HEAD(bacon, "Bacon Globular") PROJ_HEAD(bipc, "Bipolar conic of western hemisphere") PROJ_HEAD(boggs, "Boggs Eumorphic") @@ -25,6 +26,7 @@ PROJ_HEAD(chamb, "Chamberlin Trimetric") PROJ_HEAD(collg, "Collignon") PROJ_HEAD(comill, "Compact Miller") PROJ_HEAD(crast, "Craster Parabolic (Putnins P4)") +PROJ_HEAD(deformation, "Kinematic grid shift") PROJ_HEAD(denoy, "Denoyer Semi-Elliptical") PROJ_HEAD(eck1, "Eckert I") PROJ_HEAD(eck2, "Eckert II") diff --git a/src/pj_malloc.c b/src/pj_malloc.c index 4e465c46..c003c717 100644 --- a/src/pj_malloc.c +++ b/src/pj_malloc.c @@ -130,6 +130,16 @@ pointer" to signal an error in a multi level allocation: return 0; } +/**********************************************************************/ +char *pj_strdup(const char *str) +/**********************************************************************/ +{ + size_t len = strlen(str) + 1; + char *dup = pj_malloc(len); + if (dup) + memcpy(dup, str, len); + return dup; +} /*****************************************************************************/ diff --git a/src/pj_pr_list.c b/src/pj_pr_list.c index 5ccfbe5b..00cd4bc3 100644 --- a/src/pj_pr_list.c +++ b/src/pj_pr_list.c @@ -62,6 +62,8 @@ char *pj_get_def( PJ *P, int options ) (void) options; definition = (char *) pj_malloc(def_max); + if (!definition) + return NULL; definition[0] = '\0'; for (t = P->params; t; t = t->next) @@ -78,9 +80,15 @@ char *pj_get_def( PJ *P, int options ) def_max = def_max * 2 + l + 5; def2 = (char *) pj_malloc(def_max); - strcpy( def2, definition ); - pj_dalloc( definition ); - definition = def2; + if (def2) { + strcpy( def2, definition ); + pj_dalloc( definition ); + definition = def2; + } + else { + pj_dalloc( definition ); + return NULL; + } } /* append this parameter */ diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c deleted file mode 100644 index 90193af8..00000000 --- a/src/pj_run_selftests.c +++ /dev/null @@ -1,80 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Generic regression test for PROJ.4 projection algorithms. - * Author: Thomas Knudsen - * - ****************************************************************************** - * Copyright (c) 2016, Thomas Knudsen - * - * 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 <stdio.h> -#define PJ_LIB__ -#include <projects.h> - - -#ifndef PJ_SELFTEST -int pj_run_selftests (int verbosity) { - (void)verbosity; - printf ("This version of libproj is not configured for internal regression tests.\n"); - return 0; -} -#else - - -static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbosity, int *n_ok, int *n_ko, int *n_stubs) { - int ret; - ret = testfunc (); - switch (ret) { - case 0: (*n_ok)++; break; - case 10000: (*n_stubs)++; break; - default: (*n_ko)++; - } - - if (verbosity) { - if (ret==10000) - printf ("Testing: %10s - [stub]\n", mnemonic); - else - printf ("Testing: %10s - return code: %d\n", mnemonic, ret); - } - return; -} - - -int pj_run_selftests (int verbosity) { - int n_ok = 0, n_ko = 0, n_stubs = 0, i = 0; - - struct PJ_SELFTEST_LIST *tests = pj_get_selftest_list_ref (); - - if (0==tests) - printf ("This version of libproj is not configured for internal regression tests.\n"); - - if (verbosity) - printf ("Running internal regression tests\n"); - - for (i = 0; tests[i].testfunc != 0; i++) - run_one_test (tests[i].id, tests[i].testfunc, verbosity, &n_ok, &n_ko, &n_stubs); - - if (0==verbosity) - printf ("Internal regression tests done. "); - printf ("[Stubs: %d] Total: %d. Failure: %d. Success: %d\n", n_stubs, n_ok+n_ko, n_ko, n_ok); - return n_ko; -} -#endif diff --git a/src/pj_strerrno.c b/src/pj_strerrno.c index 89a5a025..fe137b87 100644 --- a/src/pj_strerrno.c +++ b/src/pj_strerrno.c @@ -62,7 +62,8 @@ pj_err_list[] = { "missing required arguments", /* -54 */ "lat_0 = 0", /* -55 */ "ellipsoidal usage unsupported", /* -56 */ - + "only one +init allowed for non-pipeline operations", /* -57 */ + /* When adding error messages, remember to update ID defines in projects.h, and transient_error array in pj_transform */ }; diff --git a/src/pj_strtod.c b/src/pj_strtod.c index 7c2da9a7..4c03a661 100644 --- a/src/pj_strtod.c +++ b/src/pj_strtod.c @@ -101,8 +101,11 @@ static char* pj_replace_point_by_locale_point(const char* pszNumber, char point, strcpy(pszWorkBuffer, pszNumber); pszNew = pszWorkBuffer; } - else - pszNew = strdup(pszNumber); + else { + pszNew = pj_strdup(pszNumber); + if (!pszNew) + return NULL; + } pszNew[pszPoint - pszNumber] = byPoint; return pszNew; } @@ -127,8 +130,11 @@ static char* pj_replace_point_by_locale_point(const char* pszNumber, char point, strcpy(pszWorkBuffer, pszNumber); pszNew = pszWorkBuffer; } - else - pszNew = strdup(pszNumber); + else { + pszNew = pj_strdup(pszNumber); + if (!pszNew) + return NULL; + } if( pszLocalePoint ) pszNew[pszLocalePoint - pszNumber] = ' '; if( pszPoint ) @@ -42,7 +42,7 @@ static char *cheby_str, /* string controlling Chebychev evaluation */ *oform = (char *)0, /* output format for x-y or decimal degrees */ *oterr = "*\t*", /* output line for unprojectable input */ - *usage = "%s\nusage: %s [ -bCeEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n"; + *usage = "%s\nusage: %s [ -beEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n"; static struct FACTORS facs; @@ -287,21 +287,15 @@ static void vprocess(FILE *fid) { (void)printf(oform, dat_xy.u); putchar('\n'); (void)fputs("Northing (y): ", stdout); (void)printf(oform, dat_xy.v); putchar('\n'); - (void)printf("Meridian scale (h)%c: %.8f ( %.4g %% error )\n", - facs.code & IS_ANAL_HK ? '*' : ' ', facs.h, (facs.h-1.)*100.); - (void)printf("Parallel scale (k)%c: %.8f ( %.4g %% error )\n", - facs.code & IS_ANAL_HK ? '*' : ' ', facs.k, (facs.k-1.)*100.); - (void)printf("Areal scale (s): %.8f ( %.4g %% error )\n", - facs.s, (facs.s-1.)*100.); - (void)printf("Angular distortion (w): %.3f\n", facs.omega * - RAD_TO_DEG); - (void)printf("Meridian/Parallel angle: %.5f\n", - facs.thetap * RAD_TO_DEG); - (void)printf("Convergence%c: ",facs.code & IS_ANAL_CONV ? '*' : ' '); + (void)printf("Meridian scale (h) : %.8f ( %.4g %% error )\n", facs.h, (facs.h-1.)*100.); + (void)printf("Parallel scale (k) : %.8f ( %.4g %% error )\n", facs.k, (facs.k-1.)*100.); + (void)printf("Areal scale (s): %.8f ( %.4g %% error )\n", facs.s, (facs.s-1.)*100.); + (void)printf("Angular distortion (w): %.3f\n", facs.omega * RAD_TO_DEG); + (void)printf("Meridian/Parallel angle: %.5f\n", facs.thetap * RAD_TO_DEG); + (void)printf("Convergence : "); (void)fputs(rtodms(pline, facs.conv, 0, 0), stdout); (void)printf(" [ %.8f ]\n", facs.conv * RAD_TO_DEG); - (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", - facs.a, facs.b); + (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", facs.a, facs.b); } } @@ -329,9 +323,6 @@ int main(int argc, char **argv) { case 'b': /* binary I/O */ bin_in = bin_out = 1; continue; - case 'C': /* Check - run internal regression tests */ - return pj_run_selftests (very_verby); - continue; case 'v': /* monitor dump of initialization */ mon = 1; continue; diff --git a/src/proj.def b/src/proj.def index 598f2824..dd4a456c 100644 --- a/src/proj.def +++ b/src/proj.def @@ -88,62 +88,61 @@ EXPORTS geod_polygon_testedge @86 geod_polygon_testpoint @87 geod_polygon_clear @88 - pj_run_selftests @89 - pj_find_file @90 + pj_find_file @89 - proj_create @91 - proj_create_argv @92 - proj_create_crs_to_crs @93 - proj_destroy @94 + proj_create @90 + proj_create_argv @91 + proj_create_crs_to_crs @92 + proj_destroy @93 - proj_trans_obs @95 - proj_trans_coord @96 - proj_transform @97 - proj_transform_obs @98 - proj_transform_coord @99 - proj_roundtrip @100 + proj_trans @94 + proj_trans_array @95 + proj_trans_generic @96 + proj_roundtrip @97 - proj_coord @101 - proj_obs @102 - proj_coord_error @103 - proj_obs_error @104 + proj_coord @98 + proj_coord_error @99 - proj_errno @105 - proj_errno_set @106 - proj_errno_reset @107 - proj_errno_restore @108 - proj_context_errno_set @109 + proj_errno @100 + proj_errno_set @101 + proj_errno_reset @102 + proj_errno_restore @103 + proj_context_errno_set @104 - proj_context_create @110 - proj_context_set @111 - proj_context_inherit @112 - proj_context_destroy @113 + proj_context_create @105 + proj_context_set @106 + proj_context_inherit @107 + proj_context_destroy @108 - proj_lp_dist @114 - proj_xy_dist @115 - proj_xyz_dist @116 + proj_lp_dist @109 + proj_lpz_dist @110 + proj_xy_dist @111 + proj_xyz_dist @112 - proj_log_level @117 - proj_log_func @118 - proj_log_error @119 - proj_log_debug @120 - proj_log_trace @121 + proj_log_level @113 + proj_log_func @114 + proj_log_error @115 + proj_log_debug @116 + proj_log_trace @117 - proj_info @122 - proj_pj_info @123 - proj_grid_info @124 - proj_init_info @125 + proj_info @118 + proj_pj_info @119 + proj_grid_info @120 + proj_init_info @121 - proj_torad @126 - proj_todeg @127 - proj_rtodms @128 - proj_dmstor @129 + proj_torad @122 + proj_todeg @123 + proj_rtodms @124 + proj_dmstor @125 - proj_derivatives @130 - proj_factors @131 + proj_derivatives @126 + proj_factors @127 - proj_list_operations @132 - proj_list_ellps @133 - proj_list_units @134 - proj_list_prime_meridians @135 + proj_list_operations @128 + proj_list_ellps @129 + proj_list_units @130 + proj_list_prime_meridians @131 + + proj_angular_input @132 + proj_angular_output @133 @@ -53,26 +53,21 @@ * it remains as-is for now). * * THIRD, I try to eliminate implicit type punning. Hence this API - * introduces the PJ_OBS ("observation") data type, for generic - * coordinate and handling of ancillary data. + * introduces the PJ_COORD union data type, for generic 4D coordinate + * handling. * - * It includes the PJ_COORD and PJ_TRIPLET unions making it possible - * to make explicit the previously used "implicit type punning", where - * a XY is turned into a LP by re#defining both as UV, behind the back - * of the user. + * PJ_COORD makes it possible to make explicit the previously used + * "implicit type punning", where a XY is turned into a LP by + * re#defining both as UV, behind the back of the user. * * The PJ_COORD union is used for storing 1D, 2D, 3D and 4D coordinates. - * The PJ_TRIPLET union is used for storing any set of up to 3 related - * observations. At the application code level, the names of these - * unions will usually not be used - they will only be accessed via - * their tag names in the PJ_OBS data type. * * The bare essentials API presented here follows the PROJ.4 * convention of sailing the coordinate to be reprojected, up on * the stack ("call by value"), and symmetrically returning the - * result on the stack. Although the PJ_OBS object is 4 times - * as large as the traditional XY and LP objects, timing results - * have shown the overhead to be very reasonable. + * result on the stack. Although the PJ_COORD object is twice as large + * as the traditional XY and LP objects, timing results have shown the + * overhead to be very reasonable. * * Contexts and thread safety * -------------------------- @@ -82,15 +77,15 @@ * context subsystem is unavoidable in a multi-threaded world. * Hence, instead of hiding it away, we move it into the limelight, * highly recommending (but not formally requiring) the bracketing - * with calls to proj_context_create(...)/proj_context_destroy() of - * any code block calling PROJ.4 functions. + * of any code block calling PROJ.4 functions with calls to + * proj_context_create(...)/proj_context_destroy() * * Legacy single threaded code need not do anything, but *may* * implement a bit of future compatibility by using the backward * compatible call proj_context_create(0), which will not create * a new context, but simply provide a pointer to the default one. * - * See pj_obs_api_test.c for an example of how to use the API. + * See proj_4D_api_test.c for examples of how to use the API. * * Author: Thomas Knudsen, <thokn@sdfe.dk> * Benefitting from a large number of comments and suggestions @@ -170,10 +165,6 @@ extern char const pj_release[]; /* global release id string */ /* first forward declare everything needed */ -/* Data type for generic geodetic observations */ -struct PJ_OBS; -typedef struct PJ_OBS PJ_OBS; - /* Data type for generic geodetic 3D data */ union PJ_TRIPLET; typedef union PJ_TRIPLET PJ_TRIPLET; @@ -182,6 +173,9 @@ typedef union PJ_TRIPLET PJ_TRIPLET; union PJ_COORD; typedef union PJ_COORD PJ_COORD; +struct PJ_AREA; +typedef struct PJ_AREA PJ_AREA; + struct DERIVS; typedef struct DERIVS PJ_DERIVS; @@ -212,9 +206,6 @@ typedef struct PJ_LIST PJ_OPERATIONS; struct PJ_ELLPS; typedef struct PJ_ELLPS PJ_ELLPS; -struct PJ_DATUMS; -typedef struct PJ_DATUMS PJ_DATUMS; - struct PJ_UNITS; typedef struct PJ_UNITS PJ_UNITS; @@ -298,18 +289,6 @@ union PJ_PAIR { double v[2]; /* Yes - It's really just a vector! */ }; -struct PJ_OBS { - PJ_COORD coo; /* coordinate data */ - PJ_TRIPLET anc; /* ancillary data */ - int id; /* integer ancillary data - e.g. observation number, EPSG code... */ - unsigned int flags; /* additional data, intended for flags */ -}; - -#define PJ_IS_ANAL_XL_YL 01 /* derivatives of lon analytic */ -#define PJ_IS_ANAL_XP_YP 02 /* derivatives of lat analytic */ -#define PJ_IS_ANAL_HK 04 /* h and k analytic */ -#define PJ_IS_ANAL_CONV 010 /* convergence analytic */ - struct PJ_INFO { char release[64]; /* Release info. Version + date */ char version[64]; /* Full version number */ @@ -366,9 +345,14 @@ PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx); /* Manage the transformation definition object PJ */ PJ *proj_create (PJ_CONTEXT *ctx, const char *definition); PJ *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv); -PJ *proj_create_crs_to_crs(PJ_CONTEXT *ctx, const char *srid_from, const char *srid_to); +PJ *proj_create_crs_to_crs(PJ_CONTEXT *ctx, const char *srid_from, const char *srid_to, PJ_AREA *area); PJ *proj_destroy (PJ *P); +/* Setter-functions for the opaque PJ_AREA struct */ +/* Uncomment these when implementing support for area-based transformations. +void proj_area_bbox(PJ_AREA *area, LP ll, LP ur); +void proj_area_description(PJ_AREA *area, const char *descr); +*/ /* Apply transformation to observation - in forward or inverse direction */ enum PJ_DIRECTION { @@ -378,11 +362,17 @@ enum PJ_DIRECTION { }; typedef enum PJ_DIRECTION PJ_DIRECTION; -PJ_OBS proj_trans_obs (PJ *P, PJ_DIRECTION direction, PJ_OBS obs); -PJ_COORD proj_trans_coord (PJ *P, PJ_DIRECTION direction, PJ_COORD coord); -size_t proj_transform ( + +int proj_angular_input (PJ *P, enum PJ_DIRECTION dir); +int proj_angular_output (PJ *P, enum PJ_DIRECTION dir); + + +PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coord); + + +size_t proj_trans_generic ( PJ *P, PJ_DIRECTION direction, double *x, size_t sx, size_t nx, @@ -391,19 +381,20 @@ size_t proj_transform ( double *t, size_t st, size_t nt ); -int proj_transform_obs (PJ *P, PJ_DIRECTION direction, size_t n, PJ_OBS *obs); -int proj_transform_coord (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord); +int proj_trans_array (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord); /* Initializers */ PJ_COORD proj_coord (double x, double y, double z, double t); -PJ_OBS proj_obs (double x, double y, double z, double t, double o, double p, double k, int id, unsigned int flags); /* Measure internal consistency - in forward or inverse direction */ -double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD coo); - +double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo); + /* Geodesic distance between two points with angular 2D coordinates */ double proj_lp_dist (const PJ *P, LP a, LP b); +/* The geodesic distance AND the vertical offset */ +double proj_lpz_dist (const PJ *P, LPZ a, LPZ b); + /* Euclidean distance between two points with linear 2D coordinates */ double proj_xy_dist (XY a, XY b); @@ -434,7 +425,7 @@ const PJ_ELLPS *proj_list_ellps(void); const PJ_UNITS *proj_list_units(void); const PJ_PRIME_MERIDIANS *proj_list_prime_meridians(void); -/* These are trivial, and while occasionaly useful in real code, primarily here to */ +/* These are trivial, and while occasionally useful in real code, primarily here to */ /* simplify demo code, and in acknowledgement of the proj-internal discrepancy between */ /* angular units expected by classical proj, and by Charles Karney's geodesics subsystem */ double proj_torad (double angle_in_degrees); diff --git a/src/pj_obs_api.c b/src/proj_4D_api.c index 9f699fcf..6e89fb60 100644 --- a/src/pj_obs_api.c +++ b/src/proj_4D_api.c @@ -1,18 +1,12 @@ /****************************************************************************** * Project: PROJ.4 * Purpose: Implement a (currently minimalistic) proj API based primarily - * on the PJ_OBS generic geodetic data type. - * - * proj thread contexts have not seen widespread use, so one of the - * intentions with this new API is to make them less visible on the - * API surface: Contexts do not have a life by themselves, they are - * visible only through their associated PJs, and the number of - * functions supporting them is limited. + * on the PJ_COORD 4D geodetic spatiotemporal data type. * * Author: Thomas Knudsen, thokn@sdfe.dk, 2016-06-09/2016-11-06 * ****************************************************************************** - * Copyright (c) 2016, 2017 Thomas Knudsen/SDFE + * Copyright (c) 2016, 2017 Thomas Knudsen/SDFE * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -32,13 +26,13 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ -#define PJ_OBS_API_C +#include <stddef.h> +#include <errno.h> +#include <ctype.h> #include <proj.h> #include "proj_internal.h" #include "projects.h" #include "geodesic.h" -#include <stddef.h> -#include <errno.h> /* Initialize PJ_COORD struct */ @@ -51,22 +45,27 @@ PJ_COORD proj_coord (double x, double y, double z, double t) { return res; } -/* Initialize PJ_OBS struct */ -PJ_OBS proj_obs (double x, double y, double z, double t, double o, double p, double k, int id, unsigned int flags) { - PJ_OBS res; - res.coo.v[0] = x; - res.coo.v[1] = y; - res.coo.v[2] = z; - res.coo.v[3] = t; - res.anc.v[0] = o; - res.anc.v[1] = p; - res.anc.v[2] = k; - res.id = id; - res.flags = flags; - - return res; +/*****************************************************************************/ +int proj_angular_input (PJ *P, enum PJ_DIRECTION dir) { +/****************************************************************************** + Returns 1 if the operator P expects angular input coordinates when + operating in direction dir, 0 otherwise. + dir: {PJ_FWD, PJ_INV} +******************************************************************************/ + if (PJ_FWD==dir) + return pj_left (P)==PJ_IO_UNITS_RADIANS; + return pj_right (P)==PJ_IO_UNITS_RADIANS; } +/*****************************************************************************/ +int proj_angular_output (PJ *P, enum PJ_DIRECTION dir) { +/****************************************************************************** + Returns 1 if the operator P provides angular output coordinates when + operating in direction dir, 0 otherwise. + dir: {PJ_FWD, PJ_INV} +******************************************************************************/ + return proj_angular_input (P, -dir); +} /* Geodesic distance (in meter) between two points with angular 2D coordinates */ @@ -77,6 +76,14 @@ double proj_lp_dist (const PJ *P, LP a, LP b) { return s12; } +/* The geodesic distance AND the vertical offset */ +double proj_lpz_dist (const PJ *P, LPZ a, LPZ b) { + PJ_COORD aa, bb; + aa.lpz = a; + bb.lpz = b; + return hypot (proj_lp_dist (P, aa.lp, bb.lp), a.z - b.z); +} + /* Euclidean distance between two points with linear 2D coordinates */ double proj_xy_dist (XY a, XY b) { return hypot (a.x - b.x, a.y - b.y); @@ -90,10 +97,9 @@ double proj_xyz_dist (XYZ a, XYZ b) { /* Measure numerical deviation after n roundtrips fwd-inv (or inv-fwd) */ -double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD coo) { +double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coo) { int i; - PJ_COORD o, u; - enum pj_io_units unit; + PJ_COORD o, u, org; if (0==P) return HUGE_VAL; @@ -103,92 +109,75 @@ double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD coo) { return HUGE_VAL; } - o = coo; + /* in the first half-step, we generate the output value */ + u = org = *coo; + o = *coo = proj_trans (P, direction, u); - switch (direction) { - case PJ_FWD: - for (i = 0; i < n; i++) { - u = pj_fwdcoord (o, P); - o = pj_invcoord (u, P); - } - break; - case PJ_INV: - for (i = 0; i < n; i++) { - u = pj_invcoord (o, P); - o = pj_fwdcoord (u, P); - } - break; - default: - proj_errno_set (P, EINVAL); - return HUGE_VAL; + /* now we take n-1 full steps */ + for (i = 0; i < n - 1; i++) { + u = proj_trans (P, -direction, o); + o = proj_trans (P, direction, u); } - /* left when forward, because we do a roundtrip, and end where we begin */ - unit = direction==PJ_FWD? P->left: P->right; - if (unit==PJ_IO_UNITS_RADIANS) - return hypot (proj_lp_dist (P, coo.lp, o.lp), coo.lpz.z - o.lpz.z); - - return proj_xyz_dist (coo.xyz, coo.xyz); -} - - - - - - - - + /* finally, we take the last half-step */ + u = proj_trans (P, -direction, o); + /* checking for angular *input* since we do a roundtrip, and end where we begin */ + if (proj_angular_input (P, direction)) + return proj_lpz_dist (P, org.lpz, u.lpz); + return proj_xyz_dist (org.xyz, u.xyz); +} /* Apply the transformation P to the coordinate coo */ -PJ_OBS proj_trans_obs (PJ *P, PJ_DIRECTION direction, PJ_OBS obs) { +PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD coo) { if (0==P) - return obs; + return coo; + if (P->inverted) + direction = -direction; switch (direction) { case PJ_FWD: - return pj_fwdobs (obs, P); + return pj_fwd4d (coo, P); case PJ_INV: - return pj_invobs (obs, P); + return pj_inv4d (coo, P); case PJ_IDENT: - return obs; + return coo; default: break; } proj_errno_set (P, EINVAL); - return proj_obs_error (); + return proj_coord_error (); } -/* Apply the transformation P to the coordinate coo */ -PJ_COORD proj_trans_coord (PJ *P, PJ_DIRECTION direction, PJ_COORD coo) { - if (0==P) - return coo; +/*****************************************************************************/ +int proj_trans_array (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) { +/****************************************************************************** + Batch transform an array of PJ_COORD. - switch (direction) { - case PJ_FWD: - return pj_fwdcoord (coo, P); - case PJ_INV: - return pj_invcoord (coo, P); - case PJ_IDENT: - return coo; - default: - break; + Returns 0 if all coordinates are transformed without error, otherwise + returns error number. +******************************************************************************/ + size_t i; + + for (i = 0; i < n; i++) { + coord[i] = proj_trans (P, direction, coord[i]); + if (proj_errno(P)) + return proj_errno (P); } - proj_errno_set (P, EINVAL); - return proj_coord_error (); + return 0; } /*************************************************************************************/ -size_t proj_transform ( +size_t proj_trans_generic ( PJ *P, PJ_DIRECTION direction, double *x, size_t sx, size_t nx, @@ -245,12 +234,16 @@ size_t proj_transform ( Return value: Number of transformations completed. **************************************************************************************/ - PJ_COORD coord = proj_coord_null; + PJ_COORD coord = {{0,0,0,0}}; size_t i, nmin; double null_broadcast = 0; + if (0==P) return 0; + if (P->inverted) + direction = -direction; + /* ignore lengths of null arrays */ if (0==x) nx = 0; if (0==y) ny = 0; @@ -300,31 +293,33 @@ size_t proj_transform ( coord.xyzt.t = *t; if (PJ_FWD==direction) - coord = pj_fwdcoord (coord, P); + coord = pj_fwd4d (coord, P); else - coord = pj_invcoord (coord, P); + coord = pj_inv4d (coord, P); - /* in all full length cases, we overwrite the input with the output */ + /* in all full length cases, we overwrite the input with the output, */ + /* and step on to the next element. */ + /* The casts are somewhat funky, but they compile down to no-ops and */ + /* they tell compilers and static analyzers that we know what we do */ if (nx > 1) { - *x = coord.xyzt.x; - x = (double *) ( ((char *) x) + sx); + *x = coord.xyzt.x; + x = (double *) ((void *) ( ((char *) x) + sx)); } if (ny > 1) { - *y = coord.xyzt.y; - y = (double *) ( ((char *) y) + sy); + *y = coord.xyzt.y; + y = (double *) ((void *) ( ((char *) y) + sy)); } if (nz > 1) { - *z = coord.xyzt.z; - z = (double *) ( ((char *) z) + sz); + *z = coord.xyzt.z; + z = (double *) ((void *) ( ((char *) z) + sz)); } if (nt > 1) { - *t = coord.xyzt.t; - t = (double *) ( ((char *) t) + st); + *t = coord.xyzt.t; + t = (double *) ((void *) ( ((char *) t) + st)); } } + /* Last time around, we update the length 1 cases with their transformed alter egos */ - /* ... or would we rather not? Then what about the nmin==1 case? */ - /* perhaps signalling the non-array case by setting all strides to 0? */ if (nx==1) *x = coord.xyzt.x; if (ny==1) @@ -337,64 +332,108 @@ size_t proj_transform ( return i; } -/*****************************************************************************/ -int proj_transform_obs (PJ *P, PJ_DIRECTION direction, size_t n, PJ_OBS *obs) { -/****************************************************************************** - Batch transform an array of PJ_OBS. - Returns 0 if all observations are transformed without error, otherwise - returns error number. -******************************************************************************/ - size_t i; - for (i=0; i<n; i++) { - obs[i] = proj_trans_obs(P, direction, obs[i]); - if (proj_errno(P)) - return proj_errno(P); - } +/*************************************************************************************/ +PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) { +/************************************************************************************** + Create a new PJ object in the context ctx, using the given definition. If ctx==0, + the default context is used, if definition==0, or invalid, a null-pointer is + returned. The definition may use '+' as argument start indicator, as in + "+proj=utm +zone=32", or leave it out, as in "proj=utm zone=32" +**************************************************************************************/ + PJ *P; + char *args, **argv; + int argc, i, j, n; - return 0; -} + if (0==ctx) + ctx = pj_get_default_ctx (); -/*****************************************************************************/ -int proj_transform_coord (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) { -/****************************************************************************** - Batch transform an array of PJ_COORD. + /* make a copy that we can manipulate */ + n = (int) strlen (definition); + args = (char *) malloc (n + 1); + if (0==args) + return 0; + strcpy (args, definition); - Returns 0 if all coordinates are transformed without error, otherwise - returns error number. -******************************************************************************/ - size_t i; - for (i=0; i<n; i++) { - coord[i] = proj_trans_coord(P, direction, coord[i]); - if (proj_errno(P)) - return proj_errno(P); - } + /* all-in-one: count args, eliminate superfluous whitespace, 0-terminate substrings */ + for (i = j = argc = 0; i < n; ) { + /* skip prefix whitespace */ + while (isspace (args[i])) + i++; - return 0; -} + /* skip at most one prefix '+' */ + if ('+'==args[i]) + i++; + /* whitespace after a '+' is a syntax error - but by Postel's prescription, we ignore and go on */ + if (isspace (args[i])) + continue; + /* move a whitespace delimited text string to the left, skipping over superfluous whitespace */ + while ((0!=args[i]) && (!isspace (args[i]))) + args[j++] = args[i++]; -PJ *proj_create (PJ_CONTEXT *ctx, const char *definition) { - if (0==ctx) - ctx = pj_get_default_ctx (); - return pj_init_plus_ctx (ctx, definition); + /* terminate string - if that makes j pass i (often the case for first arg), let i catch up */ + args[j++] = 0; + if (i < j) + i = j; + + /* we finished another arg */ + argc++; + + /* skip postfix whitespace */ + while (isspace (args[i])) + i++; + } + + /* turn the massaged input into an array of strings */ + argv = (char **) calloc (argc, sizeof (char *)); + if (0==argv) + return pj_dealloc (args); + + argv[0] = args; + for (i = 0, j = 1; i < n; i++) { + if (0==args[i]) + argv[j++] = args + (i + 1); + if (j==argc) + break; + } + + /* ...and let pj_init_ctx do the hard work */ + P = pj_init_ctx (ctx, argc, argv); + pj_dealloc (argv); + pj_dealloc (args); + return P; } + + +/*************************************************************************************/ PJ *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv) { +/************************************************************************************** +Create a new PJ object in the context ctx, using the given definition argument +array argv. If ctx==0, the default context is used, if definition==0, or invalid, +a null-pointer is returned. The definition arguments may use '+' as argument start +indicator, as in {"+proj=utm", "+zone=32"}, or leave it out, as in {"proj=utm", +"zone=32"}. +**************************************************************************************/ + if (0==argv) + return 0; if (0==ctx) ctx = pj_get_default_ctx (); return pj_init_ctx (ctx, argc, argv); } + + /*****************************************************************************/ -PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *srid_from, const char *srid_to) { +PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *srid_from, const char *srid_to, PJ_AREA *area) { /****************************************************************************** Create a transformation pipeline between two known coordinate reference systems. srid_from and srid_to should be the value part of a +init=... parameter - set, i.e. "epsg:25833" or "IGNF:AMST63". Any projection definition that is + set, i.e. "epsg:25833" or "IGNF:AMST63". Any projection definition that can be found in a init-file in PROJ_LIB is a valid input to this function. For now the function mimics the cs2cs app: An input and an output CRS is @@ -403,14 +442,23 @@ PJ *proj_create_crs_to_crs (PJ_CONTEXT *ctx, const char *srid_from, const char function can be extended to support "late-binding" transformations in the future without affecting users of the function. + An "area of use" can be specified in area. In the current version of this + function is has no function, but is added in anticipation of a + "late-binding" implementation in the future. The idea being, that if a user + supplies an area of use, the more accurate transformation between two given + systems can be chosen. + Example call: - PJ *P = proj_create_crs_to_crs(0, "epsg:25832", "epsg:25833"); + PJ *P = proj_create_crs_to_crs(0, "epsg:25832", "epsg:25833", NULL); ******************************************************************************/ PJ *P; char buffer[512]; + /* area not in use yet, suppressing warning */ + (void)area; + strcpy(buffer, "+proj=pipeline +step +init="); strncat(buffer, srid_from, 512-strlen(buffer)); strncat(buffer, " +inv +step +init=", 512-strlen(buffer)); @@ -495,7 +543,7 @@ int proj_errno_reset (PJ *P) { } -/* Create a new context - or provide a pointer to the default context */ +/* Create a new context */ PJ_CONTEXT *proj_context_create (void) { return pj_ctx_alloc (); } @@ -618,7 +666,7 @@ PJ_PROJ_INFO proj_pj_info(PJ *P) { /* this does not take into account that a pipeline potentially does not */ /* have an inverse. */ - info.has_inverse = (P->inv != 0 || P->inv3d != 0 || P->invobs != 0); + info.has_inverse = (P->inv != 0 || P->inv3d != 0 || P->inv4d != 0); return info; } @@ -768,9 +816,6 @@ PJ_FACTORS proj_factors(PJ *P, const LP lp) { ******************************************************************************/ PJ_FACTORS factors; - /* pj_factors rely code being zero */ - factors.code = 0; - if (pj_factors(lp, P, 0.0, &factors)) { /* errno set in pj_factors */ memset(&factors, 0, sizeof(PJ_FACTORS)); diff --git a/src/proj_api.h b/src/proj_api.h index 2add2946..b0c4b71f 100644 --- a/src/proj_api.h +++ b/src/proj_api.h @@ -167,6 +167,7 @@ void *pj_malloc(size_t); void pj_dalloc(void *); void *pj_calloc (size_t n, size_t size); void *pj_dealloc (void *ptr); +char *pj_strdup(const char *str); char *pj_strerrno(int); int *pj_get_errno_ref(void); const char *pj_get_release(void); @@ -174,8 +175,6 @@ void pj_acquire_lock(void); void pj_release_lock(void); void pj_cleanup_lock(void); -int pj_run_selftests (int verbosity); - void pj_set_ctx( projPJ, projCtx ); projCtx pj_ctx_alloc(void); void pj_ctx_free( projCtx ); diff --git a/src/proj_etmerc.c b/src/proj_etmerc.c index a756a7ac..b03862f8 100644 --- a/src/proj_etmerc.c +++ b/src/proj_etmerc.c @@ -332,63 +332,6 @@ PJ *PROJECTION(etmerc) { - - - - -#ifndef PJ_SELFTEST -int pj_etmerc_selftest (void) {return 0;} -#else - -int pj_etmerc_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=etmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {222650.79679758562, 110642.22941193319}, - {222650.79679758562, -110642.22941193319}, - {-222650.79679758562, 110642.22941193319}, - {-222650.79679758562, -110642.22941193319}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {0.0017966305681649398, 0.00090436947663183873}, - {0.0017966305681649398, -0.00090436947663183873}, - {-0.0017966305681649398, 0.00090436947663183873}, - {-0.0017966305681649398, -0.00090436947663183873}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} -#endif - - - - - - - - - - - - /* utm uses etmerc for the underlying projection */ @@ -429,48 +372,3 @@ PJ *PROJECTION(utm) { return setup (P); } - -#ifndef PJ_SELFTEST -int pj_utm_selftest (void) {return 0;} -#else - -int pj_utm_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - {1057002.4054912981, 110955.14117594929}, - {1057002.4054912981, -110955.14117594929}, - {611263.81227890507, 110547.10569680421}, - {611263.81227890507, -110547.10569680421}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - {-7.4869520833902357, 0.00090193980983462605}, - {-7.4869520833902357, -0.00090193980983462605}, - {-7.4905356820622613, 0.00090193535121489081}, - {-7.4905356820622613, -0.00090193535121489081}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} -#endif - - - diff --git a/src/proj_internal.h b/src/proj_internal.h index 0b74b563..95f34994 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -48,8 +48,6 @@ extern "C" { #endif - - #ifndef PJ_TODEG #define PJ_TODEG(rad) ((rad)*180.0/M_PI) #endif @@ -57,30 +55,33 @@ extern "C" { #define PJ_TORAD(deg) ((deg)*M_PI/180.0) #endif +/* This enum is also conditionally defined in projects.h - but we need it here */ +/* for the pj_left/right prototypes, and enums cannot be forward declared */ +enum pj_io_units { + PJ_IO_UNITS_CLASSIC = 0, /* Scaled meters (right) */ + PJ_IO_UNITS_METERS = 1, /* Meters */ + PJ_IO_UNITS_RADIANS = 2 /* Radians */ +}; +enum pj_io_units pj_left (PJ *P); +enum pj_io_units pj_right (PJ *P); +PJ_COORD proj_trans (PJ *P, PJ_DIRECTION direction, PJ_COORD obs); PJ_COORD proj_coord_error (void); -PJ_OBS proj_obs_error (void); -#ifndef PJ_INTERNAL_C -extern const PJ_COORD proj_coord_null; -extern const PJ_OBS proj_obs_null; -#endif -/* Part of MSVC workaround: Make proj_*_null look function-like for symmetry with proj_*_error */ -#define proj_coord_null(x) proj_coord_null -#define proj_obs_null(x) proj_obs_null - void proj_context_errno_set (PJ_CONTEXT *ctx, int err); void proj_context_set (PJ *P, PJ_CONTEXT *ctx); void proj_context_inherit (PJ *parent, PJ *child); +PJ_COORD pj_fwd4d (PJ_COORD coo, PJ *P); +PJ_COORD pj_inv4d (PJ_COORD coo, PJ *P); -PJ_OBS pj_fwdobs (PJ_OBS obs, PJ *P); -PJ_OBS pj_invobs (PJ_OBS obs, PJ *P); -PJ_COORD pj_fwdcoord (PJ_COORD coo, PJ *P); -PJ_COORD pj_invcoord (PJ_COORD coo, PJ *P); - - +/* Grid functionality */ +int proj_vgrid_init(PJ *P, const char *grids); +int proj_hgrid_init(PJ *P, const char *grids); +double proj_vgrid_value(PJ *P, LP lp); +LP proj_hgrid_value(PJ *P, LP lp); +LP proj_hgrid_apply(PJ *P, LP lp, PJ_DIRECTION direction); /* High level functionality for handling thread contexts */ enum proj_log_level { @@ -103,6 +104,8 @@ void proj_log_trace (PJ *P, const char *fmt, ...); /*void proj_log_func (PJ *P, void *app_data, void (*log)(void *, int, const char *));*/ void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION log); +void pj_inherit_ellipsoid_defs(const PJ *src, PJ *dst); +int pj_calc_ellps_params(PJ *P, double a, double es); /* Lowest level: Minimum support for fileapi */ void proj_fileapi_set (PJ *P, void *fileapi); diff --git a/src/proj_rouss.c b/src/proj_rouss.c index 952e5c55..5555e3e4 100644 --- a/src/proj_rouss.c +++ b/src/proj_rouss.c @@ -152,47 +152,3 @@ PJ *PROJECTION(rouss) { return P; } - -#ifndef PJ_SELFTEST -int pj_rouss_selftest (void) {return 0;} -#else - -int pj_rouss_selftest (void) { - double tolerance_lp = 1e-10; - double tolerance_xy = 1e-7; - - char e_args[] = {"+proj=rouss +ellps=GRS80 +lat_1=0.5 +lat_2=2"}; - - LP fwd_in[] = { - { 2, 1}, - { 2,-1}, - {-2, 1}, - {-2,-1} - }; - - XY e_fwd_expect[] = { - { 222644.89413161727, 110611.09186837047}, - { 222644.89413161727, -110611.09186837047}, - {-222644.89413161727, 110611.09186837047}, - {-222644.89413161727, -110611.09186837047}, - }; - - XY inv_in[] = { - { 200, 100}, - { 200,-100}, - {-200, 100}, - {-200,-100} - }; - - LP e_inv_expect[] = { - { 0.0017966305682019911, 0.00090436947683699559}, - { 0.0017966305682019911, -0.00090436947683699559}, - {-0.0017966305682019911, 0.00090436947683699559}, - {-0.0017966305682019911, -0.00090436947683699559}, - }; - - return pj_generic_selftest (e_args, 0, tolerance_xy, tolerance_lp, 4, 4, fwd_in, e_fwd_expect, 0, inv_in, e_inv_expect, 0); -} - - -#endif diff --git a/src/proj_strtod.c b/src/proj_strtod.c index e9942e5c..fa683465 100644 --- a/src/proj_strtod.c +++ b/src/proj_strtod.c @@ -17,7 +17,7 @@ In the early versions of proj, iirc, a gnu version of strtod was used, mostly to work around cases where the same system library was used for C and Fortran linking, hence making strtod accept "D" and "d" as exponentiation indicators, following Fortran Double Precision constant -syntax. This broke the proj angular syntax accepting a "d" to mean +syntax. This broke the proj angular syntax, accepting a "d" to mean "degree": 12d34'56", meaning 12 degrees 34 minutes and 56 seconds. With an explicit MIT licence, PROJ.4 could not include GPL code any @@ -86,6 +86,8 @@ Thomas Knudsen, thokn@sdfe.dk, 2017-01-17/2017-09-18 ***********************************************************************/ +#include <stdlib.h> /* for abs */ +#include <string.h> /* for strchr */ #include <errno.h> #include <ctype.h> #include <float.h> /* for HUGE_VAL */ @@ -93,16 +95,18 @@ Thomas Knudsen, thokn@sdfe.dk, 2017-01-17/2017-09-18 double proj_strtod(const char *str, char **endptr); double proj_atof(const char *str); - + double proj_strtod(const char *str, char **endptr) { - double number = 0; + double number = 0, integral_part = 0; int exponent = 0; + int fraction_is_nonzero = 0; int sign = 0; char *p = (char *) str; int n = 0; - int num_digits_total = 0; - int num_digits_after_comma = 0; + int num_digits_total = 0; + int num_digits_after_comma = 0; + int num_prefixed_zeros = 0; if (0==str) { errno = EFAULT; @@ -117,25 +121,48 @@ double proj_strtod(const char *str, char **endptr) { /* Empty string? */ if (0==*p) { - errno = EINVAL; if (endptr) - *endptr = p; - return HUGE_VAL; + *endptr = (char *) str; + return 0; + } + + /* non-numeric? */ + if (0==strchr("0123456789+-._", *p)) { + if (endptr) + *endptr = (char *) str; + return 0; } - /* Then handle optional prefixed sign */ + /* Then handle optional prefixed sign and skip prefix zeros */ switch (*p) { case '-': - sign = -1, p++; break; + sign = -1, p++; break; case '+': sign = 1, p++; break; default: if (isdigit(*p) || '_'==*p || '.'==*p) break; if (endptr) - *endptr = p; - errno = EINVAL; - return HUGE_VAL; + *endptr = (char *) str; + return 0; + } + + /* stray sign, as in "+/-"? */ + if (0!=sign && (0==strchr ("0123456789._", *p) || 0==*p)) { + if (endptr) + *endptr = (char *) str; + return 0; + } + + /* skip prefixed zeros before '.' */ + while ('0'==*p || '_'==*p) + p++; + + /* zero? */ + if ((0==*p) || 0==strchr ("0123456789eE.", *p) || isspace(*p)) { + if (endptr) + *endptr = p; + return sign==-1? -0: 0; } /* Now expect a (potentially zero-length) string of digits */ @@ -148,24 +175,61 @@ double proj_strtod(const char *str, char **endptr) { p++; num_digits_total++; } - + integral_part = number; + + /* Done? */ + if (0==*p) { + if (endptr) + *endptr = p; + if (sign==-1) + return -number; + return number; + } + /* Do we have a fractional part? */ if ('.'==*p) { p++; + /* keep on skipping prefixed zeros (i.e. allow writing 1e-20 */ + /* as 0.00000000000000000001 without losing precision) */ + if (0==integral_part) + while ('0'==*p || '_'==*p) { + if ('0'==*p) + num_prefixed_zeros++; + p++; + } + + /* if the next character is nonnumeric, we have reached the end */ + if (0==*p || 0==strchr ("_0123456789eE+-", *p)) { + if (endptr) + *endptr = p; + if (sign==-1) + return -number; + return number; + } + while (isdigit(*p) || '_'==*p) { - if ('_'==*p) { + /* Don't let pathologically long fractions destroy precision */ + if ('_'==*p || num_digits_total > 17) { p++; continue; } + number = number * 10. + (*p - '0'); + if (*p!='0') + fraction_is_nonzero = 1; p++; num_digits_total++; num_digits_after_comma++; } - exponent = -num_digits_after_comma; - } + /* Avoid having long zero-tails (4321.000...000) destroy precision */ + if (fraction_is_nonzero) + exponent = -(num_digits_after_comma + num_prefixed_zeros); + else + number = integral_part; + } /* end of fractional part */ + /* non-digit */ if (0==num_digits_total) { @@ -179,8 +243,17 @@ double proj_strtod(const char *str, char **endptr) { number = -number; /* Do we have an exponent part? */ - if (*p == 'e' || *p == 'E') { + while (*p == 'e' || *p == 'E') { p++; + + /* Just a stray "e", as in 100elephants? */ + if (0==*p || 0==strchr ("0123456789+-_", *p)) { + p--; + break; + } + + while ('_'==*p) + p++; /* Does it have a sign? */ sign = 0; if ('-'==*p) @@ -212,36 +285,152 @@ double proj_strtod(const char *str, char **endptr) { if (-1==sign) n = -n; exponent += n; + break; } - if ((exponent < DBL_MIN_EXP) || (exponent > DBL_MAX_EXP)) { - errno = ERANGE; - if (endptr) - *endptr = p; - return HUGE_VAL; - } - - number *= pow (10, exponent); + if (endptr) + *endptr = p; - if (fabs(number) > DBL_MAX) + if ((exponent < DBL_MIN_EXP) || (exponent > DBL_MAX_EXP)) { errno = ERANGE; + return HUGE_VAL; + } - if (endptr) - *endptr = p; + /* on some platforms pow() is very slow - so don't call it if exponent is close to 0 */ + if (0==exponent) + return number; + if (abs (exponent) < 20) { + double ex = 1; + int absexp = exponent < 0? -exponent: exponent; + while (absexp--) + ex *= 10; + number = exponent < 0? number / ex: number * ex; + } + else + number *= pow (10, exponent); return number; } double proj_atof(const char *str) { - return proj_strtod(str, (void *) 0); + return proj_strtod(str, (void *) 0); } #ifdef TEST + +/* compile/run: gcc -DTEST -o proj_strtod_test proj_strtod.c && proj_strtod_test */ + +#include <stdio.h> +#include <stdlib.h> #include <string.h> +char *un_underscore (char *s) { + static char u[1024]; + int i, m, n; + for (i = m = 0, n = strlen (s); i < n; i++) { + if (s[i]=='_') { + m++; + continue; + } + u[i - m] = s[i]; + } + u[n-m] = 0; + return u; +} + +int thetest (char *s, int line) { + char *endp, *endq, *u; + double p, q; + int errnop, errnoq, prev_errno; + + prev_errno = errno; + + u = un_underscore (s); + + errno = 0; + p = proj_strtod (s, &endp); + errnop = errno; + errno = 0; + q = strtod (u, &endq); + errnoq = errno; + + errno = prev_errno; + + if (q==p && 0==strcmp (endp, endq) && errnop==errnoq) + return 0; + + errno = line; + printf ("Line: %3.3d - [%s] [%s]\n", line, s, u); + printf ("proj_strtod: %2d %.17g [%s]\n", errnop, p, endp); + printf ("libc_strtod: %2d %.17g [%s]\n", errnoq, q, endq); + return 1; +} + +#define test(s) thetest(s, __LINE__) + int main (int argc, char **argv) { double res; char *endptr; + + errno = 0; + + test (""); + test (" "); + test (" abcde"); + test (" edcba"); + test ("abcde"); + test ("edcba"); + test ("+"); + test ("-"); + test ("+ "); + test ("- "); + test (" + "); + test (" - "); + test ("e 1"); + test ("e1"); + test ("0 66"); + test ("1."); + test ("0."); + test ("1.0"); + test ("0.0"); + test ("1 "); + test ("0 "); + test ("-0 "); + test ("0_ "); + test ("0_"); + test ("1e"); + test ("_1.0"); + test ("_0.0"); + test ("1_.0"); + test ("0_.0"); + test ("1__.0"); + test ("0__.0"); + test ("1.__0"); + test ("0.__0"); + test ("1.0___"); + test ("0.0___"); + test ("1e2"); + test ("__123_456_789_._10_11_12"); + test ("1______"); + test ("1___e__2__"); + test ("-1"); + test ("-1.0"); + test ("-0"); + test ("-1e__-_2__rest"); + test ("0.00002"); + test ("0.00001"); + test ("-0.00002"); + test ("-0.00001"); + test ("-0.00001e-2"); + test ("-0.00001e2"); + test ("1e9999"); + + /* We expect this one to differ */ + test ("0.000000000000000000000000000000000000000000000000000000000000000000000000002"); + + if (errno) + printf ("First discrepancy in line %d\n", errno); + if (argc < 2) return 0; res = proj_strtod (argv[1], &endptr); diff --git a/src/projects.h b/src/projects.h index 9391835d..32b74b08 100644 --- a/src/projects.h +++ b/src/projects.h @@ -84,7 +84,7 @@ extern "C" { #endif /* prototype hypot for systems where absent */ -#if !defined(_WIN32) || !defined(__ANSI__) +#if !(defined(HAVE_C99_MATH) && HAVE_C99_MATH) extern double hypot(double, double); #endif @@ -93,7 +93,6 @@ extern double hypot(double, double); # include <wce_stdio.h> # define rewind wceex_rewind # define getenv wceex_getenv -# define strdup _strdup # define hypot _hypot #endif @@ -174,7 +173,7 @@ typedef struct { double u, v, w; } UVW; /* Forward declarations and typedefs for stuff needed inside the PJ object */ struct PJconsts; -struct PJ_OBS; + union PJ_COORD; struct geod_geodesic; struct pj_opaque; @@ -183,14 +182,15 @@ struct FACTORS; struct PJ_REGION_S; typedef struct PJ_REGION_S PJ_Region; typedef struct ARG_list paralist; /* parameter list */ +#ifndef PROJ_INTERNAL_H enum pj_io_units { - PJ_IO_UNITS_CLASSIC = 0, /* LEFT: Radians RIGHT: Scaled meters */ + PJ_IO_UNITS_CLASSIC = 0, /* Scaled meters (right) */ PJ_IO_UNITS_METERS = 1, /* Meters */ PJ_IO_UNITS_RADIANS = 2 /* Radians */ }; +#endif #ifndef PROJ_H typedef struct PJconsts PJ; /* the PJ object herself */ -typedef struct PJ_OBS PJ_OBS; typedef union PJ_COORD PJ_COORD; #endif @@ -201,10 +201,17 @@ struct PJ_REGION_S { double ur_lat; }; +struct PJ_AREA { + int id; /* Area ID in the EPSG database */ + LP ll; /* Lower left corner of bounding box */ + LP ur; /* Upper right corner of bounding box */ + char descr[64]; /* text representation of area */ +}; struct projCtx_t; typedef struct projCtx_t projCtx_t; + /* base projection data structure */ struct PJconsts { @@ -224,6 +231,7 @@ struct PJconsts { paralist *params; /* Parameter list */ struct geod_geodesic *geod; /* For geodesic computations */ struct pj_opaque *opaque; /* Projection specific parameters, Defined in PJ_*.c */ + int inverted; /* Tell high level API functions to swap inv/fwd */ /************************************************************************************* @@ -246,15 +254,11 @@ struct PJconsts { LP (*inv)(XY, PJ *); XYZ (*fwd3d)(LPZ, PJ *); LPZ (*inv3d)(XYZ, PJ *); - PJ_OBS (*fwdobs)(PJ_OBS, PJ *); - PJ_OBS (*invobs)(PJ_OBS, PJ *); - PJ_COORD (*fwdcoord)(PJ_COORD, PJ *); - PJ_COORD (*invcoord)(PJ_COORD, PJ *); - - void (*spc)(LP, PJ *, struct FACTORS *); + PJ_COORD (*fwd4d)(PJ_COORD, PJ *); + PJ_COORD (*inv4d)(PJ_COORD, PJ *); void *(*destructor)(PJ *, int); - + /************************************************************************************* @@ -320,6 +324,7 @@ struct PJconsts { int geoc; /* Geocentric latitude flag */ int is_latlong; /* proj=latlong ... not really a projection at all */ int is_geocent; /* proj=geocent ... not really a projection at all */ + int need_ellps; /* 0 for operations that are purely cartesian */ enum pj_io_units left; /* Flags for input/output coordinate types */ enum pj_io_units right; @@ -452,14 +457,17 @@ struct FACTORS { double conv; /* convergence */ double s; /* areal scale factor */ double a, b; /* max-min scale error */ - int code; /* info as to analytics, see following */ + int code; /* always 0 */ +}; + +enum deprecated_constants_for_now_dropped_analytical_factors { + IS_ANAL_XL_YL = 01, /* derivatives of lon analytic */ + IS_ANAL_XP_YP = 02, /* derivatives of lat analytic */ + IS_ANAL_HK = 04, /* h and k analytic */ + IS_ANAL_CONV = 010 /* convergence analytic */ }; -#define IS_ANAL_XL_YL 01 /* derivatives of lon analytic */ -#define IS_ANAL_XP_YP 02 /* derivatives of lat analytic */ -#define IS_ANAL_HK 04 /* h and k analytic */ -#define IS_ANAL_CONV 010 /* convergence analytic */ /* datum_type values */ #define PJD_UNKNOWN 0 @@ -525,6 +533,7 @@ struct FACTORS { #define PJD_ERR_MISSING_ARGS -54 #define PJD_ERR_LAT_0_IS_ZERO -55 #define PJD_ERR_ELLIPSOIDAL_UNSUPPORTED -56 +#define PJD_ERR_TOO_MANY_INITS -57 struct projFileAPI_t; @@ -552,7 +561,6 @@ struct PJ_LIST { #ifndef USE_PJ_LIST_H extern struct PJ_LIST pj_list[]; -extern struct PJ_SELFTEST_LIST pj_selftest_list[]; #endif #ifndef PJ_ELLPS__ @@ -575,12 +583,13 @@ extern struct PJ_PRIME_MERIDIANS pj_prime_meridians[]; #ifdef PJ_LIB__ #define PROJ_HEAD(id, name) static const char des_##id [] = name - -#define PROJECTION(name) \ +#define OPERATION(name, NEED_ELLPS) \ + \ pj_projection_specific_setup_##name (PJ *P); \ -C_NAMESPACE_VAR const char * const pj_s_##name = des_##name; \ C_NAMESPACE PJ *pj_##name (PJ *P); \ -int pj_ ## name ## _selftest (void); \ + \ +C_NAMESPACE_VAR const char * const pj_s_##name = des_##name; \ + \ C_NAMESPACE PJ *pj_##name (PJ *P) { \ if (P) \ return pj_projection_specific_setup_##name (P); \ @@ -589,30 +598,22 @@ C_NAMESPACE PJ *pj_##name (PJ *P) { \ return 0; \ P->destructor = pj_default_destructor; \ P->descr = des_##name; \ + P->need_ellps = NEED_ELLPS; \ P->left = PJ_IO_UNITS_RADIANS; \ P->right = PJ_IO_UNITS_CLASSIC; \ return P; \ } \ + \ PJ *pj_projection_specific_setup_##name (PJ *P) -#endif /* def PJ_LIB__ */ - -int pj_generic_selftest ( - char *e_args, - char *s_args, - double tolerance_xy, - double tolerance_lp, - int n_fwd, - int n_inv, - LP *fwd_in, - XY *e_fwd_expect, - XY *s_fwd_expect, - XY *inv_in, - LP *e_inv_expect, - LP *s_inv_expect -); +/* In ISO19000 lingo, an operation is either a conversion or a transformation */ +#define CONVERSION(name, need_ellps) OPERATION (name, need_ellps) +#define TRANSFORMATION(name, need_ellps) OPERATION (name, need_ellps) +/* In PROJ.4 a projection is a conversion taking angular input and giving scaled linear output */ +#define PROJECTION(name) CONVERSION (name, 1) +#endif /* def PJ_LIB__ */ #define MAX_TAB_ID 80 @@ -792,7 +793,6 @@ struct PJ_ELLPS *pj_get_ellps_ref( void ); struct PJ_DATUMS *pj_get_datums_ref( void ); struct PJ_UNITS *pj_get_units_ref( void ); struct PJ_LIST *pj_get_list_ref( void ); -struct PJ_SELFTEST_LIST *pj_get_selftest_list_ref ( void ); struct PJ_PRIME_MERIDIANS *pj_get_prime_meridians_ref( void ); void *pj_default_destructor (PJ *P, int errlev); diff --git a/test/fuzzers/README.TXT b/test/fuzzers/README.TXT index 483c33be..a5f8f3ea 100644 --- a/test/fuzzers/README.TXT +++ b/test/fuzzers/README.TXT @@ -10,7 +10,7 @@ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj4 - Build standard_fuzzer in a standalone mode: - $ g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -DSTANDALONE ../../src/.libs/libproj.a -lpthread + $ g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -DSTANDALONE ../../src/.libs/libproj.a -lpthread -I../../src Run it: $ PROJ_LIB=../../nad ./standard_fuzzer {file_generated_by_oss_fuzz} diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp index a39a2dbf..be90b80a 100644 --- a/test/fuzzers/standard_fuzzer.cpp +++ b/test/fuzzers/standard_fuzzer.cpp @@ -38,7 +38,7 @@ #include "proj_api.h" /* Standalone build: -g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -DSTANDALONE ../../src/.libs/libproj.a -lpthread +g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -DSTANDALONE ../../src/.libs/libproj.a -lpthread -I../../src */ extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv); @@ -47,7 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len); int LLVMFuzzerInitialize(int* /*argc*/, char*** argv) { const char* argv0 = (*argv)[0]; - char* path = strdup(argv0); + char* path = pj_strdup(argv0); char* lastslash = strrchr(path, '/'); if( lastslash ) { diff --git a/test/gie/axisswap.gie b/test/gie/axisswap.gie new file mode 100644 index 00000000..b9281ef7 --- /dev/null +++ b/test/gie/axisswap.gie @@ -0,0 +1,74 @@ +------------------------------------------------------------------------------- + Tests for the axisswap operation +------------------------------------------------------------------------------- + +BEGIN + +OPERATION +proj=axisswap +order=1,2,3,4 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT 1 2 3 4 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=4,3,2,1 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT 4 3 2 1 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=-1,-2,-3,-4 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT -1 -2 -3 -4 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=1,2,-3,4 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT 1 2 -3 4 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=-1,2,3,4 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT -1 2 3 4 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=1,2,3,-4 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT 1 2 3 -4 +ROUNDTRIP 100 + +OPERATION +proj=axisswap +order=-2,1 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT -2 1 3 4 +ROUNDTRIP 100 +$ +OPERATION +proj=axisswap +order=3,-2,1 +TOLERANCE 0.000001 m +ACCEPT 1 2 3 4 +EXPECT 3 -2 1 4 +ROUNDTRIP 100 + + +OPERATION proj=pipeline step proj=latlong step proj=axisswap order=1,2,3,4 angularunits +TOLERANCE 0.00001 m +ACCEPT 12 55 0 0 +EXPECT 12 55 0 0 + +OPERATION +proj=pipeline +step +proj=latlong +step +proj=axisswap +order=-2,-1,3,4 +angularunits +TOLERANCE 0.00001 m +ACCEPT 12 55 0 0 +EXPECT -55 -12 0 0 + +------------------------------------------------------------------------------- +operation +proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222571.608757106 110653.326743030 +ROUNDTRIP 100 + +END diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie new file mode 100644 index 00000000..c6a801f8 --- /dev/null +++ b/test/gie/builtins.gie @@ -0,0 +1,4690 @@ +=============================================================================== + +Test material, mostly converted from selftest entries in PJ_xxx.c + +Most of this material was autogenerated, and does not attempt to exercise +corner cases etc. + +See more_builtins.gie for some test cases with a more human touch. + +=============================================================================== + + +BEGIN + +=============================================================================== +Albers Equal Area + Conic Sph&Ell + lat_1= lat_2= +=============================================================================== +------------------------------------------------------------------------------- +operation +proj=aea +ellps=GRS80 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222571.608757106 110653.326743030 +accept 2 -1 +expect 222706.306508391 -110484.267144400 +accept -2 1 +expect -222571.608757106 110653.326743030 +accept -2 -1 +expect -222706.306508391 -110484.267144400 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796630 -0.000904370 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796630 -0.000904370 + +------------------------------------------------------------------------------- +operation +proj=aea +R=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223334.085170885 111780.431884472 +accept 2 -1 +expect 223470.154991687 -111610.339430990 +accept -2 1 +expect -223334.085170885 111780.431884472 +accept -2 -1 +expect -223470.154991687 -111610.339430990 + +direction inverse +accept 200 100 +expect 0.001790494 0.000895246 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790494 0.000895246 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Azimuthal Equidistant + Azi, Sph&Ell + lat_0 guam +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=aeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222616.522190052 110596.996549550 +accept 2 -1 +expect 222616.522190052 -110596.996549550 +accept -2 1 +expect -222616.522190052 110596.996549550 +accept -2 -1 +expect -222616.522190052 -110596.996549550 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=aeqd +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223379.456047271 111723.757570854 +accept 2 -1 +expect 223379.456047271 -111723.757570854 +accept -2 1 +expect -223379.456047271 111723.757570854 +accept -2 -1 +expect -223379.456047271 -111723.757570854 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Airy + Misc Sph, no inv. + no_cut lat_b= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=airy +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 189109.886908621 94583.752387504 +accept 2 -1 +expect 189109.886908621 -94583.752387504 +accept -2 1 +expect -189109.886908621 94583.752387504 +accept -2 -1 +expect -189109.886908621 -94583.752387504 + + +=============================================================================== +Aitoff + Misc Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=aitoff +R=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223379.458811696 111706.742883853 +accept 2 -1 +expect 223379.458811696 -111706.742883853 +accept -2 1 +expect -223379.458811696 111706.742883853 +accept -2 -1 +expect -223379.458811696 -111706.742883853 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Mod. Stereographic of Alaska + Azi(mod) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=alsk +ellps=clrk66 +------------------------------------------------------------------------------- +tolerance 0.00001 mm +accept -160.000000000 55.000000000 +expect -513253.146950842 -968928.031867943 +accept -160.000000000 70.000000000 +expect -305001.133897637 687494.464958651 +accept -145.000000000 70.000000000 +expect 266454.305088600 683423.477493031 +accept -145.000000000 60.000000000 +expect 389141.322439244 -423913.251230397 + +direction inverse +accept -500000.000000000 -950000.000000000 +expect -159.830804303 55.183195262 +accept -305000.000000000 700000.000000000 +expect -160.042203156 70.111086864 +accept 250000.000000000 700000.000000000 +expect -145.381043551 70.163900908 +accept 400000.000000000 -400000.000000000 +expect -144.758985461 60.202929201 + +------------------------------------------------------------------------------- +operation +proj=alsk +R=6370997 +------------------------------------------------------------------------------- +tolerance 0.0001 mm +accept -160.000000000 55.000000000 +expect -511510.319410844 -967150.991676078 +accept -160.000000000 70.000000000 +expect -303744.771290369 685439.745941123 +accept -145.000000000 70.000000000 +expect 265354.974019663 681386.892874573 +accept -145.000000000 60.000000000 +expect 387711.995394027 -422980.685505463 + +direction inverse +accept -500000.000000000 -950000.000000000 +expect -159.854014458 55.165653849 +accept -305000.000000000 700000.000000000 +expect -160.082332372 70.128307618 +accept 250000.000000000 700000.000000000 +expect -145.347827407 70.181566919 +accept 400000.000000000 -400000.000000000 +expect -144.734239827 60.193564733 + + +=============================================================================== +Apian Globular I + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=apian +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223374.577355253 111701.072127637 +accept 2 -1 +expect 223374.577355253 -111701.072127637 +accept -2 1 +expect -223374.577355253 111701.072127637 +accept -2 -1 +expect -223374.577355253 -111701.072127637 + + +=============================================================================== +August Epicycloidal + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=august +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223404.978180972 111722.340289763 +accept 2 -1 +expect 223404.978180972 -111722.340289763 +accept -2 1 +expect -223404.978180972 111722.340289763 +accept -2 -1 +expect -223404.978180972 -111722.340289763 + + +=============================================================================== +Bacon Globular + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=bacon +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223334.132555965 175450.725922666 +accept 2 -1 +expect 223334.132555965 -175450.725922666 +accept -2 1 +expect -223334.132555965 175450.725922666 +accept -2 -1 +expect -223334.132555965 -175450.725922666 + + +=============================================================================== +Bipolar conic of western hemisphere + Conic Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=bipc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 2452160.217725756 -14548450.759654747 +accept 2 -1 +expect 2447915.213725341 -14763427.212798730 +accept -2 1 +expect 2021695.522934909 -14540413.695283702 +accept -2 -1 +expect 2018090.503004699 -14755620.651414108 + +direction inverse +accept 200 100 +expect -73.038700285 17.248118466 +accept 200 -100 +expect -73.037303739 17.249414978 +accept -200 100 +expect -73.035893173 17.245536403 +accept -200 -100 +expect -73.034496627 17.246832896 + +------------------------------------------------------------------------------- +operation +proj=bipc +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 2460565.740974965 -14598319.989330800 +accept 2 -1 +expect 2456306.185935200 -14814033.339502094 +accept -2 1 +expect 2028625.497819099 -14590255.375482792 +accept -2 -1 +expect 2025008.120589143 -14806200.018759441 + +direction inverse +accept 200 100 +expect -73.038693105 17.248116270 +accept 200 -100 +expect -73.037301330 17.249408353 +accept -200 100 +expect -73.035895582 17.245543028 +accept -200 -100 +expect -73.034503807 17.246835092 + + +=============================================================================== +Boggs Eumorphic + PCyl., no inv., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=boggs +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 211949.700808182 117720.998305411 +accept 2 -1 +expect 211949.700808182 -117720.998305411 +accept -2 1 +expect -211949.700808182 117720.998305411 +accept -2 -1 +expect -211949.700808182 -117720.998305411 + + +=============================================================================== +Bonne (Werner lat_1=90) + Conic Sph&Ell + lat_1= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=bonne +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222605.296097157 55321.139565495 +accept 2 -1 +expect 222605.296099239 -165827.647799052 +accept -2 1 +expect -222605.296097157 55321.139565495 +accept -2 -1 +expect -222605.296099239 -165827.647799052 + +direction inverse +accept 200 100 +expect 0.001796699 0.500904369 +accept 200 -100 +expect 0.001796698 0.499095631 +accept -200 100 +expect -0.001796699 0.500904369 +accept -200 -100 +expect -0.001796698 0.499095631 + +------------------------------------------------------------------------------- +operation +proj=bonne +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.115572528 55884.555246394 +accept 2 -1 +expect 223368.115574632 -167517.599369694 +accept -2 1 +expect -223368.115572528 55884.555246394 +accept -2 -1 +expect -223368.115574632 -167517.599369694 + +direction inverse +accept 200 100 +expect 0.001790562 0.500895246 +accept 200 -100 +expect 0.001790561 0.499104753 +accept -200 100 +expect -0.001790562 0.500895246 +accept -200 -100 +expect -0.001790561 0.499104753 + + +=============================================================================== +Cal Coop Ocean Fish Invest Lines/Stations + Cyl, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=calcofi +ellps=GRS80 +lat_1=0.5 +lat_2=2 +no_defs +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 508.444872150 -1171.764860418 +accept 2 -1 +expect 514.999168152 -1145.821981468 +accept -2 1 +expect 500.685384125 -1131.445377920 +accept -2 -1 +expect 507.369719137 -1106.178201483 + +direction inverse +accept 200 100 +expect -110.363307925 12.032056976 +accept 200 -100 +expect -98.455008863 18.698723643 +accept -200 100 +expect -207.447024504 81.314089279 +accept -200 -100 +expect -62.486322854 87.980755945 + +------------------------------------------------------------------------------- +operation +proj=calcofi +R=6400000 +lat_1=0.5 +lat_2=2 +no_defs +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 507.090507488 -1164.727375198 +accept 2 -1 +expect 513.686136375 -1138.999268217 +accept -2 1 +expect 499.336261476 -1124.435130997 +accept -2 -1 +expect 506.060570393 -1099.375665067 + +direction inverse +accept 200 100 +expect -110.305190410 12.032056976 +accept 200 -100 +expect -98.322360950 18.698723643 +accept -200 100 +expect -207.544906814 81.314089279 +accept -200 -100 +expect -62.576950372 87.980755945 + + +=============================================================================== +Cassini + Cyl, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=cass +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222605.285776991 110642.229253999 +accept 2 -1 +expect 222605.285776991 -110642.229253999 +accept -2 1 +expect -222605.285776991 110642.229253999 +accept -2 -1 +expect -222605.285776991 -110642.229253999 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=cass +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.105203484 111769.145040586 +accept 2 -1 +expect 223368.105203484 -111769.145040586 +accept -2 1 +expect -223368.105203484 111769.145040586 +accept -2 -1 +expect -223368.105203484 -111769.145040586 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Central Cylindrical + Cyl, Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=cc +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111712.415540593 +accept 2 -1 +expect 223402.144255274 -111712.415540593 +accept -2 1 +expect -223402.144255274 111712.415540593 +accept -2 -1 +expect -223402.144255274 -111712.415540593 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Equal Area Cylindrical + Cyl, Sph&Ell + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=cea +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222638.981586547 110568.812396267 +accept 2 -1 +expect 222638.981586547 -110568.812396266 +accept -2 1 +expect -222638.981586547 110568.812396267 +accept -2 -1 +expect -222638.981586547 -110568.812396266 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=cea +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111695.401198614 +accept 2 -1 +expect 223402.144255274 -111695.401198614 +accept -2 1 +expect -223402.144255274 111695.401198614 +accept -2 -1 +expect -223402.144255274 -111695.401198614 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Chamberlin Trimetric + Misc Sph, no inv. + lat_1= lon_1= lat_2= lon_2= lat_3= lon_3= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=chamb +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -27864.779586801 -223364.324593274 +accept 2 -1 +expect -251312.283053493 -223402.145526208 +accept -2 1 +expect -27864.785649105 223364.327328827 +accept -2 -1 +expect -251312.289116443 223402.142197287 + + +=============================================================================== +Collignon + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=collg +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 249872.921577930 99423.174788460 +accept 2 -1 +expect 254272.532301245 -98559.307760743 +accept -2 1 +expect -249872.921577930 99423.174788460 +accept -2 -1 +expect -254272.532301245 -98559.307760743 + +direction inverse +accept 200 100 +expect 0.001586797 0.001010173 +accept 200 -100 +expect 0.001586769 -0.001010182 +accept -200 100 +expect -0.001586797 0.001010173 +accept -200 -100 +expect -0.001586769 -0.001010182 + + +=============================================================================== +Compact Miller + Cyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=comill +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 110611.859089459 +accept 2 -1 +expect 223402.144255274 -110611.859089459 +accept -2 1 +expect -223402.144255274 110611.859089459 +accept -2 -1 +expect -223402.144255274 -110611.859089459 + +direction inverse +accept 200 100 +expect 0.001790493 0.000904107 +accept 200 -100 +expect 0.001790493 -0.000904107 +accept -200 100 +expect -0.001790493 0.000904107 +accept -200 -100 +expect -0.001790493 -0.000904107 + + +=============================================================================== +Craster Parabolic (Putnins P4) + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=crast +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 218280.142056781 114306.045604280 +accept 2 -1 +expect 218280.142056781 -114306.045604280 +accept -2 1 +expect -218280.142056781 114306.045604280 +accept -2 -1 +expect -218280.142056781 -114306.045604280 + +direction inverse +accept 200 100 +expect 0.001832259 0.000874839 +accept 200 -100 +expect 0.001832259 -0.000874839 +accept -200 100 +expect -0.001832259 0.000874839 +accept -200 -100 +expect -0.001832259 -0.000874839 + + +=============================================================================== +Denoyer Semi-Elliptical + PCyl., no inv., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=denoy +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223377.422876954 111701.072127637 +accept 2 -1 +expect 223377.422876954 -111701.072127637 +accept -2 1 +expect -223377.422876954 111701.072127637 +accept -2 -1 +expect -223377.422876954 -111701.072127637 + + +=============================================================================== +Eckert I + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck1 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 204680.888202951 102912.178426065 +accept 2 -1 +expect 204680.888202951 -102912.178426065 +accept -2 1 +expect -204680.888202951 102912.178426065 +accept -2 -1 +expect -204680.888202951 -102912.178426065 + +direction inverse +accept 200 100 +expect 0.001943415 0.000971702 +accept 200 -100 +expect 0.001943415 -0.000971702 +accept -200 100 +expect -0.001943415 0.000971702 +accept -200 -100 +expect -0.001943415 -0.000971702 + + +=============================================================================== +Eckert II + PCyl. Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 204472.870907960 121633.734975242 +accept 2 -1 +expect 204472.870907960 -121633.734975242 +accept -2 1 +expect -204472.870907960 121633.734975242 +accept -2 -1 +expect -204472.870907960 -121633.734975242 + +direction inverse +accept 200 100 +expect 0.001943415 0.000824804 +accept 200 -100 +expect 0.001943415 -0.000824804 +accept -200 100 +expect -0.001943415 0.000824804 +accept -200 -100 +expect -0.001943415 -0.000824804 + + +=============================================================================== +Eckert III + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck3 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 188652.015721538 94328.919337031 +accept 2 -1 +expect 188652.015721538 -94328.919337031 +accept -2 1 +expect -188652.015721538 94328.919337031 +accept -2 -1 +expect -188652.015721538 -94328.919337031 + +direction inverse +accept 200 100 +expect 0.002120241 0.001060120 +accept 200 -100 +expect 0.002120241 -0.001060120 +accept -200 100 +expect -0.002120241 0.001060120 +accept -200 -100 +expect -0.002120241 -0.001060120 + + +=============================================================================== +Eckert IV + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck4 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 188646.389356416 132268.540174065 +accept 2 -1 +expect 188646.389356416 -132268.540174065 +accept -2 1 +expect -188646.389356416 132268.540174065 +accept -2 -1 +expect -188646.389356416 -132268.540174065 + +direction inverse +accept 200 100 +expect 0.002120241 0.000756015 +accept 200 -100 +expect 0.002120241 -0.000756015 +accept -200 100 +expect -0.002120241 0.000756015 +accept -200 -100 +expect -0.002120241 -0.000756015 + + +=============================================================================== +Eckert V + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck5 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 197031.392134061 98523.198847227 +accept 2 -1 +expect 197031.392134061 -98523.198847227 +accept -2 1 +expect -197031.392134061 98523.198847227 +accept -2 -1 +expect -197031.392134061 -98523.198847227 + +direction inverse +accept 200 100 +expect 0.002029979 0.001014989 +accept 200 -100 +expect 0.002029979 -0.001014989 +accept -200 100 +expect -0.002029979 0.001014989 +accept -200 -100 +expect -0.002029979 -0.001014989 + + +=============================================================================== +Eckert VI + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eck6 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 197021.605628992 126640.420733174 +accept 2 -1 +expect 197021.605628992 -126640.420733174 +accept -2 1 +expect -197021.605628992 126640.420733174 +accept -2 -1 +expect -197021.605628992 -126640.420733174 + +direction inverse +accept 200 100 +expect 0.002029979 0.000789630 +accept 200 -100 +expect 0.002029979 -0.000789630 +accept -200 100 +expect -0.002029979 0.000789630 +accept -200 -100 +expect -0.002029979 -0.000789630 + + +=============================================================================== +Equidistant Cylindrical (Plate Caree) + Cyl, Sph + lat_ts=[, lat_0=0] +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eqc +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111701.072127637 +accept 2 -1 +expect 223402.144255274 -111701.072127637 +accept -2 1 +expect -223402.144255274 111701.072127637 +accept -2 -1 +expect -223402.144255274 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Equidistant Conic + Conic, Sph&Ell + lat_1= lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=eqdc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.440269286 110659.134907347 +accept 2 -1 +expect 222756.836702042 -110489.578087221 +accept -2 1 +expect -222588.440269286 110659.134907347 +accept -2 -1 +expect -222756.836702042 -110489.578087221 + +direction inverse +accept 200 100 +expect 0.001796359 0.000904369 +accept 200 -100 +expect 0.001796358 -0.000904370 +accept -200 100 +expect -0.001796359 0.000904369 +accept -200 -100 +expect -0.001796358 -0.000904370 + +------------------------------------------------------------------------------- +operation +proj=eqdc +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223351.088175114 111786.108747174 +accept 2 -1 +expect 223521.200266735 -111615.970741241 +accept -2 1 +expect -223351.088175114 111786.108747174 +accept -2 -1 +expect -223521.200266735 -111615.970741241 + +direction inverse +accept 200 100 +expect 0.001790221 0.000895246 +accept 200 -100 +expect 0.001790220 -0.000895247 +accept -200 100 +expect -0.001790221 0.000895246 +accept -200 -100 +expect -0.001790220 -0.000895247 + + +=============================================================================== +Euler + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=euler +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222597.634659108 111404.240549919 +accept 2 -1 +expect 222767.165631876 -111234.676491018 +accept -2 1 +expect -222597.634659108 111404.240549919 +accept -2 -1 +expect -222767.165631876 -111234.676491018 + +direction inverse +accept 200 100 +expect 0.001796281 0.000898315 +accept 200 -100 +expect 0.001796279 -0.000898316 +accept -200 100 +expect -0.001796281 0.000898315 +accept -200 -100 +expect -0.001796279 -0.000898316 + +------------------------------------------------------------------------------- +operation +proj=euler +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223360.655598694 111786.112389791 +accept 2 -1 +expect 223530.767690316 -111615.967098624 +accept -2 1 +expect -223360.655598694 111786.112389791 +accept -2 -1 +expect -223530.767690316 -111615.967098624 + +direction inverse +accept 200 100 +expect 0.001790144 0.000895246 +accept 200 -100 +expect 0.001790143 -0.000895247 +accept -200 100 +expect -0.001790144 0.000895246 +accept -200 -100 +expect -0.001790143 -0.000895247 + + +=============================================================================== +Extended Transverse Mercator + Cyl, Sph + lat_ts=(0) +lat_0=(0) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=etmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222650.796797586 110642.229411933 +accept 2 -1 +expect 222650.796797586 -110642.229411933 +accept -2 1 +expect -222650.796797586 110642.229411933 +accept -2 -1 +expect -222650.796797586 -110642.229411933 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + + +=============================================================================== +Fahey + Pcyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=fahey +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 182993.344649124 101603.193569884 +accept 2 -1 +expect 182993.344649124 -101603.193569884 +accept -2 1 +expect -182993.344649124 101603.193569884 +accept -2 -1 +expect -182993.344649124 -101603.193569884 + +direction inverse +accept 200 100 +expect 0.002185789 0.000984246 +accept 200 -100 +expect 0.002185789 -0.000984246 +accept -200 100 +expect -0.002185789 0.000984246 +accept -200 -100 +expect -0.002185789 -0.000984246 + + +=============================================================================== +Foucaut + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=fouc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.120675892 111322.316700694 +accept 2 -1 +expect 222588.120675892 -111322.316700694 +accept -2 1 +expect -222588.120675892 111322.316700694 +accept -2 -1 +expect -222588.120675892 -111322.316700694 + +direction inverse +accept 200 100 +expect 0.001796631 0.000898315 +accept 200 -100 +expect 0.001796631 -0.000898315 +accept -200 100 +expect -0.001796631 0.000898315 +accept -200 -100 +expect -0.001796631 -0.000898315 + +------------------------------------------------------------------------------- +operation +proj=fouc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223351.109003414 111703.907721713 +accept 2 -1 +expect 223351.109003414 -111703.907721713 +accept -2 1 +expect -223351.109003414 111703.907721713 +accept -2 -1 +expect -223351.109003414 -111703.907721713 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Foucaut Sinusoidal + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=fouc_s +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111695.401198614 +accept 2 -1 +expect 223402.144255274 -111695.401198614 +accept -2 1 +expect -223402.144255274 111695.401198614 +accept -2 -1 +expect -223402.144255274 -111695.401198614 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Gall (Gall Stereographic) + Cyl, Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gall +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 157969.171134520 95345.249178386 +accept 2 -1 +expect 157969.171134520 -95345.249178386 +accept -2 1 +expect -157969.171134520 95345.249178386 +accept -2 -1 +expect -157969.171134520 -95345.249178386 + +direction inverse +accept 200 100 +expect 0.002532140 0.001048847 +accept 200 -100 +expect 0.002532140 -0.001048847 +accept -200 100 +expect -0.002532140 0.001048847 +accept -200 -100 +expect -0.002532140 -0.001048847 + + +=============================================================================== +Geocentric + +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=geocent +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222638.981586547 111319.490793274 +accept 2 -1 +expect 222638.981586547 -111319.490793274 +accept -2 1 +expect -222638.981586547 111319.490793274 +accept -2 -1 +expect -222638.981586547 -111319.490793274 + +direction inverse +accept 200 100 +expect 0.001796631 0.000898315 +accept 200 -100 +expect 0.001796631 -0.000898315 +accept -200 100 +expect -0.001796631 0.000898315 +accept -200 -100 +expect -0.001796631 -0.000898315 + +------------------------------------------------------------------------------- +operation +proj=geocent +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm + + +=============================================================================== +Geostationary Satellite View + Azi, Sph&Ell + h= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=geos +ellps=GRS80 +lat_1=0.5 +lat_2=2 +h=35785831 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222527.070365800 110551.303413329 +accept 2 -1 +expect 222527.070365800 -110551.303413329 +accept -2 1 +expect -222527.070365800 110551.303413329 +accept -2 -1 +expect -222527.070365800 -110551.303413329 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=geos +R=6400000 +lat_1=0.5 +lat_2=2 +h=35785831 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223289.457635795 111677.657456537 +accept 2 -1 +expect 223289.457635795 -111677.657456537 +accept -2 1 +expect -223289.457635795 111677.657456537 +accept -2 -1 +expect -223289.457635795 -111677.657456537 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Ginsburg VIII (TsNIIGAiK) + PCyl, Sph., no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gins8 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 194350.250939590 111703.907635335 +accept 2 -1 +expect 194350.250939590 -111703.907635335 +accept -2 1 +expect -194350.250939590 111703.907635335 +accept -2 -1 +expect -194350.250939590 -111703.907635335 + + +=============================================================================== +General Sinusoidal Series + PCyl, Sph. + m= n= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gn_sinu +a=6400000 +lat_1=0.5 +lat_2=2 +m=1 +n=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223385.132504696 111698.236447187 +accept 2 -1 +expect 223385.132504696 -111698.236447187 +accept -2 1 +expect -223385.132504696 111698.236447187 +accept -2 -1 +expect -223385.132504696 -111698.236447187 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Gnomonic + Azi, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gnom +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223492.924747185 111780.509206593 +accept 2 -1 +expect 223492.924747185 -111780.509206593 +accept -2 1 +expect -223492.924747185 111780.509206593 +accept -2 -1 +expect -223492.924747185 -111780.509206593 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Goode Homolosine + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=goode +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.119026632 111701.072127637 +accept 2 -1 +expect 223368.119026632 -111701.072127637 +accept -2 1 +expect -223368.119026632 111701.072127637 +accept -2 -1 +expect -223368.119026632 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Mod. Stereographic of 48 U.S. + Azi(mod) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gs48 +R=6370997 +------------------------------------------------------------------------------- +tolerance 0.0001 mm +accept -119.000000000 40.000000000 +expect -1923908.446529346 355874.658944479 +accept -70.000000000 64.000000000 +expect 1354020.375109298 3040846.007866525 +accept -80.000000000 25.000000000 +expect 1625139.160484320 -1413614.894029108 +accept -95.000000000 35.000000000 +expect 90241.658071458 -439595.048485902 + +direction inverse +accept -1923000.000000000 355000.000000000 +expect -118.987112613 39.994449789 +accept 1354000.000000000 3040000.000000000 +expect -70.005208999 63.993387836 +accept 1625000.000000000 -1413000.000000000 +expect -80.000346610 25.005602547 +accept 90000.000000000 -439000.000000000 +expect -95.002606473 35.005424705 + + +=============================================================================== +Mod. Stereographic of 50 U.S. + Azi(mod) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gs50 +ellps=clrk66 +------------------------------------------------------------------------------- +tolerance 0.0001 mm +accept -160.000000000 65.000000000 +expect -1874628.537740233 2660907.942291015 +accept -130.000000000 45.000000000 +expect -771831.518853336 48465.166491305 +accept -65.000000000 45.000000000 +expect 4030931.833981509 1323687.864777399 +accept -80.000000000 36.000000000 +expect 3450764.261536101 -175619.041820732 + +direction inverse +accept -1800000.000000000 2600000.000000000 +expect -157.989285000 64.851559610 +accept -800000.000000000 500000.000000000 +expect -131.171390467 49.084969746 +accept 4000000.000000000 1300000.000000000 +expect -65.491568685 44.992837924 +accept 3900000.000000000 -170000.000000000 +expect -75.550660091 34.191114076 + +------------------------------------------------------------------------------- +operation +proj=gs50 +R=6370997 +------------------------------------------------------------------------------- +tolerance 0.0001 mm +accept -160.000000000 65.000000000 +expect -1867268.253460009 2656506.230401823 +accept -130.000000000 45.000000000 +expect -769572.189672994 48324.312440864 +accept -65.000000000 45.000000000 +expect 4019393.068680791 1320191.309350289 +accept -80.000000000 36.000000000 +expect 3442685.615172346 -178760.423489429 + +direction inverse +accept -1800000.000000000 2600000.000000000 +expect -158.163295045 64.854288365 +accept -800000.000000000 500000.000000000 +expect -131.206816960 49.082915351 +accept 4000000.000000000 1300000.000000000 +expect -65.348945221 44.957292682 +accept 3900000.000000000 -170000.000000000 +expect -75.446820242 34.185406226 + + +=============================================================================== +Hammer & Eckert-Greifendorff + Misc Sph, + W= M= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=hammer +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223373.788703241 111703.907397767 +accept 2 -1 +expect 223373.788703241 -111703.907397767 +accept -2 1 +expect -223373.788703241 111703.907397767 +accept -2 -1 +expect -223373.788703241 -111703.907397767 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Hatano Asymmetrical Equal Area + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=hatano +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 189878.878946528 131409.802440626 +accept 2 -1 +expect 189881.081952445 -131409.142276074 +accept -2 1 +expect -189878.878946528 131409.802440626 +accept -2 -1 +expect -189881.081952445 -131409.142276074 + +direction inverse +accept 200 100 +expect 0.002106462 0.000760957 +accept 200 -100 +expect 0.002106462 -0.000760958 +accept -200 100 +expect -0.002106462 0.000760957 +accept -200 -100 +expect -0.002106462 -0.000760958 + + +=============================================================================== +HEALPix + Sph., Ellps. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=healpix +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222390.103949239 130406.588664482 +accept 2 -1 +expect 222390.103949239 -130406.588664481 +accept -2 1 +expect -222390.103949239 130406.588664482 +accept -2 -1 +expect -222390.103949239 -130406.588664481 + +direction inverse +accept 200 100 +expect 0.001798641 0.000766795 +accept 200 -100 +expect 0.001798641 -0.000766795 +accept -200 100 +expect -0.001798641 0.000766795 +accept -200 -100 +expect -0.001798641 -0.000766795 + +------------------------------------------------------------------------------- +operation +proj=healpix +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 131588.044441999 +accept 2 -1 +expect 223402.144255274 -131588.044441999 +accept -2 1 +expect -223402.144255274 131588.044441999 +accept -2 -1 +expect -223402.144255274 -131588.044441999 + +direction inverse +accept 200 100 +expect 0.001790493 0.000759909 +accept 200 -100 +expect 0.001790493 -0.000759909 +accept -200 100 +expect -0.001790493 0.000759909 +accept -200 -100 +expect -0.001790493 -0.000759909 + + +=============================================================================== +rHEALPix + Sph., Ellps. + north_square= south_square= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=rhealpix +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222390.103949239 130406.588664482 +accept 2 -1 +expect 222390.103949239 -130406.588664481 +accept -2 1 +expect -222390.103949239 130406.588664482 +accept -2 -1 +expect -222390.103949239 -130406.588664481 + +direction inverse +accept 200 100 +expect 0.001798641 0.000766795 +accept 200 -100 +expect 0.001798641 -0.000766795 +accept -200 100 +expect -0.001798641 0.000766795 +accept -200 -100 +expect -0.001798641 -0.000766795 + +------------------------------------------------------------------------------- +operation +proj=rhealpix +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 131588.044441999 +accept 2 -1 +expect 223402.144255274 -131588.044441999 +accept -2 1 +expect -223402.144255274 131588.044441999 +accept -2 -1 +expect -223402.144255274 -131588.044441999 + +direction inverse +accept 200 100 +expect 0.001790493 0.000759909 +accept 200 -100 +expect 0.001790493 -0.000759909 +accept -200 100 +expect -0.001790493 0.000759909 +accept -200 -100 +expect -0.001790493 -0.000759909 + + +=============================================================================== +Interrupted Goode Homolosine + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=igh +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223878.497456271 111701.072127637 +accept 2 -1 +expect 223708.371313058 -111701.072127637 +accept -2 1 +expect -222857.740596992 111701.072127637 +accept -2 -1 +expect -223027.866740205 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790489 0.000895247 +accept 200 -100 +expect 0.001790491 -0.000895247 +accept -200 100 +expect -0.001790497 0.000895247 +accept -200 -100 +expect -0.001790496 -0.000895247 + + +=============================================================================== +International Map of the World Polyconic + Mod. Polyconic, Ell + lat_1= and lat_2= [lon_1=] +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=imw_p +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.441139376 55321.128653810 +accept 2 -1 +expect 222756.906377687 -165827.584288324 +accept -2 1 +expect -222588.441139376 55321.128653810 +accept -2 -1 +expect -222756.906377687 -165827.584288324 + +direction inverse +accept 200 100 +expect 0.001796699 0.500904924 +accept 200 -100 +expect 0.001796698 0.499095076 +accept -200 100 +expect -0.001796699 0.500904924 +accept -200 -100 +expect -0.001796698 0.499095076 + + +=============================================================================== +Icosahedral Snyder Equal Area + Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=isea +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -1097074.948022474 3442909.309037183 +accept 2 -1 +expect -1097074.948264795 3233611.728585708 +accept -2 1 +expect -1575486.353641554 3442168.342028188 +accept -2 -1 +expect -1575486.353880283 3234352.695594706 + + +=============================================================================== +Kavraisky V + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=kav5 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 200360.905308829 123685.082476998 +accept 2 -1 +expect 200360.905308829 -123685.082476998 +accept -2 1 +expect -200360.905308829 123685.082476998 +accept -2 -1 +expect -200360.905308829 -123685.082476998 + +direction inverse +accept 200 100 +expect 0.001996259 0.000808483 +accept 200 -100 +expect 0.001996259 -0.000808483 +accept -200 100 +expect -0.001996259 0.000808483 +accept -200 -100 +expect -0.001996259 -0.000808483 + +------------------------------------------------------------------------------- +operation +proj=kav5 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 201047.703110878 124109.050629171 +accept 2 -1 +expect 201047.703110878 -124109.050629171 +accept -2 1 +expect -201047.703110878 124109.050629171 +accept -2 -1 +expect -201047.703110878 -124109.050629171 + +direction inverse +accept 200 100 +expect 0.001989440 0.000805721 +accept 200 -100 +expect 0.001989440 -0.000805721 +accept -200 100 +expect -0.001989440 0.000805721 +accept -200 -100 +expect -0.001989440 -0.000805721 + + +=============================================================================== +Kavraisky VII + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=kav7 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 193462.974943729 111701.072127637 +accept 2 -1 +expect 193462.974943729 -111701.072127637 +accept -2 1 +expect -193462.974943729 111701.072127637 +accept -2 -1 +expect -193462.974943729 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.002067483 0.000895247 +accept 200 -100 +expect 0.002067483 -0.000895247 +accept -200 100 +expect -0.002067483 0.000895247 +accept -200 -100 +expect -0.002067483 -0.000895247 + + +=============================================================================== +Krovak + PCyl., Ellps. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=krovak +ellps=GRS80 +no_defs +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -3196535.232563641 -6617878.867551444 +accept 2 -1 +expect -3260035.440552109 -6898873.614878031 +accept -2 1 +expect -3756305.328869175 -6478142.561571511 +accept -2 -1 +expect -3831703.658501982 -6759107.170155395 + +direction inverse +accept 200 100 +expect 24.836218919 59.758403933 +accept 200 -100 +expect 24.836315485 59.756888426 +accept -200 100 +expect 24.830447748 59.758403933 +accept -200 -100 +expect 24.830351182 59.756888426 + + +=============================================================================== +Laborde + Cyl, Sph + Special for Madagascar +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=labrd +ellps=GRS80 +lon_0=0.5 +lat_0=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 166973.166090228 -110536.912730266 +accept 2 -1 +expect 166973.168287157 -331761.993650884 +accept -2 1 +expect -278345.500519976 -110469.032642032 +accept -2 -1 +expect -278345.504185270 -331829.870790275 + +direction inverse +accept 200 100 +expect 0.501797719 2.000904357 +accept 200 -100 +expect 0.501797717 1.999095641 +accept -200 100 +expect 0.498202281 2.000904357 +accept -200 -100 +expect 0.498202283 1.999095641 + + +=============================================================================== +Lambert Azimuthal Equal Area + Azi, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=laea +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222602.471450095 110589.827224410 +accept 2 -1 +expect 222602.471450095 -110589.827224409 +accept -2 1 +expect -222602.471450095 110589.827224410 +accept -2 -1 +expect -222602.471450095 -110589.827224409 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=laea +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223365.281370125 111716.668072916 +accept 2 -1 +expect 223365.281370125 -111716.668072916 +accept -2 1 +expect -223365.281370125 111716.668072916 +accept -2 -1 +expect -223365.281370125 -111716.668072916 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Lagrange + Misc Sph, no inv. + W= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lagrng +a=6400000 +W=2 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 111703.375917226 27929.831908033 +accept 2 -1 +expect 111699.122088816 -83784.178013358 +accept -2 1 +expect -111703.375917226 27929.831908033 +accept -2 -1 +expect -111699.122088816 -83784.178013358 + + +=============================================================================== +Larrivee + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=larr +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223393.637624201 111707.215961256 +accept 2 -1 +expect 223393.637624201 -111707.215961256 +accept -2 1 +expect -223393.637624201 111707.215961256 +accept -2 -1 +expect -223393.637624201 -111707.215961256 + + +=============================================================================== +Laskowski + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lask +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 217928.275907355 112144.329220142 +accept 2 -1 +expect 217928.275907355 -112144.329220142 +accept -2 1 +expect -217928.275907355 112144.329220142 +accept -2 -1 +expect -217928.275907355 -112144.329220142 + + +=============================================================================== +Lambert Conformal Conic + Conic, Sph&Ell + lat_1= and lat_2= or lat_0 +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lcc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.439735968 110660.533870800 +accept 2 -1 +expect 222756.879700279 -110532.797660827 +accept -2 1 +expect -222588.439735968 110660.533870800 +accept -2 -1 +expect -222756.879700279 -110532.797660827 + +direction inverse +accept 200 100 +expect 0.001796359 0.000904232 +accept 200 -100 +expect 0.001796358 -0.000904233 +accept -200 100 +expect -0.001796359 0.000904232 +accept -200 -100 +expect -0.001796358 -0.000904233 + + +=============================================================================== +Lambert Conformal Conic Alternative + Conic, Sph&Ell + lat_0= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lcca +ellps=GRS80 +lat_0=1 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222605.285770237 67.806007272 +accept 2 -1 +expect 222740.037637937 -221125.539829602 +accept -2 1 +expect -222605.285770237 67.806007272 +accept -2 -1 +expect -222740.037637937 -221125.539829602 + +direction inverse +accept 200 100 +expect 0.001796903 1.000904366 +accept 200 -100 +expect 0.001796902 0.999095633 +accept -200 100 +expect -0.001796903 1.000904366 +accept -200 -100 +expect -0.001796902 0.999095633 + + +=============================================================================== +Lambert Equal Area Conic + Conic, Sph&Ell + lat_1= south +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=leac +ellps=GRS80 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 220685.140542979 112983.500889396 +accept 2 -1 +expect 224553.312279826 -108128.636744873 +accept -2 1 +expect -220685.140542979 112983.500889396 +accept -2 -1 +expect -224553.312279826 -108128.636744873 + +direction inverse +accept 200 100 +expect 0.001796645 0.000904352 +accept 200 -100 +expect 0.001796616 -0.000904387 +accept -200 100 +expect -0.001796645 0.000904352 +accept -200 -100 +expect -0.001796616 -0.000904387 + +------------------------------------------------------------------------------- +operation +proj=leac +R=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 221432.868592852 114119.454526532 +accept 2 -1 +expect 225331.724127111 -109245.829435056 +accept -2 1 +expect -221432.868592852 114119.454526532 +accept -2 -1 +expect -225331.724127111 -109245.829435056 + +direction inverse +accept 200 100 +expect 0.001790507 0.000895229 +accept 200 -100 +expect 0.001790479 -0.000895264 +accept -200 100 +expect -0.001790507 0.000895229 +accept -200 -100 +expect -0.001790479 -0.000895264 + + +=============================================================================== +Lee Oblated Stereographic + Azi(mod) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lee_os +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.0010 mm +accept 2 1 +expect -25564478.952605054 154490848.828625500 +accept 2 -1 +expect 30115393.938574642 125193997.439701970 +accept -2 1 +expect -31039340.592166007 57678685.044891544 +accept -2 -1 +expect -3088419.939423571 58150091.099111013 + +direction inverse +accept 200 100 +expect -164.997479458 -9.998758861 +accept 200 -100 +expect -164.997479439 -10.001241120 +accept -200 100 +expect -165.002520542 -9.998758861 +accept -200 -100 +expect -165.002520561 -10.001241120 + + +=============================================================================== +Loximuthal + PCyl Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=loxim +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223382.295791339 55850.536063819 +accept 2 -1 +expect 223393.637462243 -167551.608191456 +accept -2 1 +expect -223382.295791339 55850.536063819 +accept -2 -1 +expect -223393.637462243 -167551.608191456 + +direction inverse +accept 200 100 +expect 0.001790561 0.500895247 +accept 200 -100 +expect 0.001790561 0.499104753 +accept -200 100 +expect -0.001790561 0.500895247 +accept -200 -100 +expect -0.001790561 0.499104753 + + +=============================================================================== +Space oblique for LANDSAT + Cyl, Sph&Ell + lsat= path= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=lsat +ellps=GRS80 +lat_1=0.5 +lat_2=2 +lsat=1 +path=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 18241950.014558550 9998256.839822935 +accept 2 -1 +expect 18746856.253319457 10215761.669925211 +accept -2 1 +expect 18565503.683633164 9085039.146727053 +accept -2 -1 +expect 19019696.902028911 9247763.039432822 + +direction inverse +accept 200 100 +expect 126.000423835 0.001723782 +accept 200 -100 +expect 126.002213738 0.001880155 +accept -200 100 +expect 126.000734469 -0.001880155 +accept -200 -100 +expect 126.002524373 -0.001723782 + + +=============================================================================== +McBryde-Thomas Flat-Polar Sine (No. 1) + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mbt_s +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 204131.517850273 121400.330225508 +accept 2 -1 +expect 204131.517850273 -121400.330225508 +accept -2 1 +expect -204131.517850273 121400.330225508 +accept -2 -1 +expect -204131.517850273 -121400.330225508 + +direction inverse +accept 200 100 +expect 0.001959383 0.000823699 +accept 200 -100 +expect 0.001959383 -0.000823699 +accept -200 100 +expect -0.001959383 0.000823699 +accept -200 -100 +expect -0.001959383 -0.000823699 + +------------------------------------------------------------------------------- +operation +proj=mbt_s +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 204831.240570992 121816.466696035 +accept 2 -1 +expect 204831.240570992 -121816.466696035 +accept -2 1 +expect -204831.240570992 121816.466696035 +accept -2 -1 +expect -204831.240570992 -121816.466696035 + +direction inverse +accept 200 100 +expect 0.001952689 0.000820885 +accept 200 -100 +expect 0.001952689 -0.000820885 +accept -200 100 +expect -0.001952689 0.000820885 +accept -200 -100 +expect -0.001952689 -0.000820885 + + +=============================================================================== +McBryde-Thomas Flat-Pole Sine (No. 2) + Cyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mbt_fps +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 198798.176129850 125512.017254531 +accept 2 -1 +expect 198798.176129850 -125512.017254531 +accept -2 1 +expect -198798.176129850 125512.017254531 +accept -2 -1 +expect -198798.176129850 -125512.017254531 + +direction inverse +accept 200 100 +expect 0.002011971 0.000796712 +accept 200 -100 +expect 0.002011971 -0.000796712 +accept -200 100 +expect -0.002011971 0.000796712 +accept -200 -100 +expect -0.002011971 -0.000796712 + + +=============================================================================== +McBride-Thomas Flat-Polar Parabolic + Cyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mbtfpp +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 206804.786929820 120649.762565793 +accept 2 -1 +expect 206804.786929820 -120649.762565793 +accept -2 1 +expect -206804.786929820 120649.762565793 +accept -2 -1 +expect -206804.786929820 -120649.762565793 + +direction inverse +accept 200 100 +expect 0.001933954 0.000828837 +accept 200 -100 +expect 0.001933954 -0.000828837 +accept -200 100 +expect -0.001933954 0.000828837 +accept -200 -100 +expect -0.001933954 -0.000828837 + + +=============================================================================== +McBryde-Thomas Flat-Polar Quartic + Cyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mbtfpq +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 209391.854738393 119161.040199055 +accept 2 -1 +expect 209391.854738393 -119161.040199055 +accept -2 1 +expect -209391.854738393 119161.040199055 +accept -2 -1 +expect -209391.854738393 -119161.040199055 + +direction inverse +accept 200 100 +expect 0.001910106 0.000839185 +accept 200 -100 +expect 0.001910106 -0.000839185 +accept -200 100 +expect -0.001910106 0.000839185 +accept -200 -100 +expect -0.001910106 -0.000839185 + + +=============================================================================== +McBryde-Thomas Flat-Polar Sinusoidal + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mbtfps +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 204740.117478572 121864.729719340 +accept 2 -1 +expect 204740.117478572 -121864.729719340 +accept -2 1 +expect -204740.117478572 121864.729719340 +accept -2 -1 +expect -204740.117478572 -121864.729719340 + +direction inverse +accept 200 100 +expect 0.001953415 0.000820580 +accept 200 -100 +expect 0.001953415 -0.000820580 +accept -200 100 +expect -0.001953415 0.000820580 +accept -200 -100 +expect -0.001953415 -0.000820580 + + +=============================================================================== +Mercator + Cyl, Sph&Ell + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=merc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222638.981586547 110579.965218250 +accept 2 -1 +expect 222638.981586547 -110579.965218249 +accept -2 1 +expect -222638.981586547 110579.965218250 +accept -2 -1 +expect -222638.981586547 -110579.965218249 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=merc +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111706.743574944 +accept 2 -1 +expect 223402.144255274 -111706.743574944 +accept -2 1 +expect -223402.144255274 111706.743574944 +accept -2 -1 +expect -223402.144255274 -111706.743574944 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Miller Oblated Stereographic + Azi(mod) +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mil_os +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -1908527.949594205 -1726237.473061448 +accept 2 -1 +expect -1916673.022918485 -1943133.888125523 +accept -2 1 +expect -2344429.412089623 -1706258.051218912 +accept -2 -1 +expect -2354637.835532999 -1926468.605135417 + +direction inverse +accept 200 100 +expect 20.002036394 18.000968347 +accept 200 -100 +expect 20.002036372 17.999031632 +accept -200 100 +expect 19.997963606 18.000968347 +accept -200 -100 +expect 19.997963628 17.999031632 + + +=============================================================================== +Miller Cylindrical + Cyl, Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=mill +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111704.701754394 +accept 2 -1 +expect 223402.144255274 -111704.701754396 +accept -2 1 +expect -223402.144255274 111704.701754394 +accept -2 -1 +expect -223402.144255274 -111704.701754396 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Space oblique for MISR + Cyl, Sph&Ell + path= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=misrsom +ellps=GRS80 +lat_1=0.5 +lat_2=2 +path=1 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 18556630.368369825 9533394.675311271 +accept 2 -1 +expect 19041866.006729737 9707182.175323525 +accept -2 1 +expect 18816810.130184799 8647669.649802955 +accept -2 -1 +expect 19252610.784536730 8778164.085801404 + +direction inverse +accept 200 100 +expect 127.759503988 0.001735150 +accept 200 -100 +expect 127.761295471 0.001871966 +accept -200 100 +expect 127.759775774 -0.001871966 +accept -200 -100 +expect 127.761567257 -0.001735150 + +------------------------------------------------------------------------------- +operation +proj=misrsom +R=6400000 +lat_1=0.5 +lat_2=2 +path=1 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 18641249.279170386 9563342.532334166 +accept 2 -1 +expect 19130982.461581279 9739539.593504636 +accept -2 1 +expect 18903483.515011538 8675064.500617975 +accept -2 -1 +expect 19343388.399800610 8807471.904068489 + +direction inverse +accept 200 100 +expect 127.759505148 0.001716231 +accept 200 -100 +expect 127.761290324 0.001854121 +accept -200 100 +expect 127.759780921 -0.001854121 +accept -200 -100 +expect 127.761566096 -0.001716231 + + +=============================================================================== +Mollweide + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=moll +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 201113.698641813 124066.283433860 +accept 2 -1 +expect 201113.698641813 -124066.283433860 +accept -2 1 +expect -201113.698641813 124066.283433860 +accept -2 -1 +expect -201113.698641813 -124066.283433860 + +direction inverse +accept 200 100 +expect 0.001988738 0.000806005 +accept 200 -100 +expect 0.001988738 -0.000806005 +accept -200 100 +expect -0.001988738 0.000806005 +accept -200 -100 +expect -0.001988738 -0.000806005 + + +=============================================================================== +Murdoch I + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=murd1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222600.813473554 111404.244180546 +accept 2 -1 +expect 222770.349287864 -111234.672856675 +accept -2 1 +expect -222600.813473554 111404.244180546 +accept -2 -1 +expect -222770.349287864 -111234.672856675 + +direction inverse +accept 200 100 +expect 0.001796255 0.000898315 +accept 200 -100 +expect 0.001796254 -0.000898316 +accept -200 100 +expect -0.001796255 0.000898315 +accept -200 -100 +expect -0.001796254 -0.000898316 + +------------------------------------------------------------------------------- +operation +proj=murd1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223363.845309492 111786.116032863 +accept 2 -1 +expect 223533.962259251 -111615.963451823 +accept -2 1 +expect -223363.845309492 111786.116032863 +accept -2 -1 +expect -223533.962259251 -111615.963451823 + +direction inverse +accept 200 100 +expect 0.001790119 0.000895246 +accept 200 -100 +expect 0.001790118 -0.000895247 +accept -200 100 +expect -0.001790119 0.000895246 +accept -200 -100 +expect -0.001790118 -0.000895247 + + +=============================================================================== +Murdoch II + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=murd2 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.099751230 111426.140027412 +accept 2 -1 +expect 222757.726267018 -111341.431317505 +accept -2 1 +expect -222588.099751230 111426.140027412 +accept -2 -1 +expect -222757.726267018 -111341.431317505 + +direction inverse +accept 200 100 +expect 0.001796357 0.000897887 +accept 200 -100 +expect 0.001796356 -0.000897888 +accept -200 100 +expect -0.001796357 0.000897887 +accept -200 -100 +expect -0.001796356 -0.000897888 + +------------------------------------------------------------------------------- +operation +proj=murd2 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223351.088007027 111808.086934388 +accept 2 -1 +expect 223521.295969170 -111723.087859673 +accept -2 1 +expect -223351.088007027 111808.086934388 +accept -2 -1 +expect -223521.295969170 -111723.087859673 + +direction inverse +accept 200 100 +expect 0.001790221 0.000894820 +accept 200 -100 +expect 0.001790220 -0.000894821 +accept -200 100 +expect -0.001790221 0.000894820 +accept -200 -100 +expect -0.001790220 -0.000894821 + + +=============================================================================== +Murdoch III + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=murd3 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222600.814077577 111404.246601372 +accept 2 -1 +expect 222770.354733899 -111234.670432178 +accept -2 1 +expect -222600.814077577 111404.246601372 +accept -2 -1 +expect -222770.354733899 -111234.670432178 + +direction inverse +accept 200 100 +expect 0.001796255 0.000898315 +accept 200 -100 +expect 0.001796254 -0.000898316 +accept -200 100 +expect -0.001796255 0.000898315 +accept -200 -100 +expect -0.001796254 -0.000898316 + +------------------------------------------------------------------------------- +operation +proj=murd3 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223363.845915585 111786.118461987 +accept 2 -1 +expect 223533.967723953 -111615.961019015 +accept -2 1 +expect -223363.845915585 111786.118461987 +accept -2 -1 +expect -223533.967723953 -111615.961019015 + +direction inverse +accept 200 100 +expect 0.001790119 0.000895246 +accept 200 -100 +expect 0.001790118 -0.000895247 +accept -200 100 +expect -0.001790119 0.000895246 +accept -200 -100 +expect -0.001790118 -0.000895247 + + +=============================================================================== +Natural Earth + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=natearth +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 194507.265257889 112508.737358295 +accept 2 -1 +expect 194507.265257889 -112508.737358295 +accept -2 1 +expect -194507.265257889 112508.737358295 +accept -2 -1 +expect -194507.265257889 -112508.737358295 + +direction inverse +accept 200 100 +expect 0.002056383 0.000888824 +accept 200 -100 +expect 0.002056383 -0.000888824 +accept -200 100 +expect -0.002056383 0.000888824 +accept -200 -100 +expect -0.002056383 -0.000888824 + + +=============================================================================== +Natural Earth 2 + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=natearth2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 189255.172934731 113022.495810907 +accept 2 -1 +expect 189255.172934731 -113022.495810907 +accept -2 1 +expect -189255.172934731 113022.495810907 +accept -2 -1 +expect -189255.172934731 -113022.495810907 + +direction inverse +accept 200 100 +expect 0.002113449 0.000884780 +accept 200 -100 +expect 0.002113449 -0.000884780 +accept -200 100 +expect -0.002113449 0.000884780 +accept -200 -100 +expect -0.002113449 -0.000884780 + + +=============================================================================== +Nell + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=nell +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223385.132504696 111698.236447187 +accept 2 -1 +expect 223385.132504696 -111698.236447187 +accept -2 1 +expect -223385.132504696 111698.236447187 +accept -2 -1 +expect -223385.132504696 -111698.236447187 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Nell-Hammer + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=nell_h +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223385.131640953 111698.236533562 +accept 2 -1 +expect 223385.131640953 -111698.236533562 +accept -2 1 +expect -223385.131640953 111698.236533562 +accept -2 -1 +expect -223385.131640953 -111698.236533562 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Nicolosi Globular + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=nicol +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223374.561814140 111732.553988545 +accept 2 -1 +expect 223374.561814140 -111732.553988545 +accept -2 1 +expect -223374.561814140 111732.553988545 +accept -2 -1 +expect -223374.561814140 -111732.553988545 + + +=============================================================================== +Near-sided perspective + Azi, Sph + h= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=nsper +a=6400000 +h=1000000 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222239.816114100 111153.763991925 +accept 2 -1 +expect 222239.816114100 -111153.763991925 +accept -2 1 +expect -222239.816114100 111153.763991925 +accept -2 -1 +expect -222239.816114100 -111153.763991925 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +New Zealand Map Grid + fixed Earth +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=nzmg +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.010 mm +accept 2 1 +expect 3352675144.747425100 -7043205391.100243600 +accept 2 -1 +expect 3691989502.779306400 -6729069415.332104700 +accept -2 1 +expect 4099000768.453238500 -7863208779.667248700 +accept -2 -1 +expect 4466166927.369976000 -7502531736.628604900 + +direction inverse +accept 200000.000000000 100000.000000000 +expect 175.482086827 -69.422692183 +accept 200000.000000000 -100000.000000000 +expect 175.756819473 -69.533571088 +accept -200000.000000000 100000.000000000 +expect 134.605119233 -61.459995711 +accept -200000.000000000 -100000.000000000 +expect 134.333684316 -61.621553676 + + +=============================================================================== +General Oblique Transformation + Misc Sph + o_proj= plus parameters for projection + o_lat_p= o_lon_p= (new pole) or + o_alpha= o_lon_c= o_lat_c= or + o_lon_1= o_lat_1= o_lon_2= o_lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=ob_tran +R=6400000 +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -2.685687214 1.237430235 +accept 2 -1 +expect -2.695406975 1.202683395 +accept -2 1 +expect -2.899366393 1.237430235 +accept -2 -1 +expect -2.889646631 1.202683395 + +direction inverse +accept 200 100 +expect 121.551874841 -2.536100157 +accept 200 -100 +expect 63.261184340 17.585319579 +accept -200 100 +expect -141.100733224 26.091712305 +accept -200 -100 +expect -65.862385599 51.830295078 + + +=============================================================================== +Oblique Cylindrical Equal Area + Cyl, Sphlonc= alpha= or + lat_1= lat_2= lon_1= lon_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=ocea +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 19994423.837934088 223322.760576728 +accept 2 -1 +expect 20217962.128015257 223322.760576729 +accept -2 1 +expect 19994423.837934092 -223322.760576727 +accept -2 -1 +expect 20217962.128015265 -223322.760576725 + +direction inverse +accept 200 100 +expect 179.999104753 0.001790493 +accept 200 -100 +expect -179.999104753 0.001790493 +accept -200 100 +expect 179.999104753 -0.001790493 +accept -200 -100 +expect -179.999104753 -0.001790493 + + +=============================================================================== +Oblated Equal Area + Misc Sph + n= m= theta= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=oea +a=6400000 +lat_1=0.5 +lat_2=2 +n=1 +m=2 +theta=3 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 228926.872097864 99870.488430076 +accept 2 -1 +expect 217242.584036940 -123247.885607475 +accept -2 1 +expect -217242.584036940 123247.885607475 +accept -2 -1 +expect -228926.872097864 -99870.488430076 + +direction inverse +accept 200 100 +expect 0.001741186 0.000987727 +accept 200 -100 +expect 0.001834893 -0.000800312 +accept -200 100 +expect -0.001834893 0.000800312 +accept -200 -100 +expect -0.001741186 -0.000987727 + + +=============================================================================== +Oblique Mercator + Cyl, Sph&Ell no_rot + alpha= [gamma=] [no_off] lonc= or + lon_1= lat_1= lon_2= lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=omerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222650.796885261 110642.229314984 +accept 2 -1 +expect 222650.796885261 -110642.229314984 +accept -2 1 +expect -222650.796885262 110642.229314984 +accept -2 -1 +expect -222650.796885262 -110642.229314984 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + + +=============================================================================== +Ortelius Oval + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=ortel +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223374.577355253 111701.072127637 +accept 2 -1 +expect 223374.577355253 -111701.072127637 +accept -2 1 +expect -223374.577355253 111701.072127637 +accept -2 -1 +expect -223374.577355253 -111701.072127637 + + +=============================================================================== +Orthographic + Azi, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=ortho +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223322.760576727 111695.401198614 +accept 2 -1 +expect 223322.760576727 -111695.401198614 +accept -2 1 +expect -223322.760576727 111695.401198614 +accept -2 -1 +expect -223322.760576727 -111695.401198614 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Perspective Conic + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=pconic +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222588.098841617 111416.604770067 +accept 2 -1 +expect 222757.718091090 -111331.881531080 +accept -2 1 +expect -222588.098841617 111416.604770067 +accept -2 -1 +expect -222757.718091090 -111331.881531080 + +direction inverse +accept 200 100 +expect 0.001796358 0.000897964 +accept 200 -100 +expect 0.001796356 -0.000897965 +accept -200 100 +expect -0.001796358 0.000897964 +accept -200 -100 +expect -0.001796356 -0.000897965 + +------------------------------------------------------------------------------- +operation +proj=pconic +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223351.087094295 111798.518992055 +accept 2 -1 +expect 223521.287765217 -111713.505338457 +accept -2 1 +expect -223351.087094295 111798.518992055 +accept -2 -1 +expect -223521.287765217 -111713.505338457 + +direction inverse +accept 200 100 +expect 0.001790221 0.000894897 +accept 200 -100 +expect 0.001790220 -0.000894897 +accept -200 100 +expect -0.001790221 0.000894897 +accept -200 -100 +expect -0.001790220 -0.000894897 + + +=============================================================================== +Patterson Cylindrical + Cyl. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=patterson +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 113354.250397780 +accept 2 -1 +expect 223402.144255274 -113354.250397780 +accept -2 1 +expect -223402.144255274 113354.250397780 +accept -2 -1 +expect -223402.144255274 -113354.250397780 + +direction inverse +accept 200 100 +expect 0.001790493 0.000882190 +accept 200 -100 +expect 0.001790493 -0.000882190 +accept -200 100 +expect -0.001790493 0.000882190 +accept -200 -100 +expect -0.001790493 -0.000882190 + + +=============================================================================== +Polyconic (American) + Conic, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=poly +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222605.285770237 110642.194561440 +accept 2 -1 +expect 222605.285770237 -110642.194561440 +accept -2 1 +expect -222605.285770237 110642.194561440 +accept -2 -1 +expect -222605.285770237 -110642.194561440 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=poly +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.105210219 111769.110491225 +accept 2 -1 +expect 223368.105210219 -111769.110491225 +accept -2 1 +expect -223368.105210219 111769.110491225 +accept -2 -1 +expect -223368.105210219 -111769.110491225 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Putnins P1 + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp1 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 211642.762754160 105831.180787330 +accept 2 -1 +expect 211642.762754160 -105831.180787330 +accept -2 1 +expect -211642.762754160 105831.180787330 +accept -2 -1 +expect -211642.762754160 -105831.180787330 + +direction inverse +accept 200 100 +expect 0.001889802 0.000944901 +accept 200 -100 +expect 0.001889802 -0.000944901 +accept -200 100 +expect -0.001889802 0.000944901 +accept -200 -100 +expect -0.001889802 -0.000944901 + + +=============================================================================== +Putnins P2 + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 211638.039634339 117895.033043380 +accept 2 -1 +expect 211638.039634339 -117895.033043380 +accept -2 1 +expect -211638.039634339 117895.033043380 +accept -2 -1 +expect -211638.039634339 -117895.033043380 + +direction inverse +accept 200 100 +expect 0.001889802 0.000848202 +accept 200 -100 +expect 0.001889802 -0.000848202 +accept -200 100 +expect -0.001889802 0.000848202 +accept -200 -100 +expect -0.001889802 -0.000848202 + + +=============================================================================== +Putnins P3 + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp3 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 178227.115507794 89124.560786088 +accept 2 -1 +expect 178227.115507794 -89124.560786088 +accept -2 1 +expect -178227.115507794 89124.560786088 +accept -2 -1 +expect -178227.115507794 -89124.560786088 + +direction inverse +accept 200 100 +expect 0.002244050 0.001122025 +accept 200 -100 +expect 0.002244050 -0.001122025 +accept -200 100 +expect -0.002244050 0.001122025 +accept -200 -100 +expect -0.002244050 -0.001122025 + + +=============================================================================== +Putnins P3' + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp3p +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 178238.118539985 89124.560786088 +accept 2 -1 +expect 178238.118539985 -89124.560786088 +accept -2 1 +expect -178238.118539985 89124.560786088 +accept -2 -1 +expect -178238.118539985 -89124.560786088 + +direction inverse +accept 200 100 +expect 0.002244050 0.001122025 +accept 200 -100 +expect 0.002244050 -0.001122025 +accept -200 100 +expect -0.002244050 0.001122025 +accept -200 -100 +expect -0.002244050 -0.001122025 + + +=============================================================================== +Putnins P4' + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp4p +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 195241.477349386 127796.782307926 +accept 2 -1 +expect 195241.477349386 -127796.782307926 +accept -2 1 +expect -195241.477349386 127796.782307926 +accept -2 -1 +expect -195241.477349386 -127796.782307926 + +direction inverse +accept 200 100 +expect 0.002048528 0.000782480 +accept 200 -100 +expect 0.002048528 -0.000782480 +accept -200 100 +expect -0.002048528 0.000782480 +accept -200 -100 +expect -0.002048528 -0.000782480 + + +=============================================================================== +Putnins P5 + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp5 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 226367.213380562 113204.568558475 +accept 2 -1 +expect 226367.213380562 -113204.568558475 +accept -2 1 +expect -226367.213380562 113204.568558475 +accept -2 -1 +expect -226367.213380562 -113204.568558475 + +direction inverse +accept 200 100 +expect 0.001766713 0.000883357 +accept 200 -100 +expect 0.001766713 -0.000883357 +accept -200 100 +expect -0.001766713 0.000883357 +accept -200 -100 +expect -0.001766713 -0.000883357 + + +=============================================================================== +Putnins P5' + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp5p +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 226388.175248756 113204.568558475 +accept 2 -1 +expect 226388.175248756 -113204.568558475 +accept -2 1 +expect -226388.175248756 113204.568558475 +accept -2 -1 +expect -226388.175248756 -113204.568558475 + +direction inverse +accept 200 100 +expect 0.001766713 0.000883357 +accept 200 -100 +expect 0.001766713 -0.000883357 +accept -200 100 +expect -0.001766713 0.000883357 +accept -200 -100 +expect -0.001766713 -0.000883357 + + +=============================================================================== +Putnins P6 + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp6 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 226369.395133403 110218.523796521 +accept 2 -1 +expect 226369.395133403 -110218.523796521 +accept -2 1 +expect -226369.395133403 110218.523796521 +accept -2 -1 +expect -226369.395133403 -110218.523796521 + +direction inverse +accept 200 100 +expect 0.001766713 0.000907296 +accept 200 -100 +expect 0.001766713 -0.000907296 +accept -200 100 +expect -0.001766713 0.000907296 +accept -200 -100 +expect -0.001766713 -0.000907296 + + +=============================================================================== +Putnins P6' + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=putp6p +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 198034.195132195 125989.475461323 +accept 2 -1 +expect 198034.195132195 -125989.475461323 +accept -2 1 +expect -198034.195132195 125989.475461323 +accept -2 -1 +expect -198034.195132195 -125989.475461323 + +direction inverse +accept 200 100 +expect 0.002019551 0.000793716 +accept 200 -100 +expect 0.002019551 -0.000793716 +accept -200 100 +expect -0.002019551 0.000793716 +accept -200 -100 +expect -0.002019551 -0.000793716 + + +=============================================================================== +Quartic Authalic + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=qua_aut +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222613.549033097 111318.077887984 +accept 2 -1 +expect 222613.549033097 -111318.077887984 +accept -2 1 +expect -222613.549033097 111318.077887984 +accept -2 -1 +expect -222613.549033097 -111318.077887984 + +direction inverse +accept 200 100 +expect 0.001796631 0.000898315 +accept 200 -100 +expect 0.001796631 -0.000898315 +accept -200 100 +expect -0.001796631 0.000898315 +accept -200 -100 +expect -0.001796631 -0.000898315 + +------------------------------------------------------------------------------- +operation +proj=qua_aut +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223376.624524029 111699.654379186 +accept 2 -1 +expect 223376.624524029 -111699.654379186 +accept -2 1 +expect -223376.624524029 111699.654379186 +accept -2 -1 +expect -223376.624524029 -111699.654379186 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Quadrilateralized Spherical Cube + Azi, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=qsc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 304638.450843852 164123.870923794 +accept 2 -1 +expect 304638.450843852 -164123.870923794 +accept -2 1 +expect -304638.450843852 164123.870923794 +accept -2 -1 +expect -304638.450843852 -164123.870923794 + +direction inverse +accept 200 100 +expect 0.001321341 0.000610653 +accept 200 -100 +expect 0.001321341 -0.000610653 +accept -200 100 +expect -0.001321341 0.000610653 +accept -200 -100 +expect -0.001321341 -0.000610653 + +------------------------------------------------------------------------------- +operation +proj=qsc +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 305863.792402891 165827.722754715 +accept 2 -1 +expect 305863.792402891 -165827.722754715 +accept -2 1 +expect -305863.792402891 165827.722754715 +accept -2 -1 +expect -305863.792402891 -165827.722754715 + +direction inverse +accept 200 100 +expect 0.001316827 0.000604493 +accept 200 -100 +expect 0.001316827 -0.000604493 +accept -200 100 +expect -0.001316827 0.000604493 +accept -200 -100 +expect -0.001316827 -0.000604493 + + +=============================================================================== +Robinson + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=robin +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 189588.423282508 107318.530350703 +accept 2 -1 +expect 189588.423282508 -107318.530350703 +accept -2 1 +expect -189588.423282508 107318.530350703 +accept -2 -1 +expect -189588.423282508 -107318.530350703 + +direction inverse +accept 200 100 +expect 0.002109689 0.000931806 +accept 200 -100 +expect 0.002109689 -0.000931806 +accept -200 100 +expect -0.002109689 0.000931806 +accept -200 -100 +expect -0.002109689 -0.000931806 + + +=============================================================================== +Roussilhe Stereographic + Azi., Ellps. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=rouss +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222644.894131617 110611.091868370 +accept 2 -1 +expect 222644.894131617 -110611.091868370 +accept -2 1 +expect -222644.894131617 110611.091868370 +accept -2 -1 +expect -222644.894131617 -110611.091868370 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + + +=============================================================================== +Rectangular Polyconic + Conic, Sph., no inv. + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=rpoly +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.098302014 111769.110486991 +accept 2 -1 +expect 223368.098302014 -111769.110486991 +accept -2 1 +expect -223368.098302014 111769.110486991 +accept -2 -1 +expect -223368.098302014 -111769.110486991 + + +=============================================================================== +Sinusoidal (Sanson-Flamsteed) + PCyl, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=sinu +ellps=GRS80 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222605.299539466 110574.388554153 +accept 2 -1 +expect 222605.299539466 -110574.388554153 +accept -2 1 +expect -222605.299539466 110574.388554153 +accept -2 -1 +expect -222605.299539466 -110574.388554153 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=sinu +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223368.119026632 111701.072127637 +accept 2 -1 +expect 223368.119026632 -111701.072127637 +accept -2 1 +expect -223368.119026632 111701.072127637 +accept -2 -1 +expect -223368.119026632 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Swiss. Obl. Mercator + Cyl, Ell + For CH1903 +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=somerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222638.981586547 110579.965218249 +accept 2 -1 +expect 222638.981586547 -110579.965218251 +accept -2 1 +expect -222638.981586547 110579.965218249 +accept -2 -1 +expect -222638.981586547 -110579.965218251 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=somerc +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223402.144255274 111706.743574944 +accept 2 -1 +expect 223402.144255274 -111706.743574945 +accept -2 1 +expect -223402.144255274 111706.743574944 +accept -2 -1 +expect -223402.144255274 -111706.743574945 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Stereographic + Azi, Sph&Ell + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=stere +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222644.854550117 110610.883474174 +accept 2 -1 +expect 222644.854550117 -110610.883474174 +accept -2 1 +expect -222644.854550117 110610.883474174 +accept -2 -1 +expect -222644.854550117 -110610.883474174 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=stere +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223407.810259507 111737.938996443 +accept 2 -1 +expect 223407.810259507 -111737.938996443 +accept -2 1 +expect -223407.810259507 111737.938996443 +accept -2 -1 +expect -223407.810259507 -111737.938996443 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Oblique Stereographic Alternative + Azimuthal, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=sterea +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222644.894109198 110611.091871737 +accept 2 -1 +expect 222644.894109198 -110611.091871738 +accept -2 1 +expect -222644.894109198 110611.091871737 +accept -2 -1 +expect -222644.894109198 -110611.091871738 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=sterea +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223407.810259507 111737.938996443 +accept 2 -1 +expect 223407.810259507 -111737.938996443 +accept -2 1 +expect -223407.810259507 111737.938996443 +accept -2 -1 +expect -223407.810259507 -111737.938996443 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion) + Cyl, Sph&Ell + lat_0= lon_0= k_0= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=gstmerc +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223413.466406322 111769.145040586 +accept 2 -1 +expect 223413.466406322 -111769.145040587 +accept -2 1 +expect -223413.466406323 111769.145040586 +accept -2 -1 +expect -223413.466406323 -111769.145040587 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Transverse Central Cylindrical + Cyl, Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tcc +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223458.844192458 111769.145040586 +accept 2 -1 +expect 223458.844192458 -111769.145040586 +accept -2 1 +expect -223458.844192458 111769.145040586 +accept -2 -1 +expect -223458.844192458 -111769.145040586 + + +=============================================================================== +Transverse Cylindrical Equal Area + Cyl, Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tcea +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223322.760576727 111769.145040586 +accept 2 -1 +expect 223322.760576727 -111769.145040586 +accept -2 1 +expect -223322.760576727 111769.145040586 +accept -2 -1 +expect -223322.760576727 -111769.145040586 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Times + Cyl, Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=times +ellps=sphere +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 0.000000000 0.000000000 +expect 0.000000000 0.000000000 +accept 80.000000000 70.000000000 +expect 5785183.576067096 7615452.066120422 +accept 25.000000000 -10.000000000 +expect 2065971.530107881 -951526.064849459 +accept -35.000000000 20.000000000 +expect -2873054.045485095 1917730.953000521 +accept -45.000000000 -30.000000000 +expect -3651383.203521487 -2914213.457815921 + +direction inverse +accept 0.000000000 0.000000000 +expect 0.000000000 0.000000000 +accept 5785183.576067096 7615452.066120422 +expect 80.000000000 70.000000000 +accept 2065971.530107881 -951526.064849459 +expect 25.000000000 -10.000000000 +accept -2873054.045485095 1917730.953000521 +expect -35.000000000 20.000000000 +accept -3651383.203521487 -2914213.457815921 +expect -45.000000000 -30.000000000 + + +=============================================================================== +Tissot + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tissot +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222641.078699631 54347.828487281 +accept 2 -1 +expect 222810.614513941 -168291.088549939 +accept -2 1 +expect -222641.078699631 54347.828487281 +accept -2 -1 +expect -222810.614513941 -168291.088549939 + +direction inverse +accept 200 100 +expect 0.001796281 0.513444955 +accept 200 -100 +expect 0.001796279 0.511648325 +accept -200 100 +expect -0.001796281 0.513444955 +accept -200 -100 +expect -0.001796279 0.511648325 + +------------------------------------------------------------------------------- +operation +proj=tissot +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223404.248556849 54534.122161158 +accept 2 -1 +expect 223574.365506608 -168867.957323528 +accept -2 1 +expect -223404.248556849 54534.122161158 +accept -2 -1 +expect -223574.365506608 -168867.957323528 + +direction inverse +accept 200 100 +expect 0.001790144 0.513441886 +accept 200 -100 +expect 0.001790143 0.511651393 +accept -200 100 +expect -0.001790144 0.513441886 +accept -200 -100 +expect -0.001790143 0.511651393 + + +=============================================================================== +Transverse Mercator + Cyl, Sph&Ell +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tmerc +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222650.796795778 110642.229411927 +accept 2 -1 +expect 222650.796795778 -110642.229411927 +accept -2 1 +expect -222650.796795778 110642.229411927 +accept -2 -1 +expect -222650.796795778 -110642.229411927 + +direction inverse +accept 200 100 +expect 0.001796631 0.000904369 +accept 200 -100 +expect 0.001796631 -0.000904369 +accept -200 100 +expect -0.001796631 0.000904369 +accept -200 -100 +expect -0.001796631 -0.000904369 + +------------------------------------------------------------------------------- +operation +proj=tmerc +R=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223413.466406322 111769.145040597 +accept 2 -1 +expect 223413.466406322 -111769.145040597 +accept -2 1 +expect -223413.466406322 111769.145040597 +accept -2 -1 +expect -223413.466406322 -111769.145040597 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Two Point Equidistant + Misc Sph + lat_1= lon_1= lat_2= lon_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tpeqd +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -27750.758831679 -222599.403691777 +accept 2 -1 +expect -250434.937024036 -222655.938193266 +accept -2 1 +expect -27750.758831679 222599.403691777 +accept -2 -1 +expect -250434.937024036 222655.938193266 + +direction inverse +accept 200 100 +expect -0.000898556 1.251796630 +accept 200 -100 +expect 0.000898556 1.251796630 +accept -200 100 +expect -0.000898554 1.248203369 +accept -200 -100 +expect 0.000898554 1.248203369 + +------------------------------------------------------------------------------- +operation +proj=tpeqd +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect -27845.882978485 -223362.430695260 +accept 2 -1 +expect -251293.378764651 -223419.158985908 +accept -2 1 +expect -27845.882978485 223362.430695260 +accept -2 -1 +expect -251293.378764651 223419.158985908 + +direction inverse +accept 200 100 +expect -0.000895486 1.251790493 +accept 200 -100 +expect 0.000895486 1.251790493 +accept -200 100 +expect -0.000895485 1.248209507 +accept -200 -100 +expect 0.000895485 1.248209507 + + +=============================================================================== +Tilted perspective + Azi, Sph + tilt= azi= h= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=tpers +a=6400000 +h=1000000 +azi=20 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 170820.288955531 180460.865555805 +accept 2 -1 +expect 246853.941538942 -28439.878035775 +accept -2 1 +expect -246853.941538942 28439.878035775 +accept -2 -1 +expect -170820.288955531 -180460.865555805 + +direction inverse +accept 200 100 +expect 0.001988706 0.000228872 +accept 200 -100 +expect 0.001376321 -0.001453641 +accept -200 100 +expect -0.001376321 0.001453641 +accept -200 -100 +expect -0.001988706 -0.000228872 + + +=============================================================================== +Universal Polar Stereographic + Azi, Sph&Ell + south +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=ups +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 2433455.563438467 -10412543.301512826 +accept 2 -1 +expect 2448749.118568199 -10850493.419804076 +accept -2 1 +expect 1566544.436561533 -10412543.301512826 +accept -2 -1 +expect 1551250.881431801 -10850493.419804076 + +direction inverse +accept 200 100 +expect -44.998567498 64.918236287 +accept 200 -100 +expect -44.995702709 64.917020251 +accept -200 100 +expect -45.004297076 64.915804281 +accept -200 -100 +expect -45.001432287 64.914588378 + + +=============================================================================== +Urmaev V + PCyl., Sph., no inv. + n= q= alpha= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=urm5 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223393.638433964 111696.818785117 +accept 2 -1 +expect 223393.638433964 -111696.818785117 +accept -2 1 +expect -223393.638433964 111696.818785117 +accept -2 -1 +expect -223393.638433964 -111696.818785117 + + +=============================================================================== +Urmaev Flat-Polar Sinusoidal + PCyl, Sph. + n= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=urmfps +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 196001.708134192 127306.843329993 +accept 2 -1 +expect 196001.708134192 -127306.843329993 +accept -2 1 +expect -196001.708134192 127306.843329993 +accept -2 -1 +expect -196001.708134192 -127306.843329993 + +direction inverse +accept 200 100 +expect 0.002040721 0.000785474 +accept 200 -100 +expect 0.002040721 -0.000785474 +accept -200 100 +expect -0.002040721 0.000785474 +accept -200 -100 +expect -0.002040721 -0.000785474 + + +=============================================================================== +Universal Transverse Mercator (UTM) + Cyl, Sph + zone= south +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=utm +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +zone=30 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 1057002.405491298 110955.141175949 +accept 2 -1 +expect 1057002.405491298 -110955.141175949 +accept -2 1 +expect 611263.812278905 110547.105696804 +accept -2 -1 +expect 611263.812278905 -110547.105696804 + +direction inverse +accept 200 100 +expect -7.486952083 0.000901940 +accept 200 -100 +expect -7.486952083 -0.000901940 +accept -200 100 +expect -7.490535682 0.000901935 +accept -200 -100 +expect -7.490535682 -0.000901935 + + +=============================================================================== +van der Grinten (I) + Misc Sph +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=vandg +a=6400000 +lat_1=0.5 +lat_2=2 +no_defs +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223395.249543407 111704.596633675 +rem 223395.249543407 111704.596633675 osgeo +rem 223395.249543407 111704.596633675 debug/bin + + +accept 2 -1 +expect 223395.249543407 -111704.596633675 +accept -2 1 +expect -223395.249543407 111704.596633675 +accept -2 -1 +expect -223395.249543407 -111704.596633675 + +direction inverse +accept 200 100 +expect 0.001790494 0.000895247 +accept 200 -100 +expect 0.001790494 -0.000895247 +accept -200 100 +expect -0.001790494 0.000895247 +accept -200 -100 +expect -0.001790494 -0.000895247 + + +=============================================================================== +van der Grinten II + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=vandg2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223395.247850437 111718.491037226 +accept 2 -1 +expect 223395.247850437 -111718.491037226 +accept -2 1 +expect -223395.247850437 111718.491037226 +accept -2 -1 +expect -223395.247850437 -111718.491037226 + + +=============================================================================== +van der Grinten III + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=vandg3 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223395.249552831 111704.519904421 +accept 2 -1 +expect 223395.249552831 -111704.519904421 +accept -2 1 +expect -223395.249552831 111704.519904421 +accept -2 -1 +expect -223395.249552831 -111704.519904421 + + +=============================================================================== +van der Grinten IV + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=vandg4 +R=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.01 mm +accept 2 1 +expect 223374.577294355 111701.195484154 +accept 2 -1 +expect 223374.577294355 -111701.195484154 +accept -2 1 +expect -223374.577294355 111701.195484154 +accept -2 -1 +expect -223374.577294355 -111701.195484154 + + +=============================================================================== +Vitkovsky I + Conic, Sph + lat_1= and lat_2= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=vitk1 +ellps=GRS80 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 222607.171211458 111404.251442435 +accept 2 -1 +expect 222776.716709598 -111234.665587445 +accept -2 1 +expect -222607.171211458 111404.251442435 +accept -2 -1 +expect -222776.716709598 -111234.665587445 + +direction inverse +accept 200 100 +expect 0.001796204 0.000898315 +accept 200 -100 +expect 0.001796202 -0.000898316 +accept -200 100 +expect -0.001796204 0.000898315 +accept -200 -100 +expect -0.001796202 -0.000898316 + +------------------------------------------------------------------------------- +operation +proj=vitk1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223370.224840471 111786.123319644 +accept 2 -1 +expect 223540.351507255 -111615.956157675 +accept -2 1 +expect -223370.224840471 111786.123319644 +accept -2 -1 +expect -223540.351507255 -111615.956157675 + +direction inverse +accept 200 100 +expect 0.001790068 0.000895246 +accept 200 -100 +expect 0.001790066 -0.000895247 +accept -200 100 +expect -0.001790068 0.000895246 +accept -200 -100 +expect -0.001790066 -0.000895247 + + +=============================================================================== +Wagner I (Kavraisky VI) + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag1 +a=6400000 +lat_1=0.5 +lat_2=2 +n=0.5 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 195986.781561158 127310.075060660 +accept 2 -1 +expect 195986.781561158 -127310.075060660 +accept -2 1 +expect -195986.781561158 127310.075060660 +accept -2 -1 +expect -195986.781561158 -127310.075060660 + +direction inverse +accept 200 100 +expect 0.002040721 0.000785474 +accept 200 -100 +expect 0.002040721 -0.000785474 +accept -200 100 +expect -0.002040721 0.000785474 +accept -200 -100 +expect -0.002040721 -0.000785474 + + +=============================================================================== +Wagner II + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 206589.888099962 120778.040357547 +accept 2 -1 +expect 206589.888099962 -120778.040357547 +accept -2 1 +expect -206589.888099962 120778.040357547 +accept -2 -1 +expect -206589.888099962 -120778.040357547 + +direction inverse +accept 200 100 +expect 0.001936024 0.000827958 +accept 200 -100 +expect 0.001936024 -0.000827958 +accept -200 100 +expect -0.001936024 0.000827958 +accept -200 -100 +expect -0.001936024 -0.000827958 + + +=============================================================================== +Wagner III + PCyl., Sph. + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag3 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223387.021718166 111701.072127637 +accept 2 -1 +expect 223387.021718166 -111701.072127637 +accept -2 1 +expect -223387.021718166 111701.072127637 +accept -2 -1 +expect -223387.021718166 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Wagner IV + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag4 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 192801.218662384 129416.216394803 +accept 2 -1 +expect 192801.218662384 -129416.216394803 +accept -2 1 +expect -192801.218662384 129416.216394803 +accept -2 -1 +expect -192801.218662384 -129416.216394803 + +direction inverse +accept 200 100 +expect 0.002074503 0.000772683 +accept 200 -100 +expect 0.002074503 -0.000772683 +accept -200 100 +expect -0.002074503 0.000772683 +accept -200 -100 +expect -0.002074503 -0.000772683 + + +=============================================================================== +Wagner V + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag5 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 203227.051925325 138651.631442713 +accept 2 -1 +expect 203227.051925325 -138651.631442713 +accept -2 1 +expect -203227.051925325 138651.631442713 +accept -2 -1 +expect -203227.051925325 -138651.631442713 + +direction inverse +accept 200 100 +expect 0.001968072 0.000721216 +accept 200 -100 +expect 0.001968072 -0.000721216 +accept -200 100 +expect -0.001968072 0.000721216 +accept -200 -100 +expect -0.001968072 -0.000721216 + + +=============================================================================== +Wagner VI + PCyl, Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag6 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 211652.562164410 105831.180787330 +accept 2 -1 +expect 211652.562164410 -105831.180787330 +accept -2 1 +expect -211652.562164410 105831.180787330 +accept -2 -1 +expect -211652.562164410 -105831.180787330 + +direction inverse +accept 200 100 +expect 0.001889802 0.000944901 +accept 200 -100 +expect 0.001889802 -0.000944901 +accept -200 100 +expect -0.001889802 0.000944901 +accept -200 -100 +expect -0.001889802 -0.000944901 + + +=============================================================================== +Wagner VII + Misc Sph, no inv. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wag7 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 198601.876957312 125637.045714171 +accept 2 -1 +expect 198601.876957312 -125637.045714171 +accept -2 1 +expect -198601.876957312 125637.045714171 +accept -2 -1 +expect -198601.876957312 -125637.045714171 + + +=============================================================================== +Werenskiold I + PCyl., Sph. +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=weren +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223378.515757634 146214.093042288 +accept 2 -1 +expect 223378.515757634 -146214.093042288 +accept -2 1 +expect -223378.515757634 146214.093042288 +accept -2 -1 +expect -223378.515757634 -146214.093042288 + +direction inverse +accept 200 100 +expect 0.001790493 0.000683918 +accept 200 -100 +expect 0.001790493 -0.000683918 +accept -200 100 +expect -0.001790493 0.000683918 +accept -200 -100 +expect -0.001790493 -0.000683918 + + +=============================================================================== +Winkel I + PCyl., Sph. + lat_ts= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wink1 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223385.131640953 111701.072127637 +accept 2 -1 +expect 223385.131640953 -111701.072127637 +accept -2 1 +expect -223385.131640953 111701.072127637 +accept -2 -1 +expect -223385.131640953 -111701.072127637 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 + + +=============================================================================== +Winkel II + PCyl., Sph., no inv. + lat_1= +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wink2 +a=6400000 +lat_1=0.5 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223387.396433786 124752.032797445 +accept 2 -1 +expect 223387.396433786 -124752.032797445 +accept -2 1 +expect -223387.396433786 124752.032797445 +accept -2 -1 +expect -223387.396433786 -124752.032797445 + + +=============================================================================== +Winkel Tripel + Misc Sph + lat_1 +=============================================================================== + +------------------------------------------------------------------------------- +operation +proj=wintri +a=6400000 +lat_1=0 +lat_2=2 +------------------------------------------------------------------------------- +tolerance 0.00010 mm +accept 2 1 +expect 223390.801533485 111703.907505745 +accept 2 -1 +expect 223390.801533485 -111703.907505745 +accept -2 1 +expect -223390.801533485 111703.907505745 +accept -2 -1 +expect -223390.801533485 -111703.907505745 + +direction inverse +accept 200 100 +expect 0.001790493 0.000895247 +accept 200 -100 +expect 0.001790493 -0.000895247 +accept -200 100 +expect -0.001790493 0.000895247 +accept -200 -100 +expect -0.001790493 -0.000895247 +Internal regression tests done. [Stubs: 0] Total: 151. Failure: 0. Success: 151 + +END diff --git a/test/gie/deformation.gie b/test/gie/deformation.gie new file mode 100644 index 00000000..ce9aca75 --- /dev/null +++ b/test/gie/deformation.gie @@ -0,0 +1,75 @@ +=============================================================================== +Test for the deformation operation - Kinematic Gridshifting + +For all the deformation tests the alaska and egm96_15.gtx grids are used even +though they are not parts of a deformation model, they are in the proper format +and for testing purposes it doesn't really matter all that much... + +The input coordinate is located at lon=60, lam=-160 - somewhere in Alaska. + +=============================================================================== + +BEGIN + +------------------------------------------------------------------------------- +Test using only horizontal grid and +tobs parameter +------------------------------------------------------------------------------- +OPERATION +proj=deformation +xy_grids=alaska +t_epoch=2016.0 +t_obs=2000.0 +------------------------------------------------------------------------------- +TOLERANCE 1 um +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 +EXPECT -3004295.5888766116 -1093474.1688513425 5500477.1338251457 +# ROUNDTRIP 1000 + +------------------------------------------------------------------------------- +Test using only vertical grid and +tobs parameter +------------------------------------------------------------------------------- +OPERATION +proj=deformation +z_grids=egm96_15.gtx +t_epoch=2016.0 +t_obs=2000.0 +------------------------------------------------------------------------------- +TOLERANCE 1 um +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 +EXPECT -3004295.5882503074 -1093474.1690603832 5500234.008855661 +# ROUNDTRIP 1000 + +------------------------------------------------------------------------------- +Test using both horizontal and vertical grids as well as the +tobs parameter +------------------------------------------------------------------------------- +OPERATION +proj=deformation +xy_grids=alaska +z_grids=egm96_15.gtx +t_epoch=2016.0 +t_obs=2000.0 +------------------------------------------------------------------------------- +TOLERANCE 0.000001 m +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 +EXPECT -3004295.5888766116 -1093474.1688513425 5500234.008855661 +# ROUNDTRIP 1000 + +------------------------------------------------------------------------------- +Test using only horizontal grid +------------------------------------------------------------------------------- +OPERATION +proj=deformation +xy_grids=alaska +t_epoch=2016.0 +------------------------------------------------------------------------------- +TOLERANCE 1 um +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 2000.0 +EXPECT -3004295.5888766116 -1093474.1688513425 5500477.1338251457 2000.0 +# ROUNDTRIP 1000 + +------------------------------------------------------------------------------- +Test using only vertical grid +------------------------------------------------------------------------------- +OPERATION +proj=deformation +z_grids=egm96_15.gtx +t_epoch=2016.0 +------------------------------------------------------------------------------- +TOLERANCE 1 um +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 2000.0 +EXPECT -3004295.5882503074 -1093474.1690603832 5500234.008855661 2000.0 +# ROUNDTRIP 1000 + +------------------------------------------------------------------------------- +Test using both horizontal and vertical grids +------------------------------------------------------------------------------- +OPERATION +proj=deformation +xy_grids=alaska +z_grids=egm96_15.gtx +t_epoch=2016.0 +ellps=GRS80 +------------------------------------------------------------------------------- +TOLERANCE 1 um +ACCEPT -3004295.5882503074 -1093474.1690603832 5500477.1338251457 2000.0 +EXPECT -3004295.5888766116 -1093474.1688513425 5500234.008855661 2000.0 +# ROUNDTRIP 1000 + + +END diff --git a/test/gie/more_builtins.gie b/test/gie/more_builtins.gie new file mode 100644 index 00000000..1e3ce185 --- /dev/null +++ b/test/gie/more_builtins.gie @@ -0,0 +1,264 @@ + +=============================================================================== + +Various test material, mostly converted from selftest entries in PJ_xxx.c + +Contrary to the material in builtins.gie, this material is handwritten and +intends to exercise corner cases. + +=============================================================================== + + +BEGIN + +------------------------------------------------------------------------------- +Two ob_tran tests from nad/testvarious +------------------------------------------------------------------------------- +operation +proj=ob_tran +o_proj=moll +R=6378137.0 +o_lon_p=0 +o_lat_p=0 +lon_0=180 +------------------------------------------------------------------------------- +tolerance 1 mm +direction inverse + +accept 300000 400000 0 0 +expect -42.7562158333 85.5911341667 0 0 + +direction forward + +accept 10 20 0 0 +expect -1384841.18787 7581707.88240 0 0 +------------------------------------------------------------------------------- + + + + + +------------------------------------------------------------------------------- +Two tests from PJ_molodensky.c +------------------------------------------------------------------------------- +operation proj=molodensky a=6378160 rf=298.25 \ + da=-23 df=-8.120449e-8 dx=-134 dy=-48 dz=149 \ + abridged +------------------------------------------------------------------------------- +tolerance 2 m + +accept 144.9667 -37.8 50 0 +expect 144.968 -37.79848 46.378 0 + +roundtrip 100 1 m +------------------------------------------------------------------------------- +Same thing once more, but this time unabridged +------------------------------------------------------------------------------- +operation proj=molodensky a=6378160 rf=298.25 \ + da=-23 df=-8.120449e-8 dx=-134 dy=-48 dz=149 +------------------------------------------------------------------------------- +tolerance 2 m + +accept 144.9667 -37.8 50 0 +expect 144.968 -37.79848 46.378 0 + +roundtrip 100 1 m +------------------------------------------------------------------------------- + + + + + +------------------------------------------------------------------------------- +Some tests from PJ_pipeline.c +------------------------------------------------------------------------------- +Forward-reverse geo->utm->geo +------------------------------------------------------------------------------- +operation proj=pipeline zone=32 step \ + proj=utm ellps=GRS80 step \ + proj=utm ellps=GRS80 inv +------------------------------------------------------------------------------- +tolerance 0.1 mm + +accept 12 55 0 0 +expect 12 55 0 0 + +Now the inverse direction (still same result: the pipeline is symmetrical) + +direction inverse +expect 12 55 0 0 +------------------------------------------------------------------------------- +And now the back-to-back situation utm->geo->utm +------------------------------------------------------------------------------- +operation proj=pipeline zone=32 ellps=GRS80 step \ + proj=utm inv step \ + proj=utm +------------------------------------------------------------------------------- +accept 691875.63214 6098907.82501 0 0 +expect 691875.63214 6098907.82501 0 0 +direction inverse +expect 691875.63214 6098907.82501 0 0 +------------------------------------------------------------------------------- +Test a corner case: A rather pointless one-step pipeline geo->utm +------------------------------------------------------------------------------- +operation proj=pipeline step proj=utm zone=32 ellps=GRS80 +------------------------------------------------------------------------------- +accept 12 55 0 0 +expect 691875.63214 6098907.82501 0 0 +direction inverse +accept 691875.63214 6098907.82501 0 0 +expect 12 55 0 0 +------------------------------------------------------------------------------- +Finally test a pipeline with more than one init step +------------------------------------------------------------------------------- +operation proj=pipeline step \ + init=epsg:25832 inv step \ + init=epsg:25833 step \ + init=epsg:25833 inv step \ + init=epsg:25832 +------------------------------------------------------------------------------- +accept 691875.63214 6098907.82501 0 0 +expect 691875.63214 6098907.82501 0 0 +direction inverse +accept 12 55 0 0 +expect 12 55 0 0 + + + + + +------------------------------------------------------------------------------- +Some tests from PJ_vgridshift.c +------------------------------------------------------------------------------- +operation proj=vgridshift grids=egm96_15.gtx ellps=GRS80 +------------------------------------------------------------------------------- +Appears there is a difference between the egm96_15.gtx distributed by OSGeo4W, +and the one from http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx +N(12.5, 55.5) = -36.021305084228515625 (download.osgeo.org) +N(12.5, 55.5) = -35.880001068115234000 (OSGeo4W) +This is annoying, but must be handled elsewhere. We jump through the hoop by +setting a very lax tolerance. + +tolerance 15 cm +accept 12.5 55.5 0 0 +expect 12.5 55.5 -36.021305084228516 0 + +roundtrip 100 1 nm +------------------------------------------------------------------------------- +Fail on purpose: +grids parameter is mandatory +operation proj=vgridshift +expect failure + +Fail on purpose: open non-existing grid +operation proj=vgridshift grids=nonexistinggrid.gtx +expect failure + + + + + +------------------------------------------------------------------------------- +Some tests from PJ_hgridshift.c +------------------------------------------------------------------------------- +operation proj=hgridshift +grids=nzgd2kgrid0005.gsb ellps=GRS80 +------------------------------------------------------------------------------- +tolerance 1 nm +accept 173 -45 0 0 +roundtrip 100 +------------------------------------------------------------------------------- +expect 172.999892181021551 -45.001620431954613 0 0 +direction inverse +accept 172.999892181021551 -45.001620431954613 0 0 +expect 173 -45 0 0 +------------------------------------------------------------------------------- +Fail on purpose: +grids parameter is mandatory: +operation proj=hgridshift +expect failure + +Fail on purpose: open non-existing grid: +operation proj=hgridshift grids=@nonexistinggrid.gsb,anothernonexistinggrid.gsb +expect failure +------------------------------------------------------------------------------- + + + + +------------------------------------------------------------------------------- +A number of tests from PJ_helmert.c +------------------------------------------------------------------------------- +This example is from Lotti Jivall: "Simplified transformations from +ITRF2008/IGS08 to ETRS89 for maritime applications" +------------------------------------------------------------------------------- +operation proj=helmert ellps=GRS80 \ + x=0.67678 y=0.65495 z=-0.52827 \ + rx=-0.022742 ry=0.012667 rz=0.022704 s=-0.01070 +------------------------------------------------------------------------------- +tolerance 1 um +accept 3565285.00000000 855949.00000000 5201383.00000000 +expect 3565285.41342351 855948.67986759 5201382.72939791 +------------------------------------------------------------------------------- +This example is a random point, transformed from ED50 to ETRS89 using KMStrans2 +------------------------------------------------------------------------------- +operation proj=helmert ellps=GRS80 \ + x=-81.0703 y=-89.3603 z=-115.7526 \ + rx=-0.48488 ry=-0.02436 rz=-0.41321 s=-0.540645 +------------------------------------------------------------------------------- +tolerance 1 um +accept 3494994.30120000 1056601.97250000 5212382.16660000 +expect 3494909.84026368 1056506.78938633 5212265.66699761 +------------------------------------------------------------------------------- +This example is a coordinate from the geodetic observatory in Onsala, +Sweden transformed from ITRF2000 @ 2017.0 to ITRF93 @ 2017.0. + +The test coordinate was transformed using GNSStrans, using transformation +parameters published by ITRF: ftp://itrf.ensg.ign.fr/pub/itrf/ITRF.TP +------------------------------------------------------------------------------- +operation proj=helmert ellps=GRS80 \ + x=0.0127 y=0.0065 z=-0.0209 s=0.00195 \ + dx=-0.0029 dy=-0.0002 dz=-0.0006 ds=0.00001 \ + rx=-0.00039 ry=0.00080 rz=-0.00114 \ + drx=-0.00011 dry=-0.00019 drz=0.00007 \ + epoch=1988.0 tobs=2017.0 transpose +------------------------------------------------------------------------------- +tolerance 0.03 mm +accept 3370658.37800 711877.31400 5349787.08600 2017.0 # ITRF2000@2017.0 +expect 3370658.18890 711877.42370 5349787.12430 2017.0 # ITRF93@2017.0 +------------------------------------------------------------------------------- +This example is from "A mathematical relationship between NAD27 and NAD83 (91) +State Plane coordinates in Southeastern Wisconsin": +http://www.sewrpc.org/SEWRPCFiles/Publications/TechRep/tr-034-Mathematical-Relationship-Between-NAD27-and-NAD83-91-State-Plane-Coordinates-Southeastern-Wisconsin.pdf + +The test data is taken from p. 29. Here we are using point 203 and converting it +from NAD27 (ft) -> NAD83 (m). The paper reports a difference of 0.0014 m from +measured to computed coordinates, hence the test tolerance is set accordingly. +------------------------------------------------------------------------------- +operation proj=helmert ellps=GRS80 \ + x=-9597.3572 y=.6112 \ + s=0.304794780637 theta=-1.244048 +------------------------------------------------------------------------------- +tolerance 1 mm +accept 2546506.957 542256.609 0 +expect 766563.675 165282.277 0 +------------------------------------------------------------------------------- +Finally test the 4D-capabilities of the proj.h API, especially that the +rotation matrix is updated when necessary. + +Test coordinates from GNSStrans. +------------------------------------------------------------------------------- +operation proj=helmert ellps=GRS80 \ + x=0.01270 y=0.00650 z=-0.0209 s=0.00195 \ + dx=-0.0029 dy=-0.0002 dz=-0.0006 ds=0.00001 \ + rx=-0.00039 ry=0.00080 rz=-0.00114 \ + drx=-0.00011 dry=-0.00019 drz=0.00007 \ + epoch=1988.0 transpose +------------------------------------------------------------------------------- +tolerance 0.1 mm +accept 3370658.378 711877.314 5349787.086 2017.0 +expect 3370658.18890 711877.42370 5349787.12430 2017.0 +accept 3370658.378 711877.314 5349787.086 2018.0 +expect 3370658.18087 711877.42750 5349787.12648 2018.0 + + + +------------------------------------------------------------------------------- +builtins +------------------------------------------------------------------------------- + + + +END + diff --git a/travis/before_install.sh b/travis/before_install.sh index 249cb591..ccf59936 100755 --- a/travis/before_install.sh +++ b/travis/before_install.sh @@ -14,7 +14,6 @@ # What is the current python setup? which python python --version -python3 --version which pip pip --version diff --git a/travis/install.sh b/travis/install.sh index 51a8ea2f..049669d4 100755 --- a/travis/install.sh +++ b/travis/install.sh @@ -80,8 +80,11 @@ if [ $TRAVIS_OS_NAME == "osx" ]; then fi make -j3 make check -PROJ_LIB=$GRIDDIR ./src/proj -VC - +PROJ_LIB=$GRIDDIR ./src/gie ./test/gie/builtins.gie +PROJ_LIB=$GRIDDIR ./src/gie ./test/gie/more_builtins.gie +PROJ_LIB=$GRIDDIR ./src/gie ./test/gie/deformation.gie +PROJ_LIB=$GRIDDIR ./src/gie ./test/gie/axisswap.gie + # install & run the working GIGS test # create locations that pyproj understands ln -s src include diff --git a/travis/osx/before_install.sh b/travis/osx/before_install.sh index 4ca62084..17c0e141 100755 --- a/travis/osx/before_install.sh +++ b/travis/osx/before_install.sh @@ -4,5 +4,5 @@ set -e ./travis/before_install.sh +brew update brew install ccache -brew install python3 |
