diff options
| author | Even Rouault <even.rouault@mines-paris.org> | 2018-12-03 17:20:48 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-12-03 17:20:48 +0100 |
| commit | d0506e19a71888f7f0c3aa8618d919624e754c4d (patch) | |
| tree | 4468cd5ef29f3f7f6ce2ed950b5d1938cfbf84b5 /test | |
| parent | 4794d755a8dea4f4501c61e896e1829bb720e69a (diff) | |
| parent | ba111ac8323ff194039a06db87d1fb17ed8175b3 (diff) | |
| download | PROJ-d0506e19a71888f7f0c3aa8618d919624e754c4d.tar.gz PROJ-d0506e19a71888f7f0c3aa8618d919624e754c4d.zip | |
Merge pull request #1182 from rouault/plug_new_code
Remove data/epsg, IGNF and esri.* files / support legacy +init=epsg:XXXX syntax
Diffstat (limited to 'test')
| -rw-r--r-- | test/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | test/Makefile.am | 2 | ||||
| -rw-r--r-- | test/cli/CMakeLists.txt (renamed from test/old/CMakeLists.txt) | 0 | ||||
| -rw-r--r-- | test/cli/Makefile.am (renamed from test/old/Makefile.am) | 13 | ||||
| -rw-r--r-- | test/cli/ntv2_out.dist (renamed from test/old/ntv2_out.dist) | 0 | ||||
| -rw-r--r-- | test/cli/pj_out27.dist (renamed from test/old/pj_out27.dist) | 0 | ||||
| -rw-r--r-- | test/cli/pj_out83.dist (renamed from test/old/pj_out83.dist) | 0 | ||||
| -rw-r--r-- | test/cli/proj_outIGNF.dist (renamed from test/old/proj_outIGNF.dist) | 42 | ||||
| -rw-r--r-- | test/cli/td_out.dist (renamed from test/old/td_out.dist) | 0 | ||||
| -rwxr-xr-x | test/cli/test27 (renamed from test/old/test27) | 4 | ||||
| -rwxr-xr-x | test/cli/test83 (renamed from test/old/test83) | 4 | ||||
| -rwxr-xr-x | test/cli/testIGNF (renamed from test/old/testIGNF) | 16 | ||||
| -rwxr-xr-x | test/cli/testdatumfile (renamed from test/old/testdatumfile) | 8 | ||||
| -rwxr-xr-x | test/cli/testflaky (renamed from test/old/testflaky) | 4 | ||||
| -rwxr-xr-x | test/cli/testntv2 (renamed from test/old/testntv2) | 4 | ||||
| -rwxr-xr-x | test/cli/testprojinfo | 67 | ||||
| -rw-r--r-- | test/cli/testprojinfo_out.dist | 480 | ||||
| -rwxr-xr-x | test/cli/testvarious (renamed from test/old/testvarious) | 28 | ||||
| -rw-r--r-- | test/cli/tf_out.dist (renamed from test/old/tf_out.dist) | 0 | ||||
| -rw-r--r-- | test/cli/tv_out.dist (renamed from test/old/tv_out.dist) | 12 | ||||
| -rw-r--r-- | test/gie/4D-API_cs2cs-style.gie | 2 | ||||
| -rw-r--r-- | test/gie/more_builtins.gie | 10 | ||||
| -rw-r--r-- | test/gigs/5101.1-jhs.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5101.2-jhs.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5101.3-jhs.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5101.4-jhs-etmerc.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5102.1.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5103.1.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5103.2.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5103.3.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5105.2.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5106.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5107.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5109.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5111.1.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5112.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5113.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5201.gie | 2 | ||||
| -rw-r--r-- | test/gigs/5208.gie | 2 | ||||
| -rw-r--r-- | test/gigs/Makefile.am | 2 | ||||
| -rw-r--r-- | test/unit/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | test/unit/Makefile.am | 26 | ||||
| -rw-r--r-- | test/unit/basic_test.cpp | 44 | ||||
| -rw-r--r-- | test/unit/gie_self_tests.cpp | 664 | ||||
| -rw-r--r-- | test/unit/main.cpp | 8 | ||||
| -rw-r--r-- | test/unit/pj_phi2_test.cpp | 3 | ||||
| -rw-r--r-- | test/unit/pj_transform_test.cpp | 583 | ||||
| -rw-r--r-- | test/unit/proj_errno_string_test.cpp | 18 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 1032 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 328 | ||||
| -rw-r--r-- | test/unit/test_factory.cpp | 17 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 335 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 221 |
53 files changed, 3496 insertions, 533 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ae3d6bf4..c46ad5d7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,5 +52,5 @@ proj_add_gie_test("GIGS-5208" "gigs/5208.gie") # ${TEST_MAIN_SRC} # ${CATCH2_INCLUDE} ) -add_subdirectory(old) +add_subdirectory(cli) add_subdirectory(unit) diff --git a/test/Makefile.am b/test/Makefile.am index 428e1650..b65e9785 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -7,4 +7,4 @@ EXTRA_DIST = CMakeLists.txt # libtestmain_la_LDFLAGS = -no-undefined # libtestmain_la_SOURCES = test_main.cpp -SUBDIRS = old googletest . gie gigs unit +SUBDIRS = cli googletest . gie gigs unit diff --git a/test/old/CMakeLists.txt b/test/cli/CMakeLists.txt index d197b2aa..d197b2aa 100644 --- a/test/old/CMakeLists.txt +++ b/test/cli/CMakeLists.txt diff --git a/test/old/Makefile.am b/test/cli/Makefile.am index 2848d40a..3650a9a8 100644 --- a/test/old/Makefile.am +++ b/test/cli/Makefile.am @@ -1,9 +1,10 @@ # Executables paths passed to test scripts DATAPATH = ../../data -THIS_DIR = $(top_srcdir)/test/old +THIS_DIR = $(top_srcdir)/test/cli EXEPATH = ../../src PROJEXE = $(EXEPATH)/proj CS2CSEXE = $(EXEPATH)/cs2cs +PROJINFOEXE = $(EXEPATH)/projinfo # PROJ.4 test scripts TEST27 = $(THIS_DIR)/test27 @@ -13,18 +14,23 @@ TESTVARIOUS = $(THIS_DIR)/testvarious TESTFLAKY = $(THIS_DIR)/testflaky TESTDATUMFILE = $(THIS_DIR)/testdatumfile TESTIGN = $(THIS_DIR)/testIGNF +TESTPROJINFO = $(THIS_DIR)/testprojinfo EXTRA_DIST = pj_out27.dist pj_out83.dist td_out.dist \ test27 test83 tv_out.dist tf_out.dist \ testflaky testvarious testdatumfile testntv2 ntv2_out.dist \ testIGNF proj_outIGNF.dist \ + testprojinfo testprojinfo_out.dist \ CMakeLists.txt -check-local: +testprojinfo-check: + PROJ_LIB=$(DATAPATH) $(TESTPROJINFO) $(PROJINFOEXE) + +check-local: testprojinfo-check $(TEST27) $(PROJEXE) $(TEST83) $(PROJEXE) PROJ_LIB=$(DATAPATH) $(TESTVARIOUS) $(CS2CSEXE) - @if [ -f $(DATAPATH)/conus ] ; then \ + @if [ -f $(DATAPATH)/conus -a -f $(DATAPATH)/ntv1_can.dat -a -f $(DATAPATH)/MD -a -f $(DATAPATH)/ntf_r93.dat ]; then \ PROJ_LIB=$(DATAPATH) $(TESTDATUMFILE) $(CS2CSEXE) ; \ fi @if [ -f $(DATAPATH)/ntf_r93.gsb ] ; then \ @@ -33,3 +39,4 @@ check-local: @if [ -f $(DATAPATH)/ntv2_0.gsb ] ; then \ PROJ_LIB=$(DATAPATH) $(TESTNTV2) $(CS2CSEXE) ; \ fi + diff --git a/test/old/ntv2_out.dist b/test/cli/ntv2_out.dist index 5ce26e6e..5ce26e6e 100644 --- a/test/old/ntv2_out.dist +++ b/test/cli/ntv2_out.dist diff --git a/test/old/pj_out27.dist b/test/cli/pj_out27.dist index 632dfc62..632dfc62 100644 --- a/test/old/pj_out27.dist +++ b/test/cli/pj_out27.dist diff --git a/test/old/pj_out83.dist b/test/cli/pj_out83.dist index 726140f3..726140f3 100644 --- a/test/old/pj_out83.dist +++ b/test/cli/pj_out83.dist diff --git a/test/old/proj_outIGNF.dist b/test/cli/proj_outIGNF.dist index 45112f60..611144b8 100644 --- a/test/old/proj_outIGNF.dist +++ b/test/cli/proj_outIGNF.dist @@ -1,24 +1,24 @@ -+init=./IGNF:NTFG +to +init=./IGNF:RGF93G ++init=IGNF:NTFG +to +init=IGNF:RGF93G 3.300866856 43.4477976569 0.0000 3d18'0.915"E 43d26'52.077"N 0.000 -+init=./IGNF:LAMBE +to +init=./IGNF:LAMB93 - 600000.0000 2600545.4523 0.0000 652760.737 7033791.243 0.000 - 135638.3592 2418760.4094 0.0000 187194.062 6855928.882 0.000 - 998137.3947 2413822.2844 0.0000 1049052.258 6843776.562 0.000 ++init=IGNF:LAMBE +to +init=IGNF:LAMB93 + 600000.0000 2600545.4523 0.0000 652759.036 7033588.609 0.000 + 135638.3592 2418760.4094 0.0000 187444.148 6856142.911 0.000 + 998137.3947 2413822.2844 0.0000 1048843.997 6843923.913 0.000 600000.0000 2200000.0000 0.0000 649398.872 6633524.191 0.000 - 311552.5340 1906457.4840 0.0000 358799.172 6342652.486 0.000 - 960488.4138 1910172.8812 0.0000 1007068.686 6340907.237 0.000 - 600000.0000 1699510.8340 0.0000 645204.279 6133556.746 0.000 -1203792.5981 626873.17210 0.0000 1238875.764 5057405.016 0.000 -+init=./IGNF:LAMBE +to +init=./IGNF:GEOPORTALFXX - 600000.0000 2600545.4523 0.0000 179040.148 5610495.275 0.000 - 135638.3592 2418760.4094 0.0000 -303729.363 5410118.356 0.000 - 998137.3947 2413822.2844 0.0000 592842.792 5410120.554 0.000 + 311552.5340 1906457.4840 0.0000 358593.374 6342647.465 0.000 + 960488.4138 1910172.8812 0.0000 1007324.119 6340956.093 0.000 + 600000.0000 1699510.8340 0.0000 645201.753 6133255.515 0.000 +1203792.5981 626873.17210 0.0000 * * inf ++init=IGNF:LAMBE +to +init=IGNF:GEOPORTALFXX + 600000.0000 2600545.4523 0.0000 179040.150 5610292.766 0.000 + 135638.3592 2418760.4094 0.0000 -303490.059 5410353.890 0.000 + 998137.3947 2413822.2844 0.0000 592635.926 5410280.335 0.000 600000.0000 2200000.0000 0.0000 179041.670 5209746.080 0.000 - 311552.5340 1906457.4840 0.0000 -96825.465 4909184.136 0.000 - 960488.4138 1910172.8812 0.0000 523880.019 4909191.141 0.000 - 600000.0000 1699510.8340 0.0000 179047.633 4708817.007 0.000 -1203792.5981 626873.17210 0.0000 658287.395 3623739.237 0.000 -+init=./IGNF:RGF93G +to +init=./IGNF:GEOPORTALFXX + 311552.5340 1906457.4840 0.0000 -97021.878 4909167.981 0.000 + 960488.4138 1910172.8812 0.0000 524126.466 4909227.598 0.000 + 600000.0000 1699510.8340 0.0000 179047.637 4708515.623 0.000 +1203792.5981 626873.17210 0.0000 * * inf ++init=IGNF:RGF93G +to +init=IGNF:GEOPORTALFXX 2d20'11.4239243" 50d23'59.7718445" 0.0 179040.151 5610495.281 0.000 -3d57'49.4051448" 48d35'59.7121716" 0.0 -303729.365 5410118.352 0.000 7d44'12.1439796" 48d35'59.7832558" 0.0 592842.794 5410120.550 0.000 @@ -27,7 +27,7 @@ 6d50'12.2276489" 44d06'00.0517019" 0.0 523880.022 4909191.143 0.000 2d20'11.7754730" 42d18'00.0824436" 0.0 179047.634 4708817.010 0.000 9d32'12.6680218" 41d24'00.3542556" 0.0 730783.054 4608637.873 0.000 -+init=./IGNF:RGF93G +to +init=./IGNF:MILLER ++init=IGNF:RGF93G +to +init=IGNF:MILLER 2d20'11.4239243" 50d23'59.7718445" 0.0 260098.730 6140682.441 0.000 -3d57'49.4051448" 48d35'59.7121716" 0.0 -441239.699 5880610.004 0.000 7d44'12.1439796" 48d35'59.7832558" 0.0 861246.246 5880612.827 0.000 @@ -36,5 +36,5 @@ 6d50'12.2276489" 44d06'00.0517019" 0.0 761061.291 5252498.745 0.000 2d20'11.7754730" 42d18'00.0824436" 0.0 260109.601 5009175.714 0.000 9d32'12.6680218" 41d24'00.3542556" 0.0 1061637.534 4889066.592 0.000 -+init=./IGNF:RGR92 +to +init=./IGNF:REUN47 -3356123.5400 1303218.3090 5247430.6050 3353421.833 1304074.314 5248935.607 ++init=IGNF:RGR92 +to +init=IGNF:REUN47 +3356123.5400 1303218.3090 5247430.6050 3353420.949 1304075.021 5248935.144 diff --git a/test/old/td_out.dist b/test/cli/td_out.dist index f6b2a219..f6b2a219 100644 --- a/test/old/td_out.dist +++ b/test/cli/td_out.dist diff --git a/test/old/test27 b/test/cli/test27 index 3b62855a..43c060d8 100755 --- a/test/old/test27 +++ b/test/cli/test27 @@ -6,7 +6,7 @@ # Proj will vary in the .001ft range with projections using Transverse # Mercator due to greater precision of meridional distance function. # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -833,7 +833,7 @@ EOF # # do 'diff' with distribution results echo "diff ${OUT} with pj_out27.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/pj_out27.dist +diff -b ${OUT} ${TEST_CLI_DIR}/pj_out27.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/test83 b/test/cli/test83 index 02f99d5f..82b491a7 100755 --- a/test/old/test83 +++ b/test/cli/test83 @@ -7,7 +7,7 @@ # Proj will vary in the .001ft range with projections using Transverse # Mercator due to greater precision of meridional distance function. # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -714,7 +714,7 @@ EOF # # do 'diff' with distribution results echo "diff ${OUT} with pj_out83.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/pj_out83.dist +diff -b ${OUT} ${TEST_CLI_DIR}/pj_out83.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/testIGNF b/test/cli/testIGNF index f785641e..0fa04e84 100755 --- a/test/old/testIGNF +++ b/test/cli/testIGNF @@ -11,7 +11,7 @@ # 2009-10-04 : addition of NTFG to RGF93G test to check if # the gsb grid is still ok -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -41,13 +41,7 @@ echo "============================================" OUT=proj_outIGNF -REMOVE_IGNF=NO -if test ! -f IGNF; then - cp ${PROJ_LIB}/IGNF . - REMOVE_IGNF=YES -fi - -INIT_FILE=./IGNF +INIT_FILE=IGNF RES="-f %.3f" # echo "doing tests into file ${OUT}, please wait" @@ -162,14 +156,10 @@ $EXE +init=${INIT_FILE}:RGR92 +to +init=${INIT_FILE}:REUN47 -E $RES >>${OUT} <<E 3356123.5400 1303218.3090 5247430.6050 EOF -if test "${REMOVE_IGNF}" = "YES"; then - rm ./IGNF -fi - # # do 'diff' with distribution results echo "diff ${OUT} with ${OUT}.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/${OUT}.dist +diff -b ${OUT} ${TEST_CLI_DIR}/${OUT}.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/testdatumfile b/test/cli/testdatumfile index 6cd25b76..55900427 100755 --- a/test/old/testdatumfile +++ b/test/cli/testdatumfile @@ -3,7 +3,7 @@ # files that are not always available. # # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -77,7 +77,7 @@ echo "edge or even a wee bit outside (#141)." >> ${OUT} # Our test points are (1) right on mesh corner, (2) outside but within # epsilon (3) inside a bit (4) outside by more than epsilon # -$EXE +proj=latlong +ellps=WGS84 +nadgrids=ntf_r93.gsb \ +$EXE +proj=latlong +ellps=WGS84 +nadgrids=ntf_r93.gsb,null \ +to +proj=latlong +datum=WGS84 \ -E -f "%.12f" >>${OUT} <<EOF -5.5 52.0 @@ -87,7 +87,7 @@ $EXE +proj=latlong +ellps=WGS84 +nadgrids=ntf_r93.gsb \ EOF # $EXE +proj=latlong +datum=WGS84 \ - +to +proj=latlong +ellps=WGS84 +nadgrids=ntf_r93.gsb \ + +to +proj=latlong +ellps=WGS84 +nadgrids=ntf_r93.gsb,null \ -E -f "%.12f" >>${OUT} <<EOF -5.5 52.0 -5.5000000000001 52.0000000000001 @@ -99,7 +99,7 @@ EOF # Done! # do 'diff' with distribution results echo "diff ${OUT} with ${OUT}.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/${OUT}.dist +diff -b ${OUT} ${TEST_CLI_DIR}/${OUT}.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/testflaky b/test/cli/testflaky index ccb9dfd5..af56a9cd 100755 --- a/test/old/testflaky +++ b/test/cli/testflaky @@ -3,7 +3,7 @@ # on datum files. # # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -59,7 +59,7 @@ EOF # Done! # do 'diff' with distribution results echo "diff ${OUT} with ${OUT}.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/${OUT}.dist +diff -b ${OUT} ${TEST_CLI_DIR}/${OUT}.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/testntv2 b/test/cli/testntv2 index a0867789..e82026fc 100755 --- a/test/old/testntv2 +++ b/test/cli/testntv2 @@ -3,7 +3,7 @@ # Test NTv2 (.gsb) support. Assumes ntv2_0.gsb is installed. # # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -58,7 +58,7 @@ EOF # Done! # do 'diff' with distribution results echo "diff ${OUT} with ${OUT}.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/${OUT}.dist +diff -b ${OUT} ${TEST_CLI_DIR}/${OUT}.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo new file mode 100755 index 00000000..ad62d1da --- /dev/null +++ b/test/cli/testprojinfo @@ -0,0 +1,67 @@ +: +# Test projinfo + +TEST_CLI_DIR=`dirname $0` +DATA_DIR=`dirname $0`/../../data +EXE=$1 + +usage() +{ + echo "Usage: ${0} <path to 'projinfo' program>" + echo + exit 1 +} + +if test -z "${EXE}"; then + EXE=../../src/projinfo +fi + +if test ! -x ${EXE}; then + echo "*** ERROR: Can not find '${EXE}' program!" + exit 1 +fi + +echo "============================================" +echo "Running ${0} using ${EXE}:" +echo "============================================" + +OUT=testprojinfo_out + +rm -f ${OUT} + +echo "Testing projinfo EPSG:4326" >> ${OUT} +$EXE EPSG:4326 >>${OUT} +echo "" >>${OUT} + +echo "Testing projinfo -o ALL EPSG:4326" >> ${OUT} +$EXE -o ALL EPSG:4326 >>${OUT} +echo "" >>${OUT} + +echo "Testing projinfo -s EPSG:4326 -t EPSG:32631" >> ${OUT} +$EXE -s EPSG:4326 -t EPSG:32631 >>${OUT} +echo "" >>${OUT} + +echo "Testing projinfo -s NAD27 -t NAD83 --grid-check none --spatial-test intersects --summary" >> ${OUT} +$EXE -s NAD27 -t NAD83 --grid-check none --spatial-test intersects --summary >>${OUT} +echo "" >>${OUT} + +echo "Testing projinfo -s NAD27 -t NAD83 --grid-check none --spatial-test intersects" >> ${OUT} +$EXE -s NAD27 -t NAD83 --grid-check none --spatial-test intersects >>${OUT} +echo "" >>${OUT} + +# do 'diff' with distribution results +echo "diff ${OUT} with testprojinfo_out.dist" +diff -u ${OUT} ${TEST_CLI_DIR}/testprojinfo_out.dist +if [ $? -ne 0 ] ; then + echo "" + echo "PROBLEMS HAVE OCCURRED" + echo "test file ${OUT} saved" + echo + exit 100 +else + echo "TEST OK" + echo "test file ${OUT} removed" + echo + /bin/rm -f ${OUT} + exit 0 +fi diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist new file mode 100644 index 00000000..fea5a299 --- /dev/null +++ b/test/cli/testprojinfo_out.dist @@ -0,0 +1,480 @@ +Testing projinfo EPSG:4326 +PROJ string: ++proj=pipeline +step +proj=longlat +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +GEODCRS["WGS 84", + DATUM["World Geodetic System 1984", + ELLIPSOID["WGS 84",6378137,298.257223563, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + AREA["World"], + BBOX[-90,-180,90,180], + ID["EPSG",4326]] + +Testing projinfo -o ALL EPSG:4326 +PROJ string: ++proj=pipeline +step +proj=longlat +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +PROJ.4 string: ++proj=longlat +datum=WGS84 +no_defs + +WKT2_2015 string: +GEODCRS["WGS 84", + DATUM["World Geodetic System 1984", + ELLIPSOID["WGS 84",6378137,298.257223563, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + AREA["World"], + BBOX[-90,-180,90,180], + ID["EPSG",4326]] + +WKT2_2018 string: +GEOGCRS["WGS 84", + DATUM["World Geodetic System 1984", + ELLIPSOID["WGS 84",6378137,298.257223563, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + USAGE[ + SCOPE["unknown"], + AREA["World"], + BBOX[-90,-180,90,180]], + ID["EPSG",4326]] + +WKT1_GDAL: +GEOGCS["WGS 84", + DATUM["WGS_1984", + SPHEROID["WGS 84",6378137,298.257223563, + AUTHORITY["EPSG","7030"]], + AUTHORITY["EPSG","6326"]], + PRIMEM["Greenwich",0, + AUTHORITY["EPSG","8901"]], + UNIT["degree",0.0174532925199433, + AUTHORITY["EPSG","9122"]], + AUTHORITY["EPSG","4326"]] + + +WKT1_ESRI: +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] + + +Testing projinfo -s EPSG:4326 -t EPSG:32631 +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=utm +zone=31 +ellps=WGS84 + +WKT2_2015 string: +CONVERSION["UTM zone 31N", + METHOD["Transverse Mercator", + ID["EPSG",9807]], + PARAMETER["Latitude of natural origin",0, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8801]], + PARAMETER["Longitude of natural origin",3, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8802]], + PARAMETER["Scale factor at natural origin",0.9996, + SCALEUNIT["unity",1], + ID["EPSG",8805]], + PARAMETER["False easting",500000, + LENGTHUNIT["metre",1], + ID["EPSG",8806]], + PARAMETER["False northing",0, + LENGTHUNIT["metre",1], + ID["EPSG",8807]], + ID["EPSG",16031]] + +Testing projinfo -s NAD27 -t NAD83 --grid-check none --spatial-test intersects --summary +Candidate operations found: 8 +DERIVED_FROM(EPSG):1312, NAD27 to NAD83 (3), 1.0 m, Canada +DERIVED_FROM(EPSG):1313, NAD27 to NAD83 (4), 1.5 m, Canada - NAD27 +DERIVED_FROM(EPSG):1241, NAD27 to NAD83 (1), 0.15 m, USA - CONUS including EEZ +DERIVED_FROM(EPSG):1243, NAD27 to NAD83 (2), 0.5 m, USA - Alaska including EEZ +ESRI:108003, NAD_1927_To_NAD_1983_PR_VI, 0.05 m, Caribbean - Puerto Rico and Virgin Islands - onshore +unknown id, Null geographic offset from NAD27 to NAD83, unknown accuracy, World +EPSG:1462, NAD27 to NAD83 (5), 1.0 m, Canada - Quebec +EPSG:1573, NAD27 to NAD83 (6), 1.5 m, Canada - Quebec + +Testing projinfo -s NAD27 -t NAD83 --grid-check none --spatial-test intersects +------------------------------------- +Operation n°1: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=ntv1_can.dat +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (3)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["NTv1", + ID["EPSG",9614]], + PARAMETERFILE["Latitude and longitude difference file","ntv1_can.dat"], + OPERATIONACCURACY[1.0], + AREA["Canada"], + BBOX[40.04,-141.01,86.46,-47.74], + ID["DERIVED_FROM(EPSG)",1312]] + +------------------------------------- +Operation n°2: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=ntv2_0.gsb +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (4)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["NTv2", + ID["EPSG",9615]], + PARAMETERFILE["Latitude and longitude difference file","ntv2_0.gsb"], + OPERATIONACCURACY[1.5], + AREA["Canada - NAD27"], + BBOX[40.04,-141.01,83.17,-47.74], + ID["DERIVED_FROM(EPSG)",1313]] + +------------------------------------- +Operation n°3: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=conus +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (1)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["CTABLE2"], + PARAMETERFILE["Latitude and longitude difference file","conus"], + OPERATIONACCURACY[0.15], + AREA["USA - CONUS including EEZ"], + BBOX[23.81,-129.17,49.38,-65.69], + ID["DERIVED_FROM(EPSG)",1241]] + +------------------------------------- +Operation n°4: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=alaska +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (2)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["CTABLE2"], + PARAMETERFILE["Latitude and longitude difference file","alaska"], + OPERATIONACCURACY[0.5], + AREA["USA - Alaska including EEZ"], + BBOX[47.88,167.65,74.71,-129.99], + ID["DERIVED_FROM(EPSG)",1243]] + +------------------------------------- +Operation n°5: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=prvi +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD_1927_To_NAD_1983_PR_VI", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["NTv2", + ID["EPSG",9615]], + PARAMETERFILE["Latitude and longitude difference file","prvi"], + OPERATIONACCURACY[0.05], + AREA["Caribbean - Puerto Rico and Virgin Islands - onshore"], + BBOX[17.62,-67.97,18.78,-64.25], + ID["ESRI",108003]] + +------------------------------------- +Operation n°6: + +PROJ string: + + +WKT2_2015 string: +COORDINATEOPERATION["Null geographic offset from NAD27 to NAD83", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + AREA["North America - NAD27"], + BBOX[7.15,167.65,83.17,-47.74], + ID["EPSG",4267]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]], + AREA["North America - NAD83"], + BBOX[14.92,167.65,86.46,-47.74], + ID["EPSG",4269]]], + METHOD["Geographic2D offsets", + ID["EPSG",9619]], + PARAMETER["Latitude offset",0, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8601]], + PARAMETER["Longitude offset",0, + ANGLEUNIT["degree",0.0174532925199433], + ID["EPSG",8602]], + AREA["World"], + BBOX[-90,-180,90,180]] + +------------------------------------- +Operation n°7: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=GS2783v1.QUE +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (5)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["NTv1", + ID["EPSG",9614]], + PARAMETERFILE["Latitude and longitude difference file","GS2783v1.QUE"], + OPERATIONACCURACY[1.0], + AREA["Canada - Quebec"], + BBOX[44.99,-79.85,62.62,-57.1], + ID["EPSG",1462]] + +------------------------------------- +Operation n°8: + +PROJ string: ++proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift +grids=QUE27-83.gsb +step +proj=unitconvert +xy_in=rad +xy_out=deg +step +proj=axisswap +order=2,1 + +WKT2_2015 string: +COORDINATEOPERATION["NAD27 to NAD83 (6)", + SOURCECRS[ + GEODCRS["NAD27", + DATUM["North American Datum 1927", + ELLIPSOID["Clarke 1866",6378206.4,294.978698213898, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + TARGETCRS[ + GEODCRS["NAD83", + DATUM["North American Datum 1983", + ELLIPSOID["GRS 1980",6378137,298.257222101, + LENGTHUNIT["metre",1]]], + PRIMEM["Greenwich",0, + ANGLEUNIT["degree",0.0174532925199433]], + CS[ellipsoidal,2], + AXIS["geodetic latitude (Lat)",north, + ORDER[1], + ANGLEUNIT["degree",0.0174532925199433]], + AXIS["geodetic longitude (Lon)",east, + ORDER[2], + ANGLEUNIT["degree",0.0174532925199433]]]], + METHOD["NTv2", + ID["EPSG",9615]], + PARAMETERFILE["Latitude and longitude difference file","QUE27-83.gsb"], + OPERATIONACCURACY[1.5], + AREA["Canada - Quebec"], + BBOX[44.99,-79.85,62.62,-57.1], + ID["EPSG",1573]] + diff --git a/test/old/testvarious b/test/cli/testvarious index dbaeb0ce..88673c5d 100755 --- a/test/old/testvarious +++ b/test/cli/testvarious @@ -3,7 +3,7 @@ # on datum files. # # -TEST_OLD_DIR=`dirname $0` +TEST_CLI_DIR=`dirname $0` DATA_DIR=`dirname $0`/../../data EXE=$1 @@ -523,7 +523,7 @@ EOF # echo "##############################################################" >> ${OUT} echo "Test the Natural Earth Projection" >> ${OUT} -$EXE +proj=latlong +a=1 +lon_0=0 \ +$EXE +proj=latlong +a=6371008.7714 +b=6371008.7714 \ +to +proj=natearth +a=6371008.7714 +b=6371008.7714 -f '%.'7'f' \ -E >>${OUT} <<EOF 0.0 0.0 0 0.0 0.0 @@ -554,7 +554,7 @@ $EXE +proj=latlong +a=1 +lon_0=0 \ EOF echo "##############################################################" >> ${OUT} echo "Test the Natural Earth II Projection" >> ${OUT} -$EXE +proj=latlong +a=1 +lon_0=0 \ +$EXE +proj=latlong +a=6371008.7714 +b=6371008.7714 \ +to +proj=natearth2 +a=6371008.7714 +b=6371008.7714 -f '%.'7'f' \ -E >>${OUT} <<EOF 0.0 0.0 0 0.00000000 0.00000000 @@ -585,7 +585,7 @@ $EXE +proj=latlong +a=1 +lon_0=0 \ EOF echo "##############################################################" >> ${OUT} echo "Test the Compact Miller projection" >> ${OUT} -$EXE +proj=latlong +a=1 +lon_0=0 \ +$EXE +proj=latlong +a=6371008.7714 +b=6371008.7714 \ +to +proj=comill +a=6371008.7714 +b=6371008.7714 -f '%.'7'f' \ -E >>${OUT} <<EOF 0.0 0.0 0 0.0 0.0 @@ -656,14 +656,14 @@ EOF echo "##############################################################" >> ${OUT} echo "Check inverse error handling with ob_tran (#225)" >> ${OUT} $EXE +proj=ob_tran \ - +o_proj=moll +a=6378137 +es=0 +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 \ + +o_proj=moll +a=6378137 +es=0 +o_lon_p=0 +o_lat_p=0 +lon_0=180 \ -E >>${OUT} <<EOF 300000 400000 20000000 30000000 EOF echo "Test inverse handling" >> ${OUT} $EXE -I +proj=ob_tran \ - +o_proj=moll +a=6378137 +es=0 +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 \ + +o_proj=moll +a=6378137 +es=0 +o_lon_p=0 +o_lat_p=0 +lon_0=180 \ -E >>${OUT} <<EOF 10 20 EOF @@ -939,11 +939,25 @@ $EXE -f '%0.3f' \ 0 0 1000 EOF +echo "##############################################################" >> ${OUT} +echo "Test EPSG:4326 to EPSG:32631" >> ${OUT} +# Input is latitude, longitude order +$EXE EPSG:4326 +to EPSG:32631 -E >> ${OUT} <<EOF +49 3 0 +EOF + +echo "##############################################################" >> ${OUT} +echo "Test EPSG:32631 to EPSG:4326" >> ${OUT} +# Input is latitude, longitude order +$EXE EPSG:32631 EPSG:4326 -E >> ${OUT} <<EOF +400000 5000000 0 +EOF + # Done! # do 'diff' with distribution results echo "diff ${OUT} with ${OUT}.dist" -diff -b ${OUT} ${TEST_OLD_DIR}/${OUT}.dist +diff -b ${OUT} ${TEST_CLI_DIR}/${OUT}.dist if [ $? -ne 0 ] ; then echo "" echo "PROBLEMS HAVE OCCURRED" diff --git a/test/old/tf_out.dist b/test/cli/tf_out.dist index 9f1778e7..9f1778e7 100644 --- a/test/old/tf_out.dist +++ b/test/cli/tf_out.dist diff --git a/test/old/tv_out.dist b/test/cli/tv_out.dist index 222c0c5f..148d413d 100644 --- a/test/old/tv_out.dist +++ b/test/cli/tv_out.dist @@ -139,7 +139,7 @@ Test healpix forward projection on ellipsoid 0 60.0 0.00000 3.35128 0.00000 0 -60.0 0.00000 -3.35128 0.00000 Test healpix inverse projection on ellipsoid -0 0.7853981633974483 * * 0.00000 +0 0.7853981633974483 * * inf -1.5707963267948966 0 -90.10072 0.00000 0.00000 0.0 0.0 0.00000 0.00000 0.00000 0.0 2.0547874222147415 0.00000 39.58811 0.00000 @@ -347,7 +347,7 @@ Test inverse calcofi projection ############################################################## Check inverse error handling with ob_tran (#225) 300000 400000 42d45'22.377"W 85d35'28.083"N 0.000 -20000000 30000000 * * 0.000 +20000000 30000000 * * inf Test inverse handling 10 20 -1384841.19 7581707.88 0.00 ############################################################## @@ -447,10 +447,16 @@ Test patterson inverse projection 20015114.352186374 -11409566.822831295 180.000 -90.000 0.000 ############################################################## Test Web Mercator to avoid issue #834 in the future -487147.594520173 4934316.46263998 -10370728.796 5552839.742 -0.000 +487147.594520173 4934316.46263998 -10370728.796 5552839.742 0.000 ############################################################## Test vto_meter 0 0 1 0.000 0.000 1000.000 0 0 1 0.000 0.000 1000.000 0 0 1000 0.000 0.000 1.000 0 0 1000 0.000 0.000 1.000 +############################################################## +Test EPSG:4326 to EPSG:32631 +49 3 0 500000.00 5427455.78 0.00 +############################################################## +Test EPSG:32631 to EPSG:4326 +400000 5000000 0 45d8'47.014"N 1d43'40.681"E 0.000 diff --git a/test/gie/4D-API_cs2cs-style.gie b/test/gie/4D-API_cs2cs-style.gie index 346f2d36..e653454e 100644 --- a/test/gie/4D-API_cs2cs-style.gie +++ b/test/gie/4D-API_cs2cs-style.gie @@ -207,6 +207,7 @@ expect failure ------------------------------------------------------------------------------- Test that Google's Web Mercator works as intended (see #834 for details). ------------------------------------------------------------------------------- +use_proj4_init_rules true operation proj=pipeline step init=epsg:26915 inv step init=epsg:3857 ------------------------------------------------------------------------------- tolerance 20 cm @@ -220,6 +221,7 @@ expect -10370728.80 5552839.74 0 ------------------------------------------------------------------------------- Test Google's Web Mercator with +proj=webmerc ------------------------------------------------------------------------------- +use_proj4_init_rules true operation proj=pipeline step init=epsg:26915 inv step proj=webmerc datum=WGS84 ------------------------------------------------------------------------------- tolerance 20 cm diff --git a/test/gie/more_builtins.gie b/test/gie/more_builtins.gie index 13b77b0a..63464998 100644 --- a/test/gie/more_builtins.gie +++ b/test/gie/more_builtins.gie @@ -166,6 +166,7 @@ expect 12 55 0 0 ------------------------------------------------------------------------------- Finally test a pipeline with more than one init step ------------------------------------------------------------------------------- +use_proj4_init_rules true operation proj=pipeline step init=epsg:25832 inv step init=epsg:25833 @@ -710,10 +711,13 @@ accept 0 0 0 0 expect failure ------------------------------------------------------------------------------- -run the few gie-builtin tests, which are currently either awkward or impossible -to express in the gie command set +# Test lon_wrap +operation +proj=longlat +ellps=WGS84 +lon_wrap=180 ------------------------------------------------------------------------------- -builtins +direction forward +accept -1 10 0 +expect 359 10 0 + ------------------------------------------------------------------------------- </gie> diff --git a/test/gigs/5101.1-jhs.gie b/test/gigs/5101.1-jhs.gie index 2fd98883..efef9fcf 100644 --- a/test/gigs/5101.1-jhs.gie +++ b/test/gigs/5101.1-jhs.gie @@ -6,6 +6,8 @@ Test 5101 (part 1), Transverse Mercator, v2-0_2011-06-28, recommended JHS formul <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4326 +inv diff --git a/test/gigs/5101.2-jhs.gie b/test/gigs/5101.2-jhs.gie index 7ea6275e..3f6218ba 100644 --- a/test/gigs/5101.2-jhs.gie +++ b/test/gigs/5101.2-jhs.gie @@ -6,6 +6,8 @@ Test 5101 (part 2), Transverse Mercator, v2-0_2011-06-28, recommended JHS formul <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4326 +inv diff --git a/test/gigs/5101.3-jhs.gie b/test/gigs/5101.3-jhs.gie index d588df4c..05b902be 100644 --- a/test/gigs/5101.3-jhs.gie +++ b/test/gigs/5101.3-jhs.gie @@ -6,6 +6,8 @@ Test 5101 (part 3), Transverse Mercator, v2-0_2011-06-28, recommended JHS formul <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4283 +inv diff --git a/test/gigs/5101.4-jhs-etmerc.gie b/test/gigs/5101.4-jhs-etmerc.gie index b97b7769..42aad560 100644 --- a/test/gigs/5101.4-jhs-etmerc.gie +++ b/test/gigs/5101.4-jhs-etmerc.gie @@ -6,6 +6,8 @@ Test 5101 (part 4), Transverse Mercator, v2-0_2011-06-28, recommended JHS formul <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4190 +inv diff --git a/test/gigs/5102.1.gie b/test/gigs/5102.1.gie index d3eef080..33bf3bac 100644 --- a/test/gigs/5102.1.gie +++ b/test/gigs/5102.1.gie @@ -6,6 +6,8 @@ Test 5102, Lambert Conic Conformal (1SP), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4230 +inv diff --git a/test/gigs/5103.1.gie b/test/gigs/5103.1.gie index c972b738..73b7d0ca 100644 --- a/test/gigs/5103.1.gie +++ b/test/gigs/5103.1.gie @@ -6,6 +6,8 @@ Test 5103 (part 1), Lambert Conic Conformal (2SP), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4313 +inv diff --git a/test/gigs/5103.2.gie b/test/gigs/5103.2.gie index 3975e9d8..b32c2758 100644 --- a/test/gigs/5103.2.gie +++ b/test/gigs/5103.2.gie @@ -6,6 +6,8 @@ Test 5103 (part 2), Lambert Conic Conformal (2SP), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4152 +inv diff --git a/test/gigs/5103.3.gie b/test/gigs/5103.3.gie index b8965132..d486ec04 100644 --- a/test/gigs/5103.3.gie +++ b/test/gigs/5103.3.gie @@ -6,6 +6,8 @@ Test 5103 (part 3), Lambert Conic Conformal (2SP), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4152 +inv diff --git a/test/gigs/5105.2.gie b/test/gigs/5105.2.gie index 190c9176..daf86433 100644 --- a/test/gigs/5105.2.gie +++ b/test/gigs/5105.2.gie @@ -6,6 +6,8 @@ Test 5105 (part 2), Oblique Mercator (variant B), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4237 +inv diff --git a/test/gigs/5106.gie b/test/gigs/5106.gie index 6c5940ef..9082c0e7 100644 --- a/test/gigs/5106.gie +++ b/test/gigs/5106.gie @@ -6,6 +6,8 @@ Test 5106, Hotine Oblique Mercator (variant A), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4742 +inv diff --git a/test/gigs/5107.gie b/test/gigs/5107.gie index f78e9c22..bfd044fd 100644 --- a/test/gigs/5107.gie +++ b/test/gigs/5107.gie @@ -6,6 +6,8 @@ Test 5107, American Polyconic, v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4674 +inv diff --git a/test/gigs/5109.gie b/test/gigs/5109.gie index a104e66f..da42109a 100644 --- a/test/gigs/5109.gie +++ b/test/gigs/5109.gie @@ -6,6 +6,8 @@ Test 5109, Albers Equal Area, v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4283 +inv diff --git a/test/gigs/5111.1.gie b/test/gigs/5111.1.gie index d146b36a..fcbd4b1a 100644 --- a/test/gigs/5111.1.gie +++ b/test/gigs/5111.1.gie @@ -12,6 +12,8 @@ Test 5111 (part 1), Mercator (variant A), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline towgs84=0,0,0 +step +init=epsg:4211 +inv diff --git a/test/gigs/5112.gie b/test/gigs/5112.gie index 207632d2..ab5c0be8 100644 --- a/test/gigs/5112.gie +++ b/test/gigs/5112.gie @@ -6,6 +6,8 @@ Test 5112, Mercator (variant B), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation proj=pipeline step init=epsg:4284 inv diff --git a/test/gigs/5113.gie b/test/gigs/5113.gie index 5c3904e7..fdb4c381 100644 --- a/test/gigs/5113.gie +++ b/test/gigs/5113.gie @@ -6,6 +6,8 @@ Test 5113, Transverse Mercator (South Oriented), v2-0_2011-06-28. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4148 +inv diff --git a/test/gigs/5201.gie b/test/gigs/5201.gie index 532443a9..29805b79 100644 --- a/test/gigs/5201.gie +++ b/test/gigs/5201.gie @@ -12,6 +12,8 @@ Test 5201, Geographic Geocentric conversions, v2.0_2011-09-28. (EPSG 4979 - WGS8 <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4978 +inv diff --git a/test/gigs/5208.gie b/test/gigs/5208.gie index 25a10b96..985dfdcb 100644 --- a/test/gigs/5208.gie +++ b/test/gigs/5208.gie @@ -22,6 +22,8 @@ To be on the safe side we, use 0.01 m as the tolerance. <gie> +use_proj4_init_rules true + -------------------------------------------------------------------------------- operation +proj=pipeline +step +init=epsg:4275 +inv diff --git a/test/gigs/Makefile.am b/test/gigs/Makefile.am index f53825bd..bea3be59 100644 --- a/test/gigs/Makefile.am +++ b/test/gigs/Makefile.am @@ -20,7 +20,7 @@ EXTRA_DIST = \ 5201.gie \ 5208.gie -PROJ_LIB ?= $(top_srcdir)/data +PROJ_LIB ?= ../../data 5101.1: 5101.1-jhs.gie PROJ_LIB=$(PROJ_LIB) $(GIEEXE) $< diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 5138dafc..68a6e60f 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -58,13 +58,13 @@ endif() include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${SQLITE3_INCLUDE_DIR}) -add_executable(proj_test_unit +add_executable(proj_pj_transform_test main.cpp - basic_test.cpp) -target_link_libraries(proj_test_unit + pj_transform_test.cpp) +target_link_libraries(proj_pj_transform_test gtest ${PROJ_LIBRARIES}) -add_test(NAME proj_test_unit COMMAND proj_test_unit) +add_test(NAME proj_pj_transform_test COMMAND proj_pj_transform_test) add_executable(proj_errno_string_test main.cpp @@ -103,3 +103,11 @@ target_link_libraries(proj_test_cpp_api ${PROJ_LIBRARIES} ${SQLITE3_LIBRARY}) add_test(NAME proj_test_cpp_api COMMAND proj_test_cpp_api) + +add_executable(gie_self_tests + main.cpp + gie_self_tests.cpp) +target_link_libraries(gie_self_tests + gtest + ${PROJ_LIBRARIES}) +add_test(NAME gie_self_tests COMMAND gie_self_tests) diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am index 77525f9a..236ad444 100644 --- a/test/unit/Makefile.am +++ b/test/unit/Makefile.am @@ -9,19 +9,17 @@ AM_CXXFLAGS = @CXX_WFLAGS@ @NO_ZERO_AS_NULL_POINTER_CONSTANT_FLAG@ PROJ_LIB ?= ../../data -noinst_PROGRAMS = basic_test +noinst_PROGRAMS = pj_transform_test noinst_PROGRAMS += pj_phi2_test noinst_PROGRAMS += proj_errno_string_test noinst_PROGRAMS += test_cpp_api +noinst_PROGRAMS += gie_self_tests -basic_test_SOURCES = basic_test.cpp main.cpp -basic_test_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la +pj_transform_test_SOURCES = pj_transform_test.cpp main.cpp +pj_transform_test_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la -test_cpp_api_SOURCES = test_util.cpp test_common.cpp test_crs.cpp test_metadata.cpp test_io.cpp test_operation.cpp test_datum.cpp test_factory.cpp test_c_api.cpp main.cpp -test_cpp_api_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la @SQLITE3_LDFLAGS@ - -basic_test-check: basic_test - ./basic_test +pj_transform_test-check: pj_transform_test + PROJ_LIB=$(PROJ_LIB) ./pj_transform_test pj_phi2_test_SOURCES = pj_phi2_test.cpp main.cpp pj_phi2_test_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la @@ -35,10 +33,16 @@ proj_errno_string_test_LDADD= ../../src/libproj.la ../../test/googletest/libgtes proj_errno_string_test-check: proj_errno_string_test ./proj_errno_string_test -check-local: basic_test-check -check-local: pj_phi2_test-check proj_errno_string_test-check +test_cpp_api_SOURCES = test_util.cpp test_common.cpp test_crs.cpp test_metadata.cpp test_io.cpp test_operation.cpp test_datum.cpp test_factory.cpp test_c_api.cpp main.cpp +test_cpp_api_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la @SQLITE3_LDFLAGS@ test_cpp_api-check: test_cpp_api PROJ_LIB=$(PROJ_LIB) ./test_cpp_api -check-local: basic_test-check test_cpp_api-check +gie_self_tests_SOURCES = gie_self_tests.cpp main.cpp +gie_self_tests_LDADD = ../../src/libproj.la ../../test/googletest/libgtest.la @SQLITE3_LDFLAGS@ + +gie_self_tests-check: gie_self_tests + PROJ_LIB=$(PROJ_LIB) ./gie_self_tests + +check-local: pj_transform_test-check pj_phi2_test-check proj_errno_string_test-check test_cpp_api-check gie_self_tests-check diff --git a/test/unit/basic_test.cpp b/test/unit/basic_test.cpp deleted file mode 100644 index d565f839..00000000 --- a/test/unit/basic_test.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * - * Project: PROJ - * Purpose: Test - * Author: Even Rouault <even dot rouault at spatialys dot com> - * - ****************************************************************************** - * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> - * - * 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 "gtest_include.h" -#include <proj.h> -#include <memory> - -namespace { - -// --------------------------------------------------------------------------- - -TEST( dumy, dummy ) { - std::unique_ptr<PJ, decltype(&::proj_destroy)> pj( - ::proj_create(PJ_DEFAULT_CTX, "+proj=merc +ellps=clrk66 +lat_ts=33"), - &::proj_destroy); - ASSERT_NE(pj, nullptr); -} - -} // namespace diff --git a/test/unit/gie_self_tests.cpp b/test/unit/gie_self_tests.cpp new file mode 100644 index 00000000..b7af926b --- /dev/null +++ b/test/unit/gie_self_tests.cpp @@ -0,0 +1,664 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: Test + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * 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 "gtest_include.h" + +// PROJ include order is sensitive +// clang-format off +#include "proj_internal.h" +#include "proj.h" +#include "projects.h" +// clang-format on + +#include <cmath> +#include <string> + +namespace { + +// --------------------------------------------------------------------------- + +TEST(gie, cart_selftest) { + PJ_CONTEXT *ctx; + PJ *P; + PJ_COORD a, b, obs[2]; + PJ_COORD coord[2]; + + int err; + size_t n, sz; + double dist, h, t; + const char *const args[3] = {"proj=utm", "zone=32", "ellps=GRS80"}; + char arg[50] = {"+proj=utm; +zone=32; +ellps=GRS80"}; + + /* An utm projection on the GRS80 ellipsoid */ + P = proj_create(PJ_DEFAULT_CTX, arg); + ASSERT_TRUE(P != nullptr); + + /* Clean up */ + proj_destroy(P); + + /* Same projection, now using argc/argv style initialization */ + P = proj_create_argv(PJ_DEFAULT_CTX, 3, const_cast<char **>(args)); + ASSERT_TRUE(P != nullptr); + + /* 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 = proj_torad(12); + a.lp.phi = proj_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, b); + ASSERT_LE(dist, 2e-9); + + /* Clear any previous error */ + proj_errno_reset(P); + + /* Invalid projection */ + a = proj_trans(P, static_cast<PJ_DIRECTION>(42), a); + ASSERT_EQ(a.lpz.lam, HUGE_VAL); + + err = proj_errno(P); + ASSERT_NE(err, 0); + + /* Clear error again */ + proj_errno_reset(P); + + /* Clean up */ + proj_destroy(P); + + /* Now do some 3D transformations */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + ASSERT_TRUE(P != nullptr); + + /* zero initialize everything, then set (longitude, latitude, height) to + * (12, 55, 100) */ + a = b = proj_coord(0, 0, 0, 0); + a.lpz.lam = proj_torad(12); + a.lpz.phi = proj_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); + ASSERT_LE(dist, 4e-9); + + /* Test at the North Pole */ + a = b = proj_coord(0, 0, 0, 0); + a.lpz.lam = proj_torad(0); + a.lpz.phi = proj_torad(90); + a.lpz.z = 100; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip(P, PJ_FWD, 1, &a); + ASSERT_LE(dist, 1e-9); + + /* Test at the South Pole */ + a = b = proj_coord(0, 0, 0, 0); + a.lpz.lam = proj_torad(0); + a.lpz.phi = proj_torad(-90); + a.lpz.z = 100; + b = a; + + /* Forward projection: Ellipsoidal-to-3D-Cartesian */ + dist = proj_roundtrip(P, PJ_FWD, 1, &a); + ASSERT_LE(dist, 4e-9); + + /* Inverse projection: 3D-Cartesian-to-Ellipsoidal */ + b = proj_trans(P, PJ_INV, b); + + /* Move p to another context */ + ctx = proj_context_create(); + ASSERT_NE(ctx, pj_get_default_ctx()); + + proj_context_set(P, ctx); + ASSERT_EQ(ctx, P->ctx); + + b = proj_trans(P, PJ_FWD, b); + + /* Move it back to the default context */ + proj_context_set(P, 0); + ASSERT_EQ(pj_get_default_ctx(), P->ctx); + + 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"); + ASSERT_TRUE(P != nullptr); + + obs[0] = proj_coord(proj_torad(12), proj_torad(55), 45, 0); + obs[1] = proj_coord(proj_torad(12), proj_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); + ASSERT_EQ(n, 2); + + ASSERT_EQ(a.lpz.lam, obs[0].lpz.lam); + ASSERT_EQ(a.lpz.phi, obs[0].lpz.phi); + ASSERT_EQ(a.lpz.z, obs[0].lpz.z); + ASSERT_EQ(b.lpz.lam, obs[1].lpz.lam); + ASSERT_EQ(b.lpz.phi, obs[1].lpz.phi); + ASSERT_EQ(b.lpz.z, obs[1].lpz.z); + + /* now test the case of constant z */ + obs[0] = proj_coord(proj_torad(12), proj_torad(55), 45, 0); + obs[1] = proj_coord(proj_torad(12), proj_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); + ASSERT_EQ(n, 2); + + ASSERT_EQ(a.lpz.lam, obs[0].lpz.lam); + ASSERT_EQ(a.lpz.phi, obs[0].lpz.phi); + ASSERT_EQ(45, obs[0].lpz.z); + ASSERT_EQ(b.lpz.lam, obs[1].lpz.lam); + ASSERT_EQ(b.lpz.phi, obs[1].lpz.phi); + ASSERT_EQ(50, obs[1].lpz.z); + ASSERT_NE(50, h); + + /* test proj_trans_array () */ + + coord[0] = proj_coord(proj_torad(12), proj_torad(55), 45, 0); + coord[1] = proj_coord(proj_torad(12), proj_torad(56), 50, 0); + ASSERT_FALSE(proj_trans_array(P, PJ_FWD, 2, coord)); + + ASSERT_EQ(a.lpz.lam, coord[0].lpz.lam); + ASSERT_EQ(a.lpz.phi, coord[0].lpz.phi); + ASSERT_EQ(a.lpz.z, coord[0].lpz.z); + ASSERT_EQ(b.lpz.lam, coord[1].lpz.lam); + ASSERT_EQ(b.lpz.phi, coord[1].lpz.phi); + ASSERT_EQ(b.lpz.z, coord[1].lpz.z); + + /* Clean up after proj_trans_* tests */ + proj_destroy(P); +} + +// --------------------------------------------------------------------------- + +class gieTest : public ::testing::Test { + + static void DummyLogFunction(void *, int, const char *) {} + + protected: + void SetUp() override { + m_ctxt = proj_context_create(); + proj_log_func(m_ctxt, nullptr, DummyLogFunction); + } + + void TearDown() override { proj_context_destroy(m_ctxt); } + + PJ_CONTEXT *m_ctxt = nullptr; +}; + +// --------------------------------------------------------------------------- + +TEST_F(gieTest, proj_create_crs_to_crs) { + /* test proj_create_crs_to_crs() */ + auto P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "epsg:25832", "epsg:25833", + NULL); + ASSERT_TRUE(P != nullptr); + PJ_COORD a, b; + + 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); + EXPECT_NEAR(a.xy.x, b.xy.x, 1e-9); + EXPECT_NEAR(a.xy.y, b.xy.y, 1e-9); + proj_destroy(P); + + /* we can also allow PROJ strings as 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); + ASSERT_TRUE(P != nullptr); + proj_destroy(P); + + EXPECT_TRUE(proj_create_crs_to_crs(m_ctxt, "invalid", "EPSG:25833", NULL) == + nullptr); + EXPECT_TRUE(proj_create_crs_to_crs(m_ctxt, "EPSG:25832", "invalid", NULL) == + nullptr); +} + +// --------------------------------------------------------------------------- + +TEST_F(gieTest, proj_create_crs_to_crs_EPSG_4326) { + + auto P = + proj_create_crs_to_crs(PJ_DEFAULT_CTX, "EPSG:4326", "EPSG:32631", NULL); + ASSERT_TRUE(P != nullptr); + PJ_COORD a, b; + + // Lat, long degrees + a.xy.x = 0.0; + a.xy.y = 3.0; + + b.xy.x = 500000.0; + b.xy.y = 0.0; + + a = proj_trans(P, PJ_FWD, a); + EXPECT_NEAR(a.xy.x, b.xy.x, 1e-9); + EXPECT_NEAR(a.xy.y, b.xy.y, 1e-9); + proj_destroy(P); +} + +// --------------------------------------------------------------------------- + +TEST_F(gieTest, proj_create_crs_to_crs_proj_longlat) { + + auto P = proj_create_crs_to_crs( + PJ_DEFAULT_CTX, "+proj=longlat +datum=WGS84", "EPSG:32631", NULL); + ASSERT_TRUE(P != nullptr); + PJ_COORD a, b; + + // Long, lat degrees + a.xy.x = 3.0; + a.xy.y = 0; + + b.xy.x = 500000.0; + b.xy.y = 0.0; + + a = proj_trans(P, PJ_FWD, a); + EXPECT_NEAR(a.xy.x, b.xy.x, 1e-9); + EXPECT_NEAR(a.xy.y, b.xy.y, 1e-9); + proj_destroy(P); +} + +// --------------------------------------------------------------------------- + +TEST(gie, info_functions) { + PJ_INFO info; + PJ_PROJ_INFO pj_info; + PJ_GRID_INFO grid_info; + PJ_INIT_INFO init_info; + + PJ_FACTORS factors; + + const PJ_OPERATIONS *oper_list; + const PJ_ELLPS *ellps_list; + const PJ_UNITS *unit_list; + const PJ_PRIME_MERIDIANS *pm_list; + + char buf[40]; + PJ *P; + char arg[50] = {"+proj=utm; +zone=32; +ellps=GRS80"}; + PJ_COORD a; + + /* ********************************************************************** */ + /* 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); + ASSERT_EQ(std::string(info.version), std::string(tmpstr)); + } + ASSERT_NE(std::string(info.release), ""); + if (getenv("HOME") || getenv("PROJ_LIB")) { + ASSERT_NE(std::string(info.searchpath), std::string()); + } + + /* proj_pj_info() */ + { + P = proj_create(PJ_DEFAULT_CTX, + "+proj=august"); /* august has no inverse */ + auto has_inverse = proj_pj_info(P).has_inverse; + proj_destroy(P); + ASSERT_FALSE(has_inverse); + } + + P = proj_create(PJ_DEFAULT_CTX, arg); + pj_info = proj_pj_info(P); + ASSERT_TRUE(pj_info.has_inverse); + pj_shrink(arg); + ASSERT_EQ(std::string(pj_info.definition), arg); + ASSERT_EQ(std::string(pj_info.id), "utm"); + + proj_destroy(P); + + /* proj_grid_info() */ + grid_info = proj_grid_info("null"); + ASSERT_NE(std::string(grid_info.filename), ""); + ASSERT_EQ(std::string(grid_info.gridname), "null"); + + grid_info = proj_grid_info("nonexistinggrid"); + ASSERT_EQ(std::string(grid_info.filename), ""); + + /* proj_init_info() */ + init_info = proj_init_info("unknowninit"); + ASSERT_EQ(std::string(init_info.filename), ""); + + init_info = proj_init_info("epsg"); + /* Need to allow for "Unknown" until all commonly distributed EPSG-files + * comes with a metadata section */ + ASSERT_TRUE(std::string(init_info.origin) == "EPSG" || + std::string(init_info.origin) == "Unknown") + << std::string(init_info.origin); + ASSERT_EQ(std::string(init_info.name), "epsg"); + + /* test proj_rtodms() and proj_dmstor() */ + ASSERT_EQ(std::string("180dN"), proj_rtodms(buf, M_PI, 'N', 'S')); + + ASSERT_EQ(proj_dmstor(&buf[0], NULL), M_PI); + + ASSERT_EQ(std::string("114d35'29.612\"S"), + proj_rtodms(buf, -2.0, 'N', 'S')); + + /* we can't expect perfect numerical accuracy so testing with a tolerance */ + ASSERT_NEAR(-2.0, proj_dmstor(&buf[0], NULL), 1e-7); + + /* 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 = proj_torad(12); + a.lp.phi = proj_torad(55); + + factors = proj_factors(P, a); + ASSERT_FALSE(proj_errno(P)); /* factors not created correctly */ + + /* check a few key characteristics of the Mercator projection */ + ASSERT_EQ(factors.angular_distortion, + 0.0); /* angular distortion should be 0 */ + ASSERT_EQ(factors.meridian_parallel_angle, + M_PI_2); /* Meridian/parallel angle should be 90 deg */ + ASSERT_EQ(factors.meridian_convergence, + 0.0); /* meridian convergence should be 0 */ + + proj_destroy(P); + + /* Check that proj_list_* functions work by looping through them */ + size_t n = 0; + for (oper_list = proj_list_operations(); oper_list->id; ++oper_list) + n++; + ASSERT_NE(n, 0U); + + n = 0; + for (ellps_list = proj_list_ellps(); ellps_list->id; ++ellps_list) + n++; + ASSERT_NE(n, 0U); + + n = 0; + for (unit_list = proj_list_units(); unit_list->id; ++unit_list) + n++; + ASSERT_NE(n, 0U); + + n = 0; + for (pm_list = proj_list_prime_meridians(); pm_list->id; ++pm_list) + n++; + ASSERT_NE(n, 0U); +} + +// --------------------------------------------------------------------------- + +TEST(gie, io_predicates) { + /* check io-predicates */ + + /* angular in on fwd, linear out */ + auto P = proj_create(PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80"); + ASSERT_TRUE(P != nullptr); + ASSERT_TRUE(proj_angular_input(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_input(P, PJ_INV)); + ASSERT_FALSE(proj_angular_output(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_output(P, PJ_INV)); + P->inverted = 1; + ASSERT_FALSE(proj_angular_input(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_input(P, PJ_INV)); + ASSERT_TRUE(proj_angular_output(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_output(P, PJ_INV)); + 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 "); + ASSERT_TRUE(P != nullptr); + ASSERT_TRUE(proj_angular_input(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_input(P, PJ_INV)); + ASSERT_TRUE(proj_angular_output(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_output(P, PJ_INV)); + P->inverted = 1; + ASSERT_TRUE(proj_angular_input(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_input(P, PJ_INV)); + ASSERT_TRUE(proj_angular_output(P, PJ_FWD)); + ASSERT_TRUE(proj_angular_output(P, PJ_INV)); + proj_destroy(P); + + /* linear in and out */ + P = proj_create(PJ_DEFAULT_CTX, + " +proj=helmert" + " +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" + " +t_epoch=1988.0 +convention=coordinate_frame +no_defs"); + ASSERT_TRUE(P != nullptr); + ASSERT_FALSE(proj_angular_input(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_input(P, PJ_INV)); + ASSERT_FALSE(proj_angular_output(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_output(P, PJ_INV)); + P->inverted = 1; + ASSERT_FALSE(proj_angular_input(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_input(P, PJ_INV)); + ASSERT_FALSE(proj_angular_output(P, PJ_FWD)); + ASSERT_FALSE(proj_angular_output(P, PJ_INV)); + + /* We specified "no_defs" but didn't give any ellipsoid info */ + /* pj_init_ctx should default to WGS84 */ + ASSERT_EQ(P->a, 6378137.0); + ASSERT_EQ(P->f, 1.0 / 298.257223563); + proj_destroy(P); + + /* Test that pj_fwd* and pj_inv* returns NaNs when receiving NaN input */ + P = proj_create(PJ_DEFAULT_CTX, "+proj=merc"); + ASSERT_TRUE(P != nullptr); + auto a = proj_coord(NAN, NAN, NAN, NAN); + a = proj_trans(P, PJ_FWD, a); + ASSERT_TRUE((std::isnan(a.v[0]) && std::isnan(a.v[1]) && + std::isnan(a.v[2]) && std::isnan(a.v[3]))); + + a = proj_coord(NAN, NAN, NAN, NAN); + a = proj_trans(P, PJ_INV, a); + ASSERT_TRUE((std::isnan(a.v[0]) && std::isnan(a.v[1]) && + std::isnan(a.v[2]) && std::isnan(a.v[3]))); + proj_destroy(P); +} + +// --------------------------------------------------------------------------- + +static void test_time(const char *args, double tol, double t_in, double t_exp) { + PJ_COORD in, out; + PJ *P = proj_create(PJ_DEFAULT_CTX, args); + + ASSERT_TRUE(P != 0); + + in = proj_coord(0.0, 0.0, 0.0, t_in); + + out = proj_trans(P, PJ_FWD, in); + EXPECT_NEAR(out.xyzt.t, t_exp, tol); + + out = proj_trans(P, PJ_INV, out); + EXPECT_NEAR(out.xyzt.t, t_in, tol); + + pj_free(P); + + proj_log_level(NULL, PJ_LOG_NONE); +} + +// --------------------------------------------------------------------------- + +TEST(gie, unitconvert_selftest) { + + 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 +t_in=yyyymmdd +t_out=yyyymmdd"; + double in5 = 20170131; + + test_time(args1, 1e-6, in1, in1); + test_time(args2, 1e-6, in2, in2); + test_time(args3, 1e-6, in3, in3); + test_time(args4, 1e-6, in4, exp4); + test_time(args5, 1e-6, in5, in5); +} + +static const 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"}; + +static const 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"}; + +// --------------------------------------------------------------------------- + +TEST(gie, horner_selftest) { + + 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); + ASSERT_TRUE(P != nullptr); + + 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); + EXPECT_LE(dist, 0.01); + proj_destroy(P); + + /* The complex polynomial transformation between the "System Storebaelt" and + * utm32/ed50 */ + P = proj_create(PJ_DEFAULT_CTX, sb_utm32); + ASSERT_TRUE(P != nullptr); + + /* 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, c); + EXPECT_LE(dist, 0.001); + + /* Inverse projection */ + b = proj_trans(P, PJ_INV, c); + dist = proj_xy_dist(b, a); + EXPECT_LE(dist, 0.001); + + /* Check roundtrip precision for 1 iteration each way */ + dist = proj_roundtrip(P, PJ_FWD, 1, &a); + EXPECT_LE(dist, 0.01); + + proj_destroy(P); +} + +} // namespace diff --git a/test/unit/main.cpp b/test/unit/main.cpp index f24a7aa6..d53e4236 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -31,9 +31,9 @@ #include "gtest_include.h" GTEST_API_ int main(int argc, char **argv) { - // Use a potentially non-C locale to make sure we are robust - setlocale(LC_ALL, ""); + // Use a potentially non-C locale to make sure we are robust + setlocale(LC_ALL, ""); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp index 186bcbc5..67441b69 100644 --- a/test/unit/pj_phi2_test.cpp +++ b/test/unit/pj_phi2_test.cpp @@ -60,7 +60,6 @@ TEST(PjPhi2Test, Basic) { EXPECT_TRUE(std::isnan(pj_phi2(ctx, -M_PI, -M_PI))); } - TEST(PjPhi2Test, AvoidUndefinedBehavior) { auto ctx = pj_get_default_ctx(); @@ -82,4 +81,4 @@ TEST(PjPhi2Test, AvoidUndefinedBehavior) { EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, -inf))); } -} // namespace +} // namespace diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp new file mode 100644 index 00000000..95329bdb --- /dev/null +++ b/test/unit/pj_transform_test.cpp @@ -0,0 +1,583 @@ +/****************************************************************************** + * + * Project: PROJ + * Purpose: Test pj_transform() legacy interface + * Author: Even Rouault <even dot rouault at spatialys dot com> + * + ****************************************************************************** + * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com> + * + * 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 ACCEPT_USE_OF_DEPRECATED_PROJ_API_H + +#include "gtest_include.h" +#include <memory> + +// PROJ include order is sensitive +// clang-format off +#include <projects.h> +#include <proj_api.h> +// clang-format on + +namespace { + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_longlat) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_EQ(x, 2 * DEG_TO_RAD); + EXPECT_EQ(y, 49 * DEG_TO_RAD); + + x = 182 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_EQ(x, 182 * DEG_TO_RAD); + EXPECT_EQ(y, 49 * DEG_TO_RAD); + + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_proj) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); + double x = 3 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 500000, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_proj_tometer) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84 +to_meter=1000"); + double x = 3 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 500, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, proj_to_longlat) { + auto src = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 500000; + double y = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 3 * DEG_TO_RAD, 1e-12); + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, proj_to_proj) { + auto src = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); + auto dst = pj_init_plus("+proj=utm +zone=31 +datum=WGS84"); + double x = 500000; + double y = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 500000, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_geocent) { + auto src = pj_init_plus("+proj=longlat +R=2"); + auto dst = pj_init_plus("+proj=geocent +R=2"); + double x = 0; + double y = 0; + double z = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + EXPECT_NEAR(z, 0, 1e-8); + + x = 90 * DEG_TO_RAD; + y = 0; + z = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 0, 1e-8); + EXPECT_NEAR(y, 2, 1e-8); + EXPECT_NEAR(z, 0, 1e-8); + + x = 0; + y = 90 * DEG_TO_RAD; + z = 0.1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 0, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + EXPECT_NEAR(z, 2 + 0.1, 1e-8); + + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_geocent_to_meter) { + auto src = pj_init_plus("+proj=longlat +R=2"); + auto dst = pj_init_plus("+proj=geocent +R=2 +to_meter=1000"); + double x = 0; + double y = 0; + double z = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2e-3, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + EXPECT_NEAR(z, 0, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, geocent_to_longlat) { + auto src = pj_init_plus("+proj=geocent +R=2"); + auto dst = pj_init_plus("+proj=longlat +R=2"); + double x = 0; + double y = 2; + double z = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 0, 1e-12); + + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, geocent_to_meter_to_longlat) { + auto src = pj_init_plus("+proj=geocent +to_meter=1000 +R=2"); + auto dst = pj_init_plus("+proj=longlat +R=2"); + double x = 0; + double y = 2e-3; + double z = 0; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 0, 1e-12); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, pm) { + auto src = pj_init_plus("+proj=longlat +pm=3 +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +pm=1 +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, (2 + 3 - 1) * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_EQ(y, 49 * DEG_TO_RAD) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_geoc_to_longlat) { + auto src = pj_init_plus("+proj=longlat +geoc +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 48.809360314691766 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_to_longlat_geoc) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +geoc +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 48.809360314691766 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, ellps_to_ellps_noop) { + auto src = pj_init_plus("+proj=longlat +ellps=clrk66"); + auto dst = pj_init_plus("+proj=longlat +ellps=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, towgs84_3param_noop) { + auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3"); + auto dst = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 10; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, towgs84_7param_noop) { + auto src = + pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7"); + auto dst = + pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=1,2,3,4,5,6,7"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 10; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_towgs84_3param_to_datum) { + auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 90 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + double z = 10; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10 + 1, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_towgs84_3param_to_datum_no_z) { + auto src = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 90 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_towgs84_7param_to_datum) { + auto src = + pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0,0,0,0,0.5"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 90 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + double z = 10; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 14.189073500223458, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, datum_to_longlat_towgs84_3param) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0"); + double x = 90 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + double z = 10 + 1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, datum_to_longlat_towgs84_7param) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = + pj_init_plus("+proj=longlat +ellps=WGS84 +towgs84=0,1,0,0,0,0,0.5"); + double x = 90 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + double z = 14.189073500223458; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 90 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, ellps_grs80_towgs84_to_datum_wgs84) { + auto src = pj_init_plus("+proj=longlat +ellps=GRS80 +towgs84=0,0,0"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 10; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-15) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-15) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, longlat_nadgrids_to_datum) { + auto src = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); + auto dst = pj_init_plus("+proj=longlat +datum=NAD83"); + double x = -100 * DEG_TO_RAD; + double y = 40 * DEG_TO_RAD; + double z = 10; + int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); + EXPECT_TRUE(ret == 0 || ret == PJD_ERR_FAILED_TO_LOAD_GRID); + if (ret == 0) { + EXPECT_NEAR(x, -100.00040583667015 * DEG_TO_RAD, 1e-12) + << x / DEG_TO_RAD; + EXPECT_NEAR(y, 40.000005895651363 * DEG_TO_RAD, 1e-12) + << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10.000043224543333, 1e-8); + } + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, nadgrids_noop) { + auto src = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); + auto dst = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); + double x = -100 * DEG_TO_RAD; + double y = 40 * DEG_TO_RAD; + double z = 10; + int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); + EXPECT_TRUE(ret == 0); + if (ret == 0) { + EXPECT_NEAR(x, -100 * DEG_TO_RAD, 1e-15) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 40 * DEG_TO_RAD, 1e-15) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + } + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, datum_to_longlat_nadgrids) { + auto src = pj_init_plus("+proj=longlat +datum=NAD83"); + auto dst = pj_init_plus("+proj=longlat +ellps=clrk66 +nadgrids=conus"); + double x = -100.00040583667015 * DEG_TO_RAD; + double y = 40.000005895651363 * DEG_TO_RAD; + double z = 10.000043224543333; + int ret = pj_transform(src, dst, 1, 0, &x, &y, &z); + EXPECT_TRUE(ret == 0 || ret == PJD_ERR_FAILED_TO_LOAD_GRID); + if (ret == 0) { + EXPECT_NEAR(x, -100 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 40 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 10, 1e-8); + } + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, long_wrap) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +lon_wrap=180"); + double x = -1 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 359 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 0 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, src_vto_meter) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84 +vto_meter=1000"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 1000, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, dest_vto_meter) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +vto_meter=1000"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 1000; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 1, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, src_axis_neu_with_z) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 49 * DEG_TO_RAD; + double y = 2 * DEG_TO_RAD; + double z = 1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 1, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, src_axis_neu_without_z) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 49 * DEG_TO_RAD; + double y = 2 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, src_axis_swd) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84 +axis=swd"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84"); + double x = 49 * DEG_TO_RAD; + double y = 2 * DEG_TO_RAD; + double z = -1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, -2 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, -49 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 1, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, dst_axis_neu) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +axis=neu"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, 49 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, 2 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, 1, 1e-8); + pj_free(src); + pj_free(dst); +} +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, dst_axis_swd) { + auto src = pj_init_plus("+proj=longlat +datum=WGS84"); + auto dst = pj_init_plus("+proj=longlat +datum=WGS84 +axis=swd"); + double x = 2 * DEG_TO_RAD; + double y = 49 * DEG_TO_RAD; + double z = 1; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, &z), 0); + EXPECT_NEAR(x, -49 * DEG_TO_RAD, 1e-12) << x / DEG_TO_RAD; + EXPECT_NEAR(y, -2 * DEG_TO_RAD, 1e-12) << y / DEG_TO_RAD; + EXPECT_NEAR(z, -1, 1e-8); + pj_free(src); + pj_free(dst); +} + +// --------------------------------------------------------------------------- + +TEST(pj_transform_test, init_epsg) { + auto src = pj_init_plus("+init=epsg:4326"); + ASSERT_TRUE(src != nullptr); + auto dst = pj_init_plus("+init=epsg:32631"); + double x = 3 * DEG_TO_RAD; + double y = 0 * DEG_TO_RAD; + EXPECT_EQ(pj_transform(src, dst, 1, 0, &x, &y, nullptr), 0); + EXPECT_NEAR(x, 500000, 1e-8); + EXPECT_NEAR(y, 0, 1e-8); + pj_free(src); + pj_free(dst); +} + +} // namespace diff --git a/test/unit/proj_errno_string_test.cpp b/test/unit/proj_errno_string_test.cpp index 92840d34..dcdff5c4 100644 --- a/test/unit/proj_errno_string_test.cpp +++ b/test/unit/proj_errno_string_test.cpp @@ -34,18 +34,20 @@ namespace { -TEST(ProjErrnoStringTest, NoError) { - EXPECT_EQ(0, proj_errno_string(0)); -} +TEST(ProjErrnoStringTest, NoError) { EXPECT_EQ(0, proj_errno_string(0)); } TEST(ProjErrnoStringTest, ProjErrnos) { EXPECT_STREQ("no arguments in initialization list", proj_errno_string(-1)); - EXPECT_STREQ("invalid projection system error (-1000)", proj_errno_string(-1000)); - EXPECT_STREQ("invalid projection system error (-9999)", proj_errno_string(-9999)); + EXPECT_STREQ("invalid projection system error (-1000)", + proj_errno_string(-1000)); + EXPECT_STREQ("invalid projection system error (-9999)", + proj_errno_string(-9999)); // for errnos < -9999, -9999 is always returned const int min = std::numeric_limits<int>::min(); - EXPECT_STREQ("invalid projection system error (-9999)",proj_errno_string(min)); - EXPECT_STREQ("invalid projection system error (-9999)", proj_errno_string(-10000)); + EXPECT_STREQ("invalid projection system error (-9999)", + proj_errno_string(min)); + EXPECT_STREQ("invalid projection system error (-9999)", + proj_errno_string(-10000)); } TEST(ProjErrnoStringTest, SystemErrnos) { @@ -65,4 +67,4 @@ TEST(ProjErrnoStringTest, SystemErrnos) { #endif } -} // namespace +} // namespace diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index 8c9f114b..7db38601 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -29,6 +29,7 @@ #include "gtest_include.h" #include "proj.h" +#include "proj_experimental.h" #include "proj/common.hpp" #include "proj/coordinateoperation.hpp" @@ -198,13 +199,14 @@ TEST_F(CApi, proj_obj_as_wkt) { ASSERT_NE(obj, nullptr); { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT2_2018, nullptr); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT2_2018, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEOGCRS[") == 0) << wkt; } { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT2_2018_SIMPLIFIED, nullptr); + auto wkt = + proj_obj_as_wkt(m_ctxt, obj, PJ_WKT2_2018_SIMPLIFIED, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEOGCRS[") == 0) << wkt; EXPECT_TRUE(std::string(wkt).find("ANGULARUNIT[") == std::string::npos) @@ -212,13 +214,14 @@ TEST_F(CApi, proj_obj_as_wkt) { } { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT2_2015, nullptr); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT2_2015, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEODCRS[") == 0) << wkt; } { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT2_2015_SIMPLIFIED, nullptr); + auto wkt = + proj_obj_as_wkt(m_ctxt, obj, PJ_WKT2_2015_SIMPLIFIED, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEODCRS[") == 0) << wkt; EXPECT_TRUE(std::string(wkt).find("ANGULARUNIT[") == std::string::npos) @@ -226,13 +229,13 @@ TEST_F(CApi, proj_obj_as_wkt) { } { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, nullptr); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEOGCS[\"WGS 84\"") == 0) << wkt; } { - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_ESRI, nullptr); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_ESRI, nullptr); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("GEOGCS[\"GCS_WGS_1984\"") == 0) << wkt; @@ -241,7 +244,7 @@ TEST_F(CApi, proj_obj_as_wkt) { // MULTILINE=NO { const char *const options[] = {"MULTILINE=NO", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("\n") == std::string::npos) << wkt; } @@ -249,7 +252,7 @@ TEST_F(CApi, proj_obj_as_wkt) { // INDENTATION_WIDTH=2 { const char *const options[] = {"INDENTATION_WIDTH=2", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("\n DATUM") != std::string::npos) << wkt; @@ -258,7 +261,7 @@ TEST_F(CApi, proj_obj_as_wkt) { // OUTPUT_AXIS=NO { const char *const options[] = {"OUTPUT_AXIS=NO", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("AXIS") == std::string::npos) << wkt; } @@ -266,7 +269,7 @@ TEST_F(CApi, proj_obj_as_wkt) { // OUTPUT_AXIS=AUTO { const char *const options[] = {"OUTPUT_AXIS=AUTO", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("AXIS") == std::string::npos) << wkt; } @@ -274,7 +277,7 @@ TEST_F(CApi, proj_obj_as_wkt) { // OUTPUT_AXIS=YES { const char *const options[] = {"OUTPUT_AXIS=YES", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, options); ASSERT_NE(wkt, nullptr); EXPECT_TRUE(std::string(wkt).find("AXIS") != std::string::npos) << wkt; } @@ -282,13 +285,32 @@ TEST_F(CApi, proj_obj_as_wkt) { // unsupported option { const char *const options[] = {"unsupported=yes", nullptr}; - auto wkt = proj_obj_as_wkt(obj, PJ_WKT2_2018, options); + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT2_2018, options); EXPECT_EQ(wkt, nullptr); } } // --------------------------------------------------------------------------- +TEST_F(CApi, proj_obj_as_wkt_check_db_use) { + auto obj = proj_obj_create_from_wkt( + m_ctxt, "GEOGCS[\"AGD66\",DATUM[\"Australian_Geodetic_Datum_1966\"," + "SPHEROID[\"Australian National Spheroid\",6378160,298.25]]," + "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]", + nullptr); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto wkt = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_ESRI, nullptr); + EXPECT_EQ(std::string(wkt), + "GEOGCS[\"GCS_Australian_1966\",DATUM[\"D_Australian_1966\"," + "SPHEROID[\"Australian\",6378160.0,298.25]]," + "PRIMEM[\"Greenwich\",0.0]," + "UNIT[\"Degree\",0.0174532925199433]]"); +} + +// --------------------------------------------------------------------------- + TEST_F(CApi, proj_obj_as_wkt_incompatible_WKT1) { auto obj = proj_obj_create_from_wkt( m_ctxt, @@ -297,7 +319,7 @@ TEST_F(CApi, proj_obj_as_wkt_incompatible_WKT1) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - auto wkt1_GDAL = proj_obj_as_wkt(obj, PJ_WKT1_GDAL, nullptr); + auto wkt1_GDAL = proj_obj_as_wkt(m_ctxt, obj, PJ_WKT1_GDAL, nullptr); ASSERT_EQ(wkt1_GDAL, nullptr); } @@ -313,7 +335,7 @@ TEST_F(CApi, proj_obj_as_proj_string) { ASSERT_NE(obj, nullptr); { - auto proj_5 = proj_obj_as_proj_string(obj, PJ_PROJ_5, nullptr); + auto proj_5 = proj_obj_as_proj_string(m_ctxt, obj, PJ_PROJ_5, nullptr); ASSERT_NE(proj_5, nullptr); EXPECT_EQ(std::string(proj_5), "+proj=pipeline +step +proj=longlat " "+ellps=WGS84 +step +proj=unitconvert " @@ -321,7 +343,7 @@ TEST_F(CApi, proj_obj_as_proj_string) { "+proj=axisswap +order=2,1"); } { - auto proj_4 = proj_obj_as_proj_string(obj, PJ_PROJ_4, nullptr); + auto proj_4 = proj_obj_as_proj_string(m_ctxt, obj, PJ_PROJ_4, nullptr); ASSERT_NE(proj_4, nullptr); EXPECT_EQ(std::string(proj_4), "+proj=longlat +datum=WGS84 +no_defs"); } @@ -337,7 +359,7 @@ TEST_F(CApi, proj_obj_as_proj_string_incompatible_WKT1) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - auto str = proj_obj_as_proj_string(obj, PJ_PROJ_5, nullptr); + auto str = proj_obj_as_proj_string(m_ctxt, obj, PJ_PROJ_5, nullptr); ASSERT_EQ(str, nullptr); } @@ -349,7 +371,7 @@ TEST_F(CApi, proj_obj_as_proj_string_etmerc_option_yes) { ASSERT_NE(obj, nullptr); const char *options[] = {"USE_ETMERC=YES", nullptr}; - auto str = proj_obj_as_proj_string(obj, PJ_PROJ_4, options); + auto str = proj_obj_as_proj_string(m_ctxt, obj, PJ_PROJ_4, options); ASSERT_NE(str, nullptr); EXPECT_EQ(str, std::string("+proj=etmerc +lat_0=0 +lon_0=0 +k=1 +x_0=0 " "+y_0=0 +datum=WGS84 +units=m +no_defs")); @@ -364,7 +386,7 @@ TEST_F(CApi, proj_obj_as_proj_string_etmerc_option_no) { ASSERT_NE(obj, nullptr); const char *options[] = {"USE_ETMERC=NO", nullptr}; - auto str = proj_obj_as_proj_string(obj, PJ_PROJ_4, options); + auto str = proj_obj_as_proj_string(m_ctxt, obj, PJ_PROJ_4, options); ASSERT_NE(str, nullptr); EXPECT_EQ(str, std::string("+proj=tmerc +lat_0=0 +lon_0=3 +k=0.9996 " "+x_0=500000 +y_0=0 +datum=WGS84 +units=m " @@ -379,17 +401,37 @@ TEST_F(CApi, proj_obj_crs_create_bound_crs_to_WGS84) { ObjectKeeper keeper(crs); ASSERT_NE(crs, nullptr); - auto res = proj_obj_crs_create_bound_crs_to_WGS84(crs); + auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, crs); ObjectKeeper keeper_res(res); ASSERT_NE(res, nullptr); - auto proj_4 = proj_obj_as_proj_string(res, PJ_PROJ_4, nullptr); + auto proj_4 = proj_obj_as_proj_string(m_ctxt, res, PJ_PROJ_4, nullptr); ASSERT_NE(proj_4, nullptr); EXPECT_EQ(std::string(proj_4), "+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 " "+y_0=500000 +ellps=krass " "+towgs84=2.329,-147.042,-92.08,-0.309,0.325,0.497,5.69 " "+units=m +no_defs"); + + auto base_crs = proj_obj_get_source_crs(m_ctxt, res); + ObjectKeeper keeper_base_crs(base_crs); + ASSERT_NE(base_crs, nullptr); + + auto hub_crs = proj_obj_get_target_crs(m_ctxt, res); + ObjectKeeper keeper_hub_crs(hub_crs); + ASSERT_NE(hub_crs, nullptr); + + auto transf = + proj_obj_crs_get_coordoperation(m_ctxt, res, nullptr, nullptr, nullptr); + ObjectKeeper keeper_transf(transf); + ASSERT_NE(transf, nullptr); + + auto res2 = + proj_obj_crs_create_bound_crs(m_ctxt, base_crs, hub_crs, transf); + ObjectKeeper keeper_res2(res2); + ASSERT_NE(res2, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(res, res2, PJ_COMP_STRICT)); } // --------------------------------------------------------------------------- @@ -404,7 +446,7 @@ TEST_F(CApi, proj_obj_crs_create_bound_crs_to_WGS84_on_invalid_type) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - auto res = proj_obj_crs_create_bound_crs_to_WGS84(obj); + auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, obj); ASSERT_EQ(res, nullptr); } @@ -647,7 +689,7 @@ TEST_F(CApi, proj_crs) { ObjectKeeper keeper(crs); EXPECT_TRUE(proj_obj_is_crs(crs)); - auto geodCRS = proj_obj_crs_get_geodetic_crs(crs); + auto geodCRS = proj_obj_crs_get_geodetic_crs(m_ctxt, crs); ASSERT_NE(geodCRS, nullptr); ObjectKeeper keeper_geogCRS(geodCRS); EXPECT_TRUE(proj_obj_is_crs(geodCRS)); @@ -655,37 +697,44 @@ TEST_F(CApi, proj_crs) { ASSERT_TRUE(geogCRS_name != nullptr); EXPECT_EQ(geogCRS_name, std::string("WGS 84")); - auto datum = proj_obj_crs_get_horizontal_datum(crs); + auto h_datum = proj_obj_crs_get_horizontal_datum(m_ctxt, crs); + ASSERT_NE(h_datum, nullptr); + ObjectKeeper keeper_h_datum(h_datum); + + auto datum = proj_obj_crs_get_datum(m_ctxt, crs); ASSERT_NE(datum, nullptr); ObjectKeeper keeper_datum(datum); + + EXPECT_TRUE(proj_obj_is_equivalent_to(h_datum, datum, PJ_COMP_STRICT)); + auto datum_name = proj_obj_get_name(datum); ASSERT_TRUE(datum_name != nullptr); EXPECT_EQ(datum_name, std::string("World Geodetic System 1984")); - auto ellipsoid = proj_obj_get_ellipsoid(crs); + auto ellipsoid = proj_obj_get_ellipsoid(m_ctxt, crs); ASSERT_NE(ellipsoid, nullptr); ObjectKeeper keeper_ellipsoid(ellipsoid); auto ellipsoid_name = proj_obj_get_name(ellipsoid); ASSERT_TRUE(ellipsoid_name != nullptr); EXPECT_EQ(ellipsoid_name, std::string("WGS 84")); - auto ellipsoid_from_datum = proj_obj_get_ellipsoid(datum); + auto ellipsoid_from_datum = proj_obj_get_ellipsoid(m_ctxt, datum); ASSERT_NE(ellipsoid_from_datum, nullptr); ObjectKeeper keeper_ellipsoid_from_datum(ellipsoid_from_datum); - EXPECT_EQ(proj_obj_get_ellipsoid(ellipsoid), nullptr); + EXPECT_EQ(proj_obj_get_ellipsoid(m_ctxt, ellipsoid), nullptr); EXPECT_FALSE(proj_obj_is_crs(ellipsoid)); double a; double b; int b_is_computed; double rf; - EXPECT_TRUE(proj_obj_ellipsoid_get_parameters(ellipsoid, nullptr, nullptr, - nullptr, nullptr)); - EXPECT_TRUE(proj_obj_ellipsoid_get_parameters(ellipsoid, &a, &b, + EXPECT_TRUE(proj_obj_ellipsoid_get_parameters(m_ctxt, ellipsoid, nullptr, + nullptr, nullptr, nullptr)); + EXPECT_TRUE(proj_obj_ellipsoid_get_parameters(m_ctxt, ellipsoid, &a, &b, &b_is_computed, &rf)); - EXPECT_FALSE( - proj_obj_ellipsoid_get_parameters(crs, &a, &b, &b_is_computed, &rf)); + EXPECT_FALSE(proj_obj_ellipsoid_get_parameters(m_ctxt, crs, &a, &b, + &b_is_computed, &rf)); EXPECT_EQ(a, 6378137); EXPECT_NEAR(b, 6356752.31424518, 1e-9); EXPECT_EQ(b_is_computed, 1); @@ -708,31 +757,31 @@ TEST_F(CApi, proj_obj_get_prime_meridian) { ASSERT_NE(crs, nullptr); ObjectKeeper keeper(crs); - auto pm = proj_obj_get_prime_meridian(crs); + auto pm = proj_obj_get_prime_meridian(m_ctxt, crs); ASSERT_NE(pm, nullptr); ObjectKeeper keeper_pm(pm); auto pm_name = proj_obj_get_name(pm); ASSERT_TRUE(pm_name != nullptr); EXPECT_EQ(pm_name, std::string("Greenwich")); - EXPECT_EQ(proj_obj_get_prime_meridian(pm), nullptr); + EXPECT_EQ(proj_obj_get_prime_meridian(m_ctxt, pm), nullptr); - EXPECT_TRUE( - proj_obj_prime_meridian_get_parameters(pm, nullptr, nullptr, nullptr)); + EXPECT_TRUE(proj_obj_prime_meridian_get_parameters(m_ctxt, pm, nullptr, + nullptr, nullptr)); double longitude = -1; double longitude_unit = 0; const char *longitude_unit_name = nullptr; EXPECT_TRUE(proj_obj_prime_meridian_get_parameters( - pm, &longitude, &longitude_unit, &longitude_unit_name)); + m_ctxt, pm, &longitude, &longitude_unit, &longitude_unit_name)); EXPECT_EQ(longitude, 0); EXPECT_NEAR(longitude_unit, UnitOfMeasure::DEGREE.conversionToSI(), 1e-10); ASSERT_TRUE(longitude_unit_name != nullptr); EXPECT_EQ(longitude_unit_name, std::string("degree")); - auto datum = proj_obj_crs_get_horizontal_datum(crs); + auto datum = proj_obj_crs_get_horizontal_datum(m_ctxt, crs); ASSERT_NE(datum, nullptr); ObjectKeeper keeper_datum(datum); - auto pm_from_datum = proj_obj_get_prime_meridian(datum); + auto pm_from_datum = proj_obj_get_prime_meridian(m_ctxt, datum); ASSERT_NE(pm_from_datum, nullptr); ObjectKeeper keeper_pm_from_datum(pm_from_datum); } @@ -748,16 +797,16 @@ TEST_F(CApi, proj_crs_compound) { ObjectKeeper keeper(crs); EXPECT_EQ(proj_obj_get_type(crs), PJ_OBJ_TYPE_COMPOUND_CRS); - EXPECT_EQ(proj_obj_crs_get_sub_crs(crs, -1), nullptr); - EXPECT_EQ(proj_obj_crs_get_sub_crs(crs, 2), nullptr); + EXPECT_EQ(proj_obj_crs_get_sub_crs(m_ctxt, crs, -1), nullptr); + EXPECT_EQ(proj_obj_crs_get_sub_crs(m_ctxt, crs, 2), nullptr); - auto subcrs_horiz = proj_obj_crs_get_sub_crs(crs, 0); + auto subcrs_horiz = proj_obj_crs_get_sub_crs(m_ctxt, crs, 0); ASSERT_NE(subcrs_horiz, nullptr); ObjectKeeper keeper_subcrs_horiz(subcrs_horiz); EXPECT_EQ(proj_obj_get_type(subcrs_horiz), PJ_OBJ_TYPE_PROJECTED_CRS); - EXPECT_EQ(proj_obj_crs_get_sub_crs(subcrs_horiz, 0), nullptr); + EXPECT_EQ(proj_obj_crs_get_sub_crs(m_ctxt, subcrs_horiz, 0), nullptr); - auto subcrs_vertical = proj_obj_crs_get_sub_crs(crs, 1); + auto subcrs_vertical = proj_obj_crs_get_sub_crs(m_ctxt, crs, 1); ASSERT_NE(subcrs_vertical, nullptr); ObjectKeeper keeper_subcrs_vertical(subcrs_vertical); EXPECT_EQ(proj_obj_get_type(subcrs_vertical), PJ_OBJ_TYPE_VERTICAL_CRS); @@ -773,12 +822,12 @@ TEST_F(CApi, proj_obj_get_source_target_crs_bound_crs) { ASSERT_NE(crs, nullptr); ObjectKeeper keeper(crs); - auto sourceCRS = proj_obj_get_source_crs(crs); + auto sourceCRS = proj_obj_get_source_crs(m_ctxt, crs); ASSERT_NE(sourceCRS, nullptr); ObjectKeeper keeper_sourceCRS(sourceCRS); EXPECT_EQ(std::string(proj_obj_get_name(sourceCRS)), "NTF (Paris)"); - auto targetCRS = proj_obj_get_target_crs(crs); + auto targetCRS = proj_obj_get_target_crs(m_ctxt, crs); ASSERT_NE(targetCRS, nullptr); ObjectKeeper keeper_targetCRS(targetCRS); EXPECT_EQ(std::string(proj_obj_get_name(targetCRS)), "WGS 84"); @@ -796,12 +845,12 @@ TEST_F(CApi, proj_obj_get_source_target_crs_transformation) { ASSERT_NE(obj, nullptr); ObjectKeeper keeper(obj); - auto sourceCRS = proj_obj_get_source_crs(obj); + auto sourceCRS = proj_obj_get_source_crs(m_ctxt, obj); ASSERT_NE(sourceCRS, nullptr); ObjectKeeper keeper_sourceCRS(sourceCRS); EXPECT_EQ(std::string(proj_obj_get_name(sourceCRS)), "NTF (Paris)"); - auto targetCRS = proj_obj_get_target_crs(obj); + auto targetCRS = proj_obj_get_target_crs(m_ctxt, obj); ASSERT_NE(targetCRS, nullptr); ObjectKeeper keeper_targetCRS(targetCRS); EXPECT_EQ(std::string(proj_obj_get_name(targetCRS)), "WGS 84"); @@ -809,6 +858,22 @@ TEST_F(CApi, proj_obj_get_source_target_crs_transformation) { // --------------------------------------------------------------------------- +TEST_F(CApi, proj_obj_get_source_crs_of_projected_crs) { + auto crs = proj_obj_create_from_wkt( + m_ctxt, + createProjectedCRS()->exportToWKT(WKTFormatter::create().get()).c_str(), + nullptr); + ASSERT_NE(crs, nullptr); + ObjectKeeper keeper(crs); + + auto sourceCRS = proj_obj_get_source_crs(m_ctxt, crs); + ASSERT_NE(sourceCRS, nullptr); + ObjectKeeper keeper_sourceCRS(sourceCRS); + EXPECT_EQ(std::string(proj_obj_get_name(sourceCRS)), "WGS 84"); +} + +// --------------------------------------------------------------------------- + TEST_F(CApi, proj_obj_get_source_target_crs_conversion_without_crs) { auto obj = proj_obj_create_from_database( m_ctxt, "EPSG", "16031", PJ_OBJ_CATEGORY_COORDINATE_OPERATION, false, @@ -816,10 +881,10 @@ TEST_F(CApi, proj_obj_get_source_target_crs_conversion_without_crs) { ASSERT_NE(obj, nullptr); ObjectKeeper keeper(obj); - auto sourceCRS = proj_obj_get_source_crs(obj); + auto sourceCRS = proj_obj_get_source_crs(m_ctxt, obj); ASSERT_EQ(sourceCRS, nullptr); - auto targetCRS = proj_obj_get_target_crs(obj); + auto targetCRS = proj_obj_get_target_crs(m_ctxt, obj); ASSERT_EQ(targetCRS, nullptr); } @@ -831,10 +896,10 @@ TEST_F(CApi, proj_obj_get_source_target_crs_invalid_object) { ASSERT_NE(obj, nullptr); ObjectKeeper keeper(obj); - auto sourceCRS = proj_obj_get_source_crs(obj); + auto sourceCRS = proj_obj_get_source_crs(m_ctxt, obj); ASSERT_EQ(sourceCRS, nullptr); - auto targetCRS = proj_obj_get_target_crs(obj); + auto targetCRS = proj_obj_get_target_crs(m_ctxt, obj); ASSERT_EQ(targetCRS, nullptr); } @@ -923,21 +988,21 @@ TEST_F(CApi, conversion) { ObjectKeeper keeper(crs); { - auto conv = - proj_obj_crs_get_coordoperation(crs, nullptr, nullptr, nullptr); + auto conv = proj_obj_crs_get_coordoperation(m_ctxt, crs, nullptr, + nullptr, nullptr); ASSERT_NE(conv, nullptr); ObjectKeeper keeper_conv(conv); - ASSERT_EQ( - proj_obj_crs_get_coordoperation(conv, nullptr, nullptr, nullptr), - nullptr); + ASSERT_EQ(proj_obj_crs_get_coordoperation(m_ctxt, conv, nullptr, + nullptr, nullptr), + nullptr); } const char *methodName = nullptr; const char *methodAuthorityName = nullptr; const char *methodCode = nullptr; auto conv = proj_obj_crs_get_coordoperation( - crs, &methodName, &methodAuthorityName, &methodCode); + m_ctxt, crs, &methodName, &methodAuthorityName, &methodCode); ASSERT_NE(conv, nullptr); ObjectKeeper keeper_conv(conv); @@ -948,16 +1013,17 @@ TEST_F(CApi, conversion) { EXPECT_EQ(methodAuthorityName, std::string("EPSG")); EXPECT_EQ(methodCode, std::string("9807")); - EXPECT_EQ(proj_coordoperation_get_param_count(conv), 5); - EXPECT_EQ(proj_coordoperation_get_param_index(conv, "foo"), -1); - EXPECT_EQ(proj_coordoperation_get_param_index(conv, "False easting"), 3); + EXPECT_EQ(proj_coordoperation_get_param_count(m_ctxt, conv), 5); + EXPECT_EQ(proj_coordoperation_get_param_index(m_ctxt, conv, "foo"), -1); + EXPECT_EQ( + proj_coordoperation_get_param_index(m_ctxt, conv, "False easting"), 3); - EXPECT_FALSE(proj_coordoperation_get_param(conv, -1, nullptr, nullptr, + EXPECT_FALSE(proj_coordoperation_get_param(m_ctxt, conv, -1, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr)); - EXPECT_FALSE(proj_coordoperation_get_param(conv, 5, nullptr, nullptr, + nullptr, nullptr, nullptr)); + EXPECT_FALSE(proj_coordoperation_get_param(m_ctxt, conv, 5, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr)); + nullptr, nullptr, nullptr)); const char *name = nullptr; const char *nameAuthorityName = nullptr; @@ -967,8 +1033,8 @@ TEST_F(CApi, conversion) { double valueUnitConvFactor = 0; const char *valueUnitName = nullptr; EXPECT_TRUE(proj_coordoperation_get_param( - conv, 3, &name, &nameAuthorityName, &nameCode, &value, &valueString, - &valueUnitConvFactor, &valueUnitName)); + m_ctxt, conv, 3, &name, &nameAuthorityName, &nameCode, &value, + &valueString, &valueUnitConvFactor, &valueUnitName)); ASSERT_NE(name, nullptr); ASSERT_NE(nameAuthorityName, nullptr); ASSERT_NE(nameCode, nullptr); @@ -993,7 +1059,7 @@ TEST_F(CApi, transformation_from_boundCRS) { ObjectKeeper keeper(crs); auto transf = - proj_obj_crs_get_coordoperation(crs, nullptr, nullptr, nullptr); + proj_obj_crs_get_coordoperation(m_ctxt, crs, nullptr, nullptr, nullptr); ASSERT_NE(transf, nullptr); ObjectKeeper keeper_transf(transf); } @@ -1007,7 +1073,7 @@ TEST_F(CApi, proj_coordoperation_get_grid_used) { ASSERT_NE(op, nullptr); ObjectKeeper keeper(op); - EXPECT_EQ(proj_coordoperation_get_grid_used_count(op), 1); + EXPECT_EQ(proj_coordoperation_get_grid_used_count(m_ctxt, op), 1); const char *shortName = nullptr; const char *fullName = nullptr; const char *packageName = nullptr; @@ -1015,16 +1081,16 @@ TEST_F(CApi, proj_coordoperation_get_grid_used) { int directDownload = 0; int openLicense = 0; int available = 0; - EXPECT_EQ(proj_coordoperation_get_grid_used(op, -1, nullptr, nullptr, + EXPECT_EQ(proj_coordoperation_get_grid_used(m_ctxt, op, -1, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr), + nullptr, nullptr, nullptr), 0); - EXPECT_EQ(proj_coordoperation_get_grid_used(op, 1, nullptr, nullptr, + EXPECT_EQ(proj_coordoperation_get_grid_used(m_ctxt, op, 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr), 0); EXPECT_EQ(proj_coordoperation_get_grid_used( - op, 0, &shortName, &fullName, &packageName, &url, + m_ctxt, op, 0, &shortName, &fullName, &packageName, &url, &directDownload, &openLicense, &available), 1); ASSERT_NE(shortName, nullptr); @@ -1049,7 +1115,7 @@ TEST_F(CApi, proj_coordoperation_is_instanciable) { nullptr); ASSERT_NE(op, nullptr); ObjectKeeper keeper(op); - EXPECT_EQ(proj_coordoperation_is_instanciable(op), 1); + EXPECT_EQ(proj_coordoperation_is_instanciable(m_ctxt, op), 1); } // --------------------------------------------------------------------------- @@ -1070,20 +1136,21 @@ TEST_F(CApi, proj_obj_create_operations) { ObjectKeeper keeper_target_crs(target_crs); proj_operation_factory_context_set_spatial_criterion( - ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); proj_operation_factory_context_set_grid_availability_use( - ctxt, PROJ_GRID_AVAILABILITY_IGNORED); + m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED); - auto res = proj_obj_create_operations(source_crs, target_crs, ctxt); + auto res = proj_obj_create_operations(m_ctxt, source_crs, target_crs, ctxt); ASSERT_NE(res, nullptr); ObjListKeeper keeper_res(res); - EXPECT_EQ(proj_obj_list_get_count(res), 7); + EXPECT_EQ(proj_obj_list_get_count(res), 8); - EXPECT_EQ(proj_obj_list_get(res, -1), nullptr); - EXPECT_EQ(proj_obj_list_get(res, proj_obj_list_get_count(res)), nullptr); - auto op = proj_obj_list_get(res, 0); + EXPECT_EQ(proj_obj_list_get(m_ctxt, res, -1), nullptr); + EXPECT_EQ(proj_obj_list_get(m_ctxt, res, proj_obj_list_get_count(res)), + nullptr); + auto op = proj_obj_list_get(m_ctxt, res, 0); ASSERT_NE(op, nullptr); ObjectKeeper keeper_op(op); @@ -1112,11 +1179,12 @@ TEST_F(CApi, proj_obj_create_operations_with_pivot) { ASSERT_NE(ctxt, nullptr); ContextKeeper keeper_ctxt(ctxt); - auto res = proj_obj_create_operations(source_crs, target_crs, ctxt); + auto res = + proj_obj_create_operations(m_ctxt, source_crs, target_crs, ctxt); ASSERT_NE(res, nullptr); ObjListKeeper keeper_res(res); EXPECT_EQ(proj_obj_list_get_count(res), 1); - auto op = proj_obj_list_get(res, 0); + auto op = proj_obj_list_get(m_ctxt, res, 0); ASSERT_NE(op, nullptr); ObjectKeeper keeper_op(op); @@ -1131,14 +1199,15 @@ TEST_F(CApi, proj_obj_create_operations_with_pivot) { auto ctxt = proj_create_operation_factory_context(m_ctxt, nullptr); ASSERT_NE(ctxt, nullptr); ContextKeeper keeper_ctxt(ctxt); - proj_operation_factory_context_set_allow_use_intermediate_crs(ctxt, - false); + proj_operation_factory_context_set_allow_use_intermediate_crs( + m_ctxt, ctxt, false); - auto res = proj_obj_create_operations(source_crs, target_crs, ctxt); + auto res = + proj_obj_create_operations(m_ctxt, source_crs, target_crs, ctxt); ASSERT_NE(res, nullptr); ObjListKeeper keeper_res(res); EXPECT_EQ(proj_obj_list_get_count(res), 1); - auto op = proj_obj_list_get(res, 0); + auto op = proj_obj_list_get(m_ctxt, res, 0); ASSERT_NE(op, nullptr); ObjectKeeper keeper_op(op); @@ -1153,18 +1222,19 @@ TEST_F(CApi, proj_obj_create_operations_with_pivot) { ContextKeeper keeper_ctxt(ctxt); const char *pivots[] = {"EPSG", "4301", nullptr}; - proj_operation_factory_context_set_allowed_intermediate_crs(ctxt, - pivots); + proj_operation_factory_context_set_allowed_intermediate_crs( + m_ctxt, ctxt, pivots); proj_operation_factory_context_set_spatial_criterion( - ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); proj_operation_factory_context_set_grid_availability_use( - ctxt, PROJ_GRID_AVAILABILITY_IGNORED); + m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED); - auto res = proj_obj_create_operations(source_crs, target_crs, ctxt); + auto res = + proj_obj_create_operations(m_ctxt, source_crs, target_crs, ctxt); ASSERT_NE(res, nullptr); ObjListKeeper keeper_res(res); - EXPECT_EQ(proj_obj_list_get_count(res), 6); - auto op = proj_obj_list_get(res, 0); + EXPECT_EQ(proj_obj_list_get_count(res), 7); + auto op = proj_obj_list_get(m_ctxt, res, 1); ASSERT_NE(op, nullptr); ObjectKeeper keeper_op(op); @@ -1181,19 +1251,20 @@ TEST_F(CApi, proj_obj_create_operations_with_pivot) { ContextKeeper keeper_ctxt(ctxt); const char *pivots[] = {"EPSG", "4612", nullptr}; - proj_operation_factory_context_set_allowed_intermediate_crs(ctxt, - pivots); + proj_operation_factory_context_set_allowed_intermediate_crs( + m_ctxt, ctxt, pivots); proj_operation_factory_context_set_spatial_criterion( - ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); + m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION); proj_operation_factory_context_set_grid_availability_use( - ctxt, PROJ_GRID_AVAILABILITY_IGNORED); + m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED); - auto res = proj_obj_create_operations(source_crs, target_crs, ctxt); + auto res = + proj_obj_create_operations(m_ctxt, source_crs, target_crs, ctxt); ASSERT_NE(res, nullptr); ObjListKeeper keeper_res(res); // includes 2 results from ESRI - EXPECT_EQ(proj_obj_list_get_count(res), 4); - auto op = proj_obj_list_get(res, 0); + EXPECT_EQ(proj_obj_list_get_count(res), 5); + auto op = proj_obj_list_get(m_ctxt, res, 0); ASSERT_NE(op, nullptr); ObjectKeeper keeper_op(op); @@ -1364,13 +1435,13 @@ TEST_F(CApi, proj_obj_identify) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); { - auto res = proj_obj_identify(obj, nullptr, nullptr, nullptr); + auto res = proj_obj_identify(m_ctxt, obj, nullptr, nullptr, nullptr); ObjListKeeper keeper_res(res); EXPECT_EQ(proj_obj_list_get_count(res), 1); } { int *confidence = nullptr; - auto res = proj_obj_identify(obj, "EPSG", nullptr, &confidence); + auto res = proj_obj_identify(m_ctxt, obj, "EPSG", nullptr, &confidence); ObjListKeeper keeper_res(res); EXPECT_EQ(proj_obj_list_get_count(res), 1); EXPECT_EQ(confidence[0], 100); @@ -1383,7 +1454,8 @@ TEST_F(CApi, proj_obj_identify) { .c_str(), nullptr); ObjectKeeper keeperEllps(objEllps); - auto res = proj_obj_identify(objEllps, nullptr, nullptr, nullptr); + auto res = + proj_obj_identify(m_ctxt, objEllps, nullptr, nullptr, nullptr); ObjListKeeper keeper_res(res); EXPECT_EQ(res, nullptr); } @@ -1397,14 +1469,15 @@ TEST_F(CApi, proj_obj_get_area_of_use) { m_ctxt, "EPSG", "4326", PJ_OBJ_CATEGORY_CRS, false, nullptr); ASSERT_NE(crs, nullptr); ObjectKeeper keeper(crs); - EXPECT_TRUE(proj_obj_get_area_of_use(crs, nullptr, nullptr, nullptr, - nullptr, nullptr)); + EXPECT_TRUE(proj_obj_get_area_of_use(m_ctxt, crs, nullptr, nullptr, + nullptr, nullptr, nullptr)); const char *name = nullptr; double w; double s; double e; double n; - EXPECT_TRUE(proj_obj_get_area_of_use(crs, &w, &s, &e, &n, &name)); + EXPECT_TRUE( + proj_obj_get_area_of_use(m_ctxt, crs, &w, &s, &e, &n, &name)); EXPECT_EQ(w, -180); EXPECT_EQ(s, -90); EXPECT_EQ(e, 180); @@ -1417,8 +1490,8 @@ TEST_F(CApi, proj_obj_get_area_of_use) { proj_obj_create_from_user_input(m_ctxt, "+proj=longlat", nullptr); ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - EXPECT_FALSE(proj_obj_get_area_of_use(obj, nullptr, nullptr, nullptr, - nullptr, nullptr)); + EXPECT_FALSE(proj_obj_get_area_of_use(m_ctxt, obj, nullptr, nullptr, + nullptr, nullptr, nullptr)); } } @@ -1430,7 +1503,7 @@ TEST_F(CApi, proj_coordoperation_get_accuracy) { m_ctxt, "EPSG", "4326", PJ_OBJ_CATEGORY_CRS, false, nullptr); ASSERT_NE(crs, nullptr); ObjectKeeper keeper(crs); - EXPECT_EQ(proj_coordoperation_get_accuracy(crs), -1.0); + EXPECT_EQ(proj_coordoperation_get_accuracy(m_ctxt, crs), -1.0); } { auto obj = proj_obj_create_from_database( @@ -1438,25 +1511,30 @@ TEST_F(CApi, proj_coordoperation_get_accuracy) { nullptr); ASSERT_NE(obj, nullptr); ObjectKeeper keeper(obj); - EXPECT_EQ(proj_coordoperation_get_accuracy(obj), 16.0); + EXPECT_EQ(proj_coordoperation_get_accuracy(m_ctxt, obj), 16.0); } { auto obj = proj_obj_create_from_user_input(m_ctxt, "+proj=helmert", nullptr); ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - EXPECT_EQ(proj_coordoperation_get_accuracy(obj), -1.0); + EXPECT_EQ(proj_coordoperation_get_accuracy(m_ctxt, obj), -1.0); } } // --------------------------------------------------------------------------- TEST_F(CApi, proj_obj_create_geographic_crs) { + + auto cs = proj_obj_create_ellipsoidal_2D_cs( + m_ctxt, PJ_ELLPS2D_LATITUDE_LONGITUDE, nullptr, 0); + ObjectKeeper keeper_cs(cs); + ASSERT_NE(cs, nullptr); + { auto obj = proj_obj_create_geographic_crs( m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, - 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, - true); + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); @@ -1469,490 +1547,822 @@ TEST_F(CApi, proj_obj_create_geographic_crs) { EXPECT_NE(objRef, nullptr); EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + + auto datum = proj_obj_crs_get_datum(m_ctxt, obj); + ObjectKeeper keeper_datum(datum); + ASSERT_NE(datum, nullptr); + + auto obj2 = proj_obj_create_geographic_crs_from_datum(m_ctxt, "WGS 84", + datum, cs); + ObjectKeeper keeperObj(obj2); + ASSERT_NE(obj2, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, obj2, PJ_COMP_STRICT)); } { auto obj = proj_obj_create_geographic_crs(m_ctxt, nullptr, nullptr, nullptr, 1.0, 0.0, nullptr, - 0.0, nullptr, 0.0, false); + 0.0, nullptr, 0.0, cs); ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); } + + // Datum with GDAL_WKT1 spelling: special case of WGS_1984 + { + auto obj = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "WGS_1984", "WGS 84", 6378137, 298.257223563, + "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto objRef = proj_obj_create_from_user_input( + m_ctxt, + GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeperobjRef(objRef); + EXPECT_NE(objRef, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + } + + // Datum with GDAL_WKT1 spelling: database query + { + auto obj = proj_obj_create_geographic_crs( + m_ctxt, "NAD83", "North_American_Datum_1983", "GRS 1980", 6378137, + 298.257222101, "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto objRef = proj_obj_create_from_user_input( + m_ctxt, + GeographicCRS::EPSG_4269->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeperobjRef(objRef); + EXPECT_NE(objRef, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + } } // --------------------------------------------------------------------------- -TEST_F(CApi, proj_obj_create_projections) { +TEST_F(CApi, proj_obj_create_geocentric_crs) { + { + auto obj = proj_obj_create_geocentric_crs( + m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, + "Metre", 1.0); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); - auto geogCRS = proj_obj_create_geographic_crs( - m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, - 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, true); - ObjectKeeper keepergeogCRS(geogCRS); - ASSERT_NE(geogCRS, nullptr); + auto objRef = proj_obj_create_from_user_input( + m_ctxt, + GeographicCRS::EPSG_4978->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeperobjRef(objRef); + EXPECT_NE(objRef, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, objRef, PJ_COMP_EQUIVALENT)); + + auto datum = proj_obj_crs_get_datum(m_ctxt, obj); + ObjectKeeper keeper_datum(datum); + ASSERT_NE(datum, nullptr); + + auto obj2 = proj_obj_create_geocentric_crs_from_datum( + m_ctxt, "WGS 84", datum, "Metre", 1.0); + ObjectKeeper keeperObj(obj2); + ASSERT_NE(obj2, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, obj2, PJ_COMP_STRICT)); + } + { + auto obj = proj_obj_create_geocentric_crs( + m_ctxt, nullptr, nullptr, nullptr, 1.0, 0.0, nullptr, 0.0, nullptr, + 0.0, nullptr, 0.0); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + } +} +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_create_projections) { /* BEGIN: Generated by scripts/create_c_api_projections.py*/ { - auto projCRS = - proj_obj_create_projected_crs_UTM(geogCRS, nullptr, 0, 0); + auto projCRS = proj_obj_create_conversion_utm(m_ctxt, 0, 0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_TransverseMercator( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_transverse_mercator( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_GaussSchreiberTransverseMercator( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_gauss_schreiber_transverse_mercator( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_TransverseMercatorSouthOriented( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_transverse_mercator_south_oriented( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_TwoPointEquidistant( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_two_point_equidistant( + m_ctxt, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_TunisiaMappingGrid( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_tunisia_mapping_grid( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_AlbersEqualArea( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_albers_equal_area( + m_ctxt, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_LambertConicConformal_1SP( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_lambert_conic_conformal_1sp( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_LambertConicConformal_2SP( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_lambert_conic_conformal_2sp( + m_ctxt, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_LambertConicConformal_2SP_Michigan( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, "Degree", - 0.0174532925199433, "Metre", 1.0); + proj_obj_create_conversion_lambert_conic_conformal_2sp_michigan( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, + "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_LambertConicConformal_2SP_Belgium( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, "Degree", - 0.0174532925199433, "Metre", 1.0); + proj_obj_create_conversion_lambert_conic_conformal_2sp_belgium( + m_ctxt, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_AzimuthalEquidistant( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_azimuthal_equidistant( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_GuamProjection( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_guam_projection( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Bonne( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_bonne( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_LambertCylindricalEqualAreaSpherical( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_lambert_cylindrical_equal_area_spherical( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_LambertCylindricalEqualArea( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_lambert_cylindrical_equal_area( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_CassiniSoldner( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_cassini_soldner( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EquidistantConic( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_equidistant_conic( + m_ctxt, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertI( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_i( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertII( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_ii( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertIII( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_iii( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertIV( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_iv( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertV( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_v( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EckertVI( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_eckert_vi( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EquidistantCylindrical( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_equidistant_cylindrical( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_EquidistantCylindricalSpherical( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_equidistant_cylindrical_spherical( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Gall( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_gall( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_GoodeHomolosine( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_goode_homolosine( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_InterruptedGoodeHomolosine( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_interrupted_goode_homolosine( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_GeostationarySatelliteSweepX( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_geostationary_satellite_sweep_x( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_GeostationarySatelliteSweepY( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_geostationary_satellite_sweep_y( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Gnomonic( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_gnomonic( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_HotineObliqueMercatorVariantA( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, "Degree", - 0.0174532925199433, "Metre", 1.0); + proj_obj_create_conversion_hotine_oblique_mercator_variant_a( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, + "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_HotineObliqueMercatorVariantB( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, "Degree", - 0.0174532925199433, "Metre", 1.0); + proj_obj_create_conversion_hotine_oblique_mercator_variant_b( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, + "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_HotineObliqueMercatorTwoPointNaturalOrigin( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, 0, "Degree", - 0.0174532925199433, "Metre", 1.0); + proj_obj_create_conversion_hotine_oblique_mercator_two_point_natural_origin( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, + "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_InternationalMapWorldPolyconic( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_international_map_world_polyconic( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_KrovakNorthOriented( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_krovak_north_oriented( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Krovak( - geogCRS, nullptr, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_krovak( + m_ctxt, 0, 0, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", + 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_LambertAzimuthalEqualArea( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_lambert_azimuthal_equal_area( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_MillerCylindrical( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_miller_cylindrical( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_MercatorVariantA( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_mercator_variant_a( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_MercatorVariantB( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_mercator_variant_b( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_PopularVisualisationPseudoMercator( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_popular_visualisation_pseudo_mercator( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Mollweide( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_mollweide( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_NewZealandMappingGrid( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_new_zealand_mapping_grid( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_ObliqueStereographic( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_oblique_stereographic( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Orthographic( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_orthographic( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_AmericanPolyconic( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_american_polyconic( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_PolarStereographicVariantA( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_polar_stereographic_variant_a( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_PolarStereographicVariantB( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_polar_stereographic_variant_b( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Robinson( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_robinson( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Sinusoidal( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_sinusoidal( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_Stereographic( - geogCRS, nullptr, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + auto projCRS = proj_obj_create_conversion_stereographic( + m_ctxt, 0, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_VanDerGrinten( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_van_der_grinten( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerI( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_i( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerII( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_ii( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerIII( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_iii( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerIV( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_iv( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerV( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_v( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerVI( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_vi( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_WagnerVII( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_wagner_vii( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { auto projCRS = - proj_obj_create_projected_crs_QuadrilateralizedSphericalCube( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, - "Metre", 1.0); + proj_obj_create_conversion_quadrilateralized_spherical_cube( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_SphericalCrossTrackHeight( - geogCRS, nullptr, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_spherical_cross_track_height( + m_ctxt, 0, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } { - auto projCRS = proj_obj_create_projected_crs_EqualEarth( - geogCRS, nullptr, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", - 1.0); + auto projCRS = proj_obj_create_conversion_equal_earth( + m_ctxt, 0, 0, 0, "Degree", 0.0174532925199433, "Metre", 1.0); ObjectKeeper keeper_projCRS(projCRS); ASSERT_NE(projCRS, nullptr); } /* END: Generated by scripts/create_c_api_projections.py*/ } +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_cs_get_axis_info) { + { + auto crs = proj_obj_create_from_database( + m_ctxt, "EPSG", "4326", PJ_OBJ_CATEGORY_CRS, false, nullptr); + ASSERT_NE(crs, nullptr); + ObjectKeeper keeper(crs); + + auto cs = proj_obj_crs_get_coordinate_system(m_ctxt, crs); + ASSERT_NE(cs, nullptr); + ObjectKeeper keeperCs(cs); + + EXPECT_EQ(proj_obj_cs_get_type(m_ctxt, cs), PJ_CS_TYPE_ELLIPSOIDAL); + + EXPECT_EQ(proj_obj_cs_get_axis_count(m_ctxt, cs), 2); + + EXPECT_FALSE(proj_obj_cs_get_axis_info(m_ctxt, cs, -1, nullptr, nullptr, + nullptr, nullptr, nullptr)); + + EXPECT_FALSE(proj_obj_cs_get_axis_info(m_ctxt, cs, 2, nullptr, nullptr, + nullptr, nullptr, nullptr)); + + EXPECT_TRUE(proj_obj_cs_get_axis_info(m_ctxt, cs, 0, nullptr, nullptr, + nullptr, nullptr, nullptr)); + + const char *name = nullptr; + const char *abbrev = nullptr; + const char *direction = nullptr; + double unitConvFactor = 0.0; + const char *unitName = nullptr; + + EXPECT_TRUE(proj_obj_cs_get_axis_info(m_ctxt, cs, 0, &name, &abbrev, + &direction, &unitConvFactor, + &unitName)); + ASSERT_NE(name, nullptr); + ASSERT_NE(abbrev, nullptr); + ASSERT_NE(direction, nullptr); + ASSERT_NE(unitName, nullptr); + EXPECT_EQ(std::string(name), "Geodetic latitude"); + EXPECT_EQ(std::string(abbrev), "Lat"); + EXPECT_EQ(std::string(direction), "north"); + EXPECT_EQ(unitConvFactor, 0.017453292519943295) << unitConvFactor; + EXPECT_EQ(std::string(unitName), "degree"); + } + + // Non CRS object + { + auto obj = proj_obj_create_from_database( + m_ctxt, "EPSG", "1170", PJ_OBJ_CATEGORY_COORDINATE_OPERATION, false, + nullptr); + ASSERT_NE(obj, nullptr); + ObjectKeeper keeper(obj); + EXPECT_EQ(proj_obj_crs_get_coordinate_system(m_ctxt, obj), nullptr); + + EXPECT_EQ(proj_obj_cs_get_type(m_ctxt, obj), PJ_CS_TYPE_UNKNOWN); + + EXPECT_EQ(proj_obj_cs_get_axis_count(m_ctxt, obj), -1); + + EXPECT_FALSE(proj_obj_cs_get_axis_info(m_ctxt, obj, 0, nullptr, nullptr, + nullptr, nullptr, nullptr)); + } +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_context_get_database_metadata) { + EXPECT_TRUE(proj_context_get_database_metadata(m_ctxt, "IGNF.VERSION") != + nullptr); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_clone) { + auto obj = + proj_obj_create_from_proj_string(m_ctxt, "+proj=longlat", nullptr); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto clone = proj_obj_clone(m_ctxt, obj); + ObjectKeeper keeperClone(clone); + ASSERT_NE(clone, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(obj, clone, PJ_COMP_STRICT)); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_crs_alter_geodetic_crs) { + auto projCRS = proj_obj_create_from_wkt( + m_ctxt, + createProjectedCRS()->exportToWKT(WKTFormatter::create().get()).c_str(), + nullptr); + ObjectKeeper keeper(projCRS); + ASSERT_NE(projCRS, nullptr); + + auto newGeodCRS = + proj_obj_create_from_proj_string(m_ctxt, "+proj=longlat", nullptr); + ObjectKeeper keeper_newGeodCRS(newGeodCRS); + ASSERT_NE(newGeodCRS, nullptr); + + auto geodCRS = proj_obj_crs_get_geodetic_crs(m_ctxt, projCRS); + ObjectKeeper keeper_geodCRS(geodCRS); + ASSERT_NE(geodCRS, nullptr); + + auto geodCRSAltered = + proj_obj_crs_alter_geodetic_crs(m_ctxt, geodCRS, newGeodCRS); + ObjectKeeper keeper_geodCRSAltered(geodCRSAltered); + ASSERT_NE(geodCRSAltered, nullptr); + EXPECT_TRUE( + proj_obj_is_equivalent_to(geodCRSAltered, newGeodCRS, PJ_COMP_STRICT)); + + auto projCRSAltered = + proj_obj_crs_alter_geodetic_crs(m_ctxt, projCRS, newGeodCRS); + ObjectKeeper keeper_projCRSAltered(projCRSAltered); + ASSERT_NE(projCRSAltered, nullptr); + + EXPECT_EQ(proj_obj_get_type(projCRSAltered), PJ_OBJ_TYPE_PROJECTED_CRS); + + auto projCRSAltered_geodCRS = + proj_obj_crs_get_geodetic_crs(m_ctxt, projCRSAltered); + ObjectKeeper keeper_projCRSAltered_geodCRS(projCRSAltered_geodCRS); + ASSERT_NE(projCRSAltered_geodCRS, nullptr); + + EXPECT_TRUE(proj_obj_is_equivalent_to(projCRSAltered_geodCRS, newGeodCRS, + PJ_COMP_STRICT)); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_crs_alter_cs_angular_unit) { + auto crs = proj_obj_create_from_wkt( + m_ctxt, + GeographicCRS::EPSG_4326->exportToWKT(WKTFormatter::create().get()) + .c_str(), + nullptr); + ObjectKeeper keeper(crs); + ASSERT_NE(crs, nullptr); + + auto alteredCRS = + proj_obj_crs_alter_cs_angular_unit(m_ctxt, crs, "my unit", 2); + ObjectKeeper keeper_alteredCRS(alteredCRS); + ASSERT_NE(alteredCRS, nullptr); + + auto cs = proj_obj_crs_get_coordinate_system(m_ctxt, alteredCRS); + ASSERT_NE(cs, nullptr); + ObjectKeeper keeperCs(cs); + double unitConvFactor = 0.0; + const char *unitName = nullptr; + + EXPECT_TRUE(proj_obj_cs_get_axis_info(m_ctxt, cs, 0, nullptr, nullptr, + nullptr, &unitConvFactor, &unitName)); + ASSERT_NE(unitName, nullptr); + EXPECT_EQ(unitConvFactor, 2) << unitConvFactor; + EXPECT_EQ(std::string(unitName), "my unit"); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_crs_alter_cs_linear_unit) { + auto crs = proj_obj_create_from_wkt( + m_ctxt, + createProjectedCRS()->exportToWKT(WKTFormatter::create().get()).c_str(), + nullptr); + ObjectKeeper keeper(crs); + ASSERT_NE(crs, nullptr); + + auto alteredCRS = + proj_obj_crs_alter_cs_linear_unit(m_ctxt, crs, "my unit", 2); + ObjectKeeper keeper_alteredCRS(alteredCRS); + ASSERT_NE(alteredCRS, nullptr); + + auto cs = proj_obj_crs_get_coordinate_system(m_ctxt, alteredCRS); + ASSERT_NE(cs, nullptr); + ObjectKeeper keeperCs(cs); + double unitConvFactor = 0.0; + const char *unitName = nullptr; + + EXPECT_TRUE(proj_obj_cs_get_axis_info(m_ctxt, cs, 0, nullptr, nullptr, + nullptr, &unitConvFactor, &unitName)); + ASSERT_NE(unitName, nullptr); + EXPECT_EQ(unitConvFactor, 2) << unitConvFactor; + EXPECT_EQ(std::string(unitName), "my unit"); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_crs_alter_parameters_linear_unit) { + auto crs = proj_obj_create_from_wkt( + m_ctxt, + createProjectedCRS()->exportToWKT(WKTFormatter::create().get()).c_str(), + nullptr); + ObjectKeeper keeper(crs); + ASSERT_NE(crs, nullptr); + + { + auto alteredCRS = proj_obj_crs_alter_parameters_linear_unit( + m_ctxt, crs, "my unit", 2, false); + ObjectKeeper keeper_alteredCRS(alteredCRS); + ASSERT_NE(alteredCRS, nullptr); + + auto wkt = proj_obj_as_wkt(m_ctxt, alteredCRS, PJ_WKT2_2018, nullptr); + ASSERT_NE(wkt, nullptr); + EXPECT_TRUE(std::string(wkt).find("500000") != std::string::npos) + << wkt; + EXPECT_TRUE(std::string(wkt).find("\"my unit\",2") != std::string::npos) + << wkt; + } + + { + auto alteredCRS = proj_obj_crs_alter_parameters_linear_unit( + m_ctxt, crs, "my unit", 2, true); + ObjectKeeper keeper_alteredCRS(alteredCRS); + ASSERT_NE(alteredCRS, nullptr); + + auto wkt = proj_obj_as_wkt(m_ctxt, alteredCRS, PJ_WKT2_2018, nullptr); + ASSERT_NE(wkt, nullptr); + EXPECT_TRUE(std::string(wkt).find("250000") != std::string::npos) + << wkt; + EXPECT_TRUE(std::string(wkt).find("\"my unit\",2") != std::string::npos) + << wkt; + } +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_create_engineering_crs) { + + auto crs = proj_obj_create_engineering_crs(m_ctxt, "name"); + ObjectKeeper keeper(crs); + ASSERT_NE(crs, nullptr); + auto wkt = proj_obj_as_wkt(m_ctxt, crs, PJ_WKT1_GDAL, nullptr); + ASSERT_NE(wkt, nullptr); + EXPECT_EQ(std::string(wkt), "LOCAL_CS[\"name\"]") << wkt; +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_alter_name) { + + auto cs = proj_obj_create_ellipsoidal_2D_cs( + m_ctxt, PJ_ELLPS2D_LONGITUDE_LATITUDE, nullptr, 0); + ObjectKeeper keeper_cs(cs); + ASSERT_NE(cs, nullptr); + + auto obj = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, cs); + ObjectKeeper keeper(obj); + ASSERT_NE(obj, nullptr); + + auto alteredObj = proj_obj_alter_name(m_ctxt, obj, "new name"); + ObjectKeeper keeper_alteredObj(alteredObj); + ASSERT_NE(alteredObj, nullptr); + + EXPECT_EQ(std::string(proj_obj_get_name(alteredObj)), "new name"); +} + +// --------------------------------------------------------------------------- + +TEST_F(CApi, proj_obj_create_projected_crs) { + + PJ_PARAM_DESCRIPTION param; + param.name = "param name"; + param.auth_name = nullptr; + param.code = nullptr; + param.value = 0.99; + param.unit_name = nullptr; + param.unit_conv_factor = 1.0; + param.unit_type = PJ_UT_SCALE; + + auto conv = proj_obj_create_conversion(m_ctxt, "conv", "conv auth", + "conv code", "method", "method auth", + "method code", 1, ¶m); + ObjectKeeper keeper_conv(conv); + ASSERT_NE(conv, nullptr); + + auto geog_cs = proj_obj_create_ellipsoidal_2D_cs( + m_ctxt, PJ_ELLPS2D_LONGITUDE_LATITUDE, nullptr, 0); + ObjectKeeper keeper_geog_cs(geog_cs); + ASSERT_NE(geog_cs, nullptr); + + auto geogCRS = proj_obj_create_geographic_crs( + m_ctxt, "WGS 84", "World Geodetic System 1984", "WGS 84", 6378137, + 298.257223563, "Greenwich", 0.0, "Degree", 0.0174532925199433, geog_cs); + ObjectKeeper keeper_geogCRS(geogCRS); + ASSERT_NE(geogCRS, nullptr); + + auto cs = proj_obj_create_cartesian_2D_cs( + m_ctxt, PJ_CART2D_EASTING_NORTHING, nullptr, 0); + ObjectKeeper keeper_cs(cs); + ASSERT_NE(cs, nullptr); + + auto projCRS = + proj_obj_create_projected_crs(m_ctxt, "my CRS", geogCRS, conv, cs); + ObjectKeeper keeper_projCRS(projCRS); + ASSERT_NE(projCRS, nullptr); +} + } // namespace diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 55df5875..3f044de0 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -1107,6 +1107,9 @@ TEST(crs, geocentricCRS_as_WKT1_GDAL) { " AUTHORITY[\"EPSG\",\"8901\"]],\n" " UNIT[\"metre\",1,\n" " AUTHORITY[\"EPSG\",\"9001\"]],\n" + " AXIS[\"Geocentric X\",OTHER],\n" + " AXIS[\"Geocentric Y\",OTHER],\n" + " AXIS[\"Geocentric Z\",NORTH],\n" " AUTHORITY[\"EPSG\",\"4328\"]]"); } @@ -1213,6 +1216,23 @@ TEST(crs, geodeticcrs_identify_no_db) { EXPECT_EQ(res.front().first.get(), GeographicCRS::EPSG_4326.get()); EXPECT_EQ(res.front().second, 25); } + + { + // WKT1 identification + auto obj = + WKTParser() + .attachDatabaseContext(DatabaseContext::create()) + .createFromWKT( + "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\"," + "6378137,298.257223563]],PRIMEM[\"Greenwich\",0]," + "UNIT[\"Degree\",0.0174532925199433]]"); + auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(nullptr); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().first.get(), GeographicCRS::EPSG_4326.get()); + EXPECT_EQ(res.front().second, 100); + } } // --------------------------------------------------------------------------- @@ -1665,6 +1685,60 @@ TEST(crs, projectedCRS_as_WKT1_ESRI) { // --------------------------------------------------------------------------- +TEST(crs, projectedCRS_with_ESRI_code_as_WKT1_ESRI) { + auto dbContext = DatabaseContext::create(); + auto crs = AuthorityFactory::create(dbContext, "ESRI") + ->createProjectedCRS("102113"); + + // Comes literally from the text_definition column of + // projected_crs table + auto esri_wkt = + "PROJCS[\"WGS_1984_Web_Mercator\"," + "GEOGCS[\"GCS_WGS_1984_Major_Auxiliary_Sphere\"," + "DATUM[\"D_WGS_1984_Major_Auxiliary_Sphere\"," + "SPHEROID[\"WGS_1984_Major_Auxiliary_Sphere\",6378137.0,0.0]]," + "PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]]," + "PROJECTION[\"Mercator\"],PARAMETER[\"False_Easting\",0.0]," + "PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0]," + "PARAMETER[\"Standard_Parallel_1\",0.0],UNIT[\"Meter\",1.0]]"; + + EXPECT_EQ( + crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_ESRI, dbContext) + .get()), + esri_wkt); +} + +// --------------------------------------------------------------------------- + +TEST(crs, projectedCRS_from_WKT1_ESRI_as_WKT1_ESRI) { + auto dbContext = DatabaseContext::create(); + // Comes literally from the text_definition column of + // projected_crs table + auto esri_wkt = + "PROJCS[\"WGS_1984_Web_Mercator\"," + "GEOGCS[\"GCS_WGS_1984_Major_Auxiliary_Sphere\"," + "DATUM[\"D_WGS_1984_Major_Auxiliary_Sphere\"," + "SPHEROID[\"WGS_1984_Major_Auxiliary_Sphere\",6378137.0,0.0]]," + "PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]]," + "PROJECTION[\"Mercator\"],PARAMETER[\"False_Easting\",0.0]," + "PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0]," + "PARAMETER[\"Standard_Parallel_1\",0.0],UNIT[\"Meter\",1.0]]"; + + auto obj = + WKTParser().attachDatabaseContext(dbContext).createFromWKT(esri_wkt); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + EXPECT_EQ( + crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_ESRI, dbContext) + .get()), + esri_wkt); +} + +// --------------------------------------------------------------------------- + TEST(crs, projectedCRS_as_PROJ_string) { auto crs = createProjected(); EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()), @@ -1890,6 +1964,93 @@ TEST(crs, projectedCRS_identify_db) { EXPECT_EQ(res.front().second, 70); } { + // Identify from a WKT1 string wit explicit correct axis order + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT( + "PROJCS[\"ETRS89 / UTM zone 32N (N-E)\",GEOGCS[\"ETRS89\"," + "DATUM[\"European_Terrestrial_Reference_System_1989\"," + "SPHEROID[\"GRS 1980\",6378137,298.257222101]]," + "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]," + "PROJECTION[\"Transverse_Mercator\"]," + "PARAMETER[\"latitude_of_origin\",0]," + "PARAMETER[\"central_meridian\",9]," + "PARAMETER[\"scale_factor\",0.9996]," + "PARAMETER[\"false_easting\",500000]," + "PARAMETER[\"false_northing\",0]," + "UNIT[\"metre\",1]," + "AXIS[\"Northing\",NORTH],AXIS[\"Easting\",EAST]]"); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(factoryEPSG); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().first->getEPSGCode(), 3044); + EXPECT_EQ(res.front().second, 100); + } + { + // Identify from a WKT1 string wit wrong axis order + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT( + "PROJCS[\"ETRS89 / UTM zone 32N (N-E)\",GEOGCS[\"ETRS89\"," + "DATUM[\"European_Terrestrial_Reference_System_1989\"," + "SPHEROID[\"GRS 1980\",6378137,298.257222101]]," + "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]," + "PROJECTION[\"Transverse_Mercator\"]," + "PARAMETER[\"latitude_of_origin\",0]," + "PARAMETER[\"central_meridian\",9]," + "PARAMETER[\"scale_factor\",0.9996]," + "PARAMETER[\"false_easting\",500000]," + "PARAMETER[\"false_northing\",0]," + "UNIT[\"metre\",1]," + "AXIS[\"Easting\",EAST], AXIS[\"Northing\",NORTH]]"); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(factoryEPSG); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().first->getEPSGCode(), 3044); + EXPECT_EQ(res.front().second, 25); + } + { + // Identify from a WKT1 string, without explicit axis + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT( + "PROJCS[\"ETRS89 / UTM zone 32N (N-E)\",GEOGCS[\"ETRS89\"," + "DATUM[\"European_Terrestrial_Reference_System_1989\"," + "SPHEROID[\"GRS 1980\",6378137,298.257222101]]," + "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]," + "PROJECTION[\"Transverse_Mercator\"]," + "PARAMETER[\"latitude_of_origin\",0]," + "PARAMETER[\"central_meridian\",9]," + "PARAMETER[\"scale_factor\",0.9996]," + "PARAMETER[\"false_easting\",500000]," + "PARAMETER[\"false_northing\",0]," + "UNIT[\"metre\",1]]"); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(factoryEPSG); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().first->getEPSGCode(), 3044); + EXPECT_EQ(res.front().second, 100); + } + { + // Identify from a WKT ESRI with bad PROJCS and GEOGCS names. + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT( + "PROJCS[\"Lambert Conformal Conic\",GEOGCS[\"grs80\"," + "DATUM[\"D_North_American_1983\"," + "SPHEROID[\"Geodetic_Reference_System_1980\"," + "6378137,298.257222101]],PRIMEM[\"Greenwich\",0]," + "UNIT[\"Degree\",0.017453292519943295]]," + "PROJECTION[\"Lambert_Conformal_Conic\"]," + "PARAMETER[\"standard_parallel_1\",34.33333333333334]," + "PARAMETER[\"standard_parallel_2\",36.16666666666666]," + "PARAMETER[\"latitude_of_origin\",33.75]," + "PARAMETER[\"central_meridian\",-79]," + "PARAMETER[\"false_easting\",609601.22]," + "PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]]"); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(factoryEPSG); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().first->getEPSGCode(), 32119); + EXPECT_EQ(res.front().second, 70); + } + { // No equivalent CRS to input one in result set auto obj = PROJStringParser().createFromPROJString("+proj=tmerc +datum=WGS84"); @@ -3407,6 +3568,40 @@ TEST(crs, boundCRS_identify_db) { "NZGD2000 to WGS 84 (1)"); EXPECT_EQ(res.front().second, 50); } + + { + // WKT has EPSG code but the definition doesn't match with the official + // one (namely linear units are different) + // https://github.com/OSGeo/gdal/issues/990 + // Also test that we can handle the synthetic Null geographic offset + // between NAD83 and WGS84 + auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT( + "PROJCS[\"NAD83 / Ohio North\",GEOGCS[\"NAD83\"," + "DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\"," + "6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]]," + "TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]]," + "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]]," + "UNIT[\"degree\",0.0174532925199433, AUTHORITY[\"EPSG\",\"9122\"]]," + "AUTHORITY[\"EPSG\",\"4269\"]]," + "PROJECTION[\"Lambert_Conformal_Conic_2SP\"]," + "PARAMETER[\"standard_parallel_1\",41.7]," + "PARAMETER[\"standard_parallel_2\",40.43333333333333]," + "PARAMETER[\"latitude_of_origin\",39.66666666666666]," + "PARAMETER[\"central_meridian\",-82.5]," + "PARAMETER[\"false_easting\",1968503.937007874]," + "PARAMETER[\"false_northing\",0]," + "UNIT[\"International Foot\",0.3048,AUTHORITY[\"EPSG\",\"9002\"]]," + "AXIS[\"X\",EAST],AXIS[\"Y\",NORTH],AUTHORITY[\"EPSG\",\"32122\"]" + "]"); + auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto res = crs->identify(factoryEPSG); + ASSERT_EQ(res.size(), 1); + EXPECT_EQ(res.front().second, 25); + auto wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()); + EXPECT_TRUE(wkt.find("32122") != std::string::npos) << wkt; + } } // --------------------------------------------------------------------------- @@ -4662,3 +4857,136 @@ TEST(crs, crs_stripVerticalComponent) { EXPECT_EQ(projCRS->coordinateSystem()->axisList().size(), 2); } } + +// --------------------------------------------------------------------------- + +TEST(crs, crs_alterGeodeticCRS) { + + { + auto crs = GeographicCRS::EPSG_4326->alterGeodeticCRS( + GeographicCRS::EPSG_4979); + EXPECT_TRUE(crs->isEquivalentTo(GeographicCRS::EPSG_4979.get())); + } + + { + auto crs = + createProjected()->alterGeodeticCRS(GeographicCRS::EPSG_4979); + auto projCRS = dynamic_cast<ProjectedCRS *>(crs.get()); + ASSERT_TRUE(projCRS != nullptr); + EXPECT_TRUE( + projCRS->baseCRS()->isEquivalentTo(GeographicCRS::EPSG_4979.get())); + } + + { + auto crs = + createCompoundCRS()->alterGeodeticCRS(GeographicCRS::EPSG_4979); + auto compoundCRS = dynamic_cast<CompoundCRS *>(crs.get()); + ASSERT_TRUE(compoundCRS != nullptr); + EXPECT_TRUE(compoundCRS->componentReferenceSystems()[0] + ->extractGeographicCRS() + ->isEquivalentTo(GeographicCRS::EPSG_4979.get())); + } + + { + auto crs = + createVerticalCRS()->alterGeodeticCRS(GeographicCRS::EPSG_4979); + EXPECT_TRUE(crs->isEquivalentTo(createVerticalCRS().get())); + } +} + +// --------------------------------------------------------------------------- + +TEST(crs, crs_alterCSLinearUnit) { + + { + auto crs = + createProjected()->alterCSLinearUnit(UnitOfMeasure("my unit", 2)); + auto projCRS = dynamic_cast<ProjectedCRS *>(crs.get()); + ASSERT_TRUE(projCRS != nullptr); + auto cs = projCRS->coordinateSystem(); + ASSERT_EQ(cs->axisList().size(), 2U); + EXPECT_EQ(cs->axisList()[0]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[0]->unit().conversionToSI(), 2); + EXPECT_EQ(cs->axisList()[1]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[1]->unit().conversionToSI(), 2); + } + + { + auto crs = GeodeticCRS::EPSG_4978->alterCSLinearUnit( + UnitOfMeasure("my unit", 2)); + auto geodCRS = dynamic_cast<GeodeticCRS *>(crs.get()); + ASSERT_TRUE(geodCRS != nullptr); + auto cs = + dynamic_cast<CartesianCS *>(geodCRS->coordinateSystem().get()); + ASSERT_EQ(cs->axisList().size(), 3U); + EXPECT_EQ(cs->axisList()[0]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[0]->unit().conversionToSI(), 2); + EXPECT_EQ(cs->axisList()[1]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[1]->unit().conversionToSI(), 2); + EXPECT_EQ(cs->axisList()[2]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[2]->unit().conversionToSI(), 2); + } + + { + auto crs = GeographicCRS::EPSG_4979->alterCSLinearUnit( + UnitOfMeasure("my unit", 2)); + auto geogCRS = dynamic_cast<GeographicCRS *>(crs.get()); + ASSERT_TRUE(geogCRS != nullptr); + auto cs = geogCRS->coordinateSystem(); + ASSERT_EQ(cs->axisList().size(), 3U); + EXPECT_NE(cs->axisList()[0]->unit().name(), "my unit"); + EXPECT_NE(cs->axisList()[0]->unit().conversionToSI(), 2); + EXPECT_NE(cs->axisList()[1]->unit().name(), "my unit"); + EXPECT_NE(cs->axisList()[1]->unit().conversionToSI(), 2); + EXPECT_EQ(cs->axisList()[2]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[2]->unit().conversionToSI(), 2); + } + + { + auto crs = + createVerticalCRS()->alterCSLinearUnit(UnitOfMeasure("my unit", 2)); + auto vertCRS = dynamic_cast<VerticalCRS *>(crs.get()); + ASSERT_TRUE(vertCRS != nullptr); + auto cs = vertCRS->coordinateSystem(); + ASSERT_EQ(cs->axisList().size(), 1U); + EXPECT_EQ(cs->axisList()[0]->unit().name(), "my unit"); + EXPECT_EQ(cs->axisList()[0]->unit().conversionToSI(), 2); + } + + { + // Not implemented on compoundCRS + auto crs = + createCompoundCRS()->alterCSLinearUnit(UnitOfMeasure("my unit", 2)); + EXPECT_TRUE(createCompoundCRS()->isEquivalentTo(crs.get())); + } +} + +// --------------------------------------------------------------------------- + +TEST(crs, alterParametersLinearUnit) { + { + auto crs = createProjected()->alterParametersLinearUnit( + UnitOfMeasure("my unit", 2), false); + auto wkt = + crs->exportToWKT(&WKTFormatter::create()->setMultiLine(false)); + EXPECT_TRUE(wkt.find("PARAMETER[\"Longitude of natural origin\",3") != + std::string::npos) + << wkt; + EXPECT_TRUE( + wkt.find( + "PARAMETER[\"False easting\",500000,UNIT[\"my unit\",2]") != + std::string::npos) + << wkt; + } + { + auto crs = createProjected()->alterParametersLinearUnit( + UnitOfMeasure("my unit", 2), true); + auto wkt = + crs->exportToWKT(&WKTFormatter::create()->setMultiLine(false)); + EXPECT_TRUE( + wkt.find( + "PARAMETER[\"False easting\",250000,UNIT[\"my unit\",2]") != + std::string::npos) + << wkt; + } +} diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp index 739bb729..7cdb0b40 100644 --- a/test/unit/test_factory.cpp +++ b/test/unit/test_factory.cpp @@ -2703,6 +2703,13 @@ TEST(factory, createObjectsFromName) { .size(), 1); + // Deprecated object (but without explicit deprecated) + EXPECT_EQ( + factoryEPSG + ->createObjectsFromName("NAD27(CGQ77) / SCoPQ zone 2", {}, false, 2) + .size(), + 1); + const auto types = std::vector<AuthorityFactory::ObjectType>{ AuthorityFactory::ObjectType::PRIME_MERIDIAN, AuthorityFactory::ObjectType::ELLIPSOID, @@ -2729,4 +2736,14 @@ TEST(factory, createObjectsFromName) { factory->createObjectsFromName("i_dont_exist", types, false, 1); } +// --------------------------------------------------------------------------- + +TEST(factory, getMetadata) { + auto ctxt = DatabaseContext::create(); + EXPECT_EQ(ctxt->getMetadata("i_do_not_exist"), nullptr); + const char *IGNF_VERSION = ctxt->getMetadata("IGNF.VERSION"); + ASSERT_TRUE(IGNF_VERSION != nullptr); + EXPECT_EQ(std::string(IGNF_VERSION), "3.0.2"); +} + } // namespace diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index 26597f09..606d57a3 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -119,6 +119,11 @@ TEST(io, wkt_parsing) { str = "A[" + str + "]"; } EXPECT_THROW(WKTNode::createFrom(str), ParsingException); + + { + auto wkt = "A[\"a\",B[\"b\",C[\"c\"]],D[\"d\"]]"; + EXPECT_EQ(WKTNode::createFrom(wkt)->toString(), wkt); + } } // --------------------------------------------------------------------------- @@ -401,6 +406,33 @@ TEST(wkt_parse, wkt1_EPSG_4326) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_EPSG_4267) { + auto obj = + WKTParser() + .attachDatabaseContext(DatabaseContext::create()) + .createFromWKT( + "GEOGCS[\"NAD27\"," + " DATUM[\"North_American_Datum_1927\"," + " SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898," + " AUTHORITY[\"EPSG\",\"7008\"]]," + " AUTHORITY[\"EPSG\",\"6267\"]]," + " PRIMEM[\"Greenwich\",0," + " AUTHORITY[\"EPSG\",\"8901\"]]," + " UNIT[\"degree\",0.0174532925199433," + " AUTHORITY[\"EPSG\",\"9122\"]]," + " AUTHORITY[\"EPSG\",\"4267\"]]"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + auto datum = crs->datum(); + ASSERT_EQ(datum->identifiers().size(), 1); + EXPECT_EQ(datum->identifiers()[0]->code(), "6267"); + EXPECT_EQ(*(datum->identifiers()[0]->codeSpace()), "EPSG"); + EXPECT_EQ(datum->nameStr(), "North American Datum 1927"); +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, wkt1_EPSG_4807_grad_mess) { auto obj = WKTParser().createFromWKT( "GEOGCS[\"NTF (Paris)\",\n" @@ -493,6 +525,9 @@ TEST(wkt_parse, wkt1_geocentric_with_PROJ4_extension) { " SPHEROID[\"WGS84\",6378137,298.257223563]],\n" " PRIMEM[\"Greenwich\",0],\n" " UNIT[\"Meter\",1],\n" + " AXIS[\"Geocentric X\",OTHER],\n" + " AXIS[\"Geocentric Y\",OTHER],\n" + " AXIS[\"Geocentric Z\",NORTH],\n" " EXTENSION[\"PROJ4\",\"+proj=geocent +foo=bar +wktext\"]]"; auto obj = WKTParser().createFromWKT(wkt); @@ -768,6 +803,28 @@ TEST(wkt_parse, wkt1_geocentric) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_geocentric_with_z_OTHER) { + auto wkt = "GEOCCS[\"WGS 84 (geocentric)\",\n" + " DATUM[\"WGS_1984\",\n" + " SPHEROID[\"WGS 84\",6378137,298.257223563,\n" + " AUTHORITY[\"EPSG\",\"7030\"]],\n" + " AUTHORITY[\"EPSG\",\"6326\"]],\n" + " PRIMEM[\"Greenwich\",0,\n" + " AUTHORITY[\"EPSG\",\"8901\"]],\n" + " UNIT[\"metre\",1,\n" + " AUTHORITY[\"EPSG\",9001]],\n" + " AXIS[\"Geocentric X\",OTHER],\n" + " AXIS[\"Geocentric Y\",OTHER],\n" + " AXIS[\"Geocentric Z\",OTHER],\n" + " AUTHORITY[\"EPSG\",\"4328\"]]"; + auto obj = WKTParser().createFromWKT(wkt); + auto crs = nn_dynamic_pointer_cast<GeodeticCRS>(obj); + ASSERT_TRUE(crs != nullptr); + checkGeocentric(crs); +} + +// --------------------------------------------------------------------------- + static void checkProjected(ProjectedCRSPtr crs, bool checkEPSGCodes = true) { EXPECT_EQ(crs->nameStr(), "WGS 84 / UTM zone 31N"); ASSERT_EQ(crs->identifiers().size(), 1); @@ -966,6 +1023,33 @@ TEST(wkt_parse, wkt1_projected_with_PROJ4_extension) { // --------------------------------------------------------------------------- +TEST(wkt_parse, wkt1_Mercator_1SP_with_latitude_origin_0) { + auto wkt = "PROJCS[\"unnamed\",\n" + " GEOGCS[\"WGS 84\",\n" + " DATUM[\"unknown\",\n" + " SPHEROID[\"WGS84\",6378137,298.257223563]],\n" + " PRIMEM[\"Greenwich\",0],\n" + " UNIT[\"degree\",0.0174532925199433]],\n" + " PROJECTION[\"Mercator_1SP\"],\n" + " PARAMETER[\"latitude_of_origin\",0],\n" + " PARAMETER[\"central_meridian\",0],\n" + " PARAMETER[\"scale_factor\",1],\n" + " PARAMETER[\"false_easting\",0],\n" + " PARAMETER[\"false_northing\",0],\n" + " UNIT[\"Meter\",1],\n" + " AXIS[\"Easting\",EAST],\n" + " AXIS[\"Northing\",NORTH]]"; + auto obj = WKTParser().createFromWKT(wkt); + + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + auto got_wkt = crs->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()); + EXPECT_TRUE(got_wkt.find("Mercator_1SP") != std::string::npos) << got_wkt; +} + +// --------------------------------------------------------------------------- + TEST(wkt_parse, wkt1_krovak_south_west) { auto wkt = "PROJCS[\"S-JTSK / Krovak\"," @@ -2641,9 +2725,10 @@ TEST(wkt_parse, LOCAL_CS_short) { // --------------------------------------------------------------------------- -TEST(wkt_parse, LOCAL_CS_long_one_aix) { +TEST(wkt_parse, LOCAL_CS_long_one_axis) { auto wkt = "LOCAL_CS[\"Engineering CRS\",\n" " LOCAL_DATUM[\"Engineering datum\",12345],\n" + " UNIT[\"meter\",1],\n" " AXIS[\"height\",up]]"; auto obj = WKTParser().createFromWKT(wkt); @@ -2661,6 +2746,7 @@ TEST(wkt_parse, LOCAL_CS_long_one_aix) { TEST(wkt_parse, LOCAL_CS_long_two_axis) { auto wkt = "LOCAL_CS[\"Engineering CRS\",\n" " LOCAL_DATUM[\"Engineering datum\",12345],\n" + " UNIT[\"meter\",1],\n" " AXIS[\"Easting\",EAST],\n" " AXIS[\"Northing\",NORTH]]"; @@ -4139,7 +4225,7 @@ TEST(wkt_parse, invalid_GEOGCS) { TEST(wkt_parse, invalid_UNIT) { std::string startWKT("GEODCRS[\"x\",DATUM[\"x\",SPHEROID[\"x\",1,0.5]],CS[" "ellipsoidal,2],AXIS[\"latitude\",north],AXIS[" - "\"longitude\",east,"); + "\"longitude\",east],"); EXPECT_NO_THROW(WKTParser().createFromWKT( startWKT + "UNIT[\"degree\",0.0174532925199433]]]")); @@ -4228,31 +4314,35 @@ TEST(wkt_parse, invalid_CS_of_GEODCRS) { // CS: OK EXPECT_NO_THROW(WKTParser().createFromWKT( startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north],AXIS[" - "\"longitude\",east]]")); + "\"longitude\",east],UNIT[\"degree\",0.0174532925199433]]")); // CS: Cartesian with 2 axis unexpected - EXPECT_THROW(WKTParser().createFromWKT(startWKT + - ",CS[Cartesian,2],AXIS[\"latitude\"," - "north],AXIS[\"longitude\",east]]"), + EXPECT_THROW(WKTParser().createFromWKT( + startWKT + ",CS[Cartesian,2],AXIS[\"latitude\"," + "north],AXIS[\"longitude\",east]," + "UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // CS: missing axis EXPECT_THROW(WKTParser().createFromWKT( - startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north]]"), + startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north]," + "UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // not enough children in AXIS EXPECT_THROW( WKTParser().createFromWKT( startWKT + - ",CS[ellipsoidal,2],AXIS[\"latitude\",north],AXIS[\"longitude\"]]"), + ",CS[ellipsoidal,2],AXIS[\"latitude\",north],AXIS[\"longitude\"]," + "UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // not enough children in ORDER EXPECT_THROW(WKTParser().createFromWKT( startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north,ORDER[]],AXIS[" - "\"longitude\",east]]"), + "\"longitude\",east]," + "UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // invalid value in ORDER @@ -4260,7 +4350,7 @@ TEST(wkt_parse, invalid_CS_of_GEODCRS) { WKTParser().createFromWKT( startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north,ORDER[\"x\"]],AXIS[" - "\"longitude\",east]]"), + "\"longitude\",east],UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // unexpected ORDER value @@ -4268,7 +4358,7 @@ TEST(wkt_parse, invalid_CS_of_GEODCRS) { WKTParser().createFromWKT( startWKT + ",CS[ellipsoidal,2],AXIS[\"latitude\",north,ORDER[2]],AXIS[" - "\"longitude\",east]]"), + "\"longitude\",east],UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // Invalid CS type @@ -4794,7 +4884,8 @@ TEST(wkt_parse, invalid_DerivedGeographicCRS) { " METHOD[\"bar\"]],\n" " CS[ellipsoidal,2],\n" " AXIS[\"latitude\",north],\n" - " AXIS[\"longitude\",east]]")); + " AXIS[\"longitude\",east],\n" + " UNIT[\"degree\",0.0174532925199433]]")); // Missing DERIVINGCONVERSION EXPECT_THROW( @@ -4805,7 +4896,8 @@ TEST(wkt_parse, invalid_DerivedGeographicCRS) { " ELLIPSOID[\"WGS 84\",6378137,298.257223563]]],\n" " CS[ellipsoidal,2],\n" " AXIS[\"latitude\",north],\n" - " AXIS[\"longitude\",east]]"), + " AXIS[\"longitude\",east],\n" + " UNIT[\"degree\",0.0174532925199433]]"), ParsingException); // Missing CS @@ -4982,18 +5074,20 @@ TEST(wkt_parse, invalid_LOCAL_CS) { TEST(wkt_parse, invalid_ParametricCRS) { - EXPECT_NO_THROW( - WKTParser().createFromWKT("PARAMETRICCRS[\"name\",\n" - " PDATUM[\"name\"],\n" - " CS[parametric,1],\n" - " AXIS[\"time (T)\",future]]")); + EXPECT_NO_THROW(WKTParser().createFromWKT( + "PARAMETRICCRS[\"name\",\n" + " PDATUM[\"name\"],\n" + " CS[parametric,1],\n" + " AXIS[\"pressure (hPa)\",up,\n" + " PARAMETRICUNIT[\"HectoPascal\",100]]]")); // Missing PDATUM - EXPECT_THROW( - WKTParser().createFromWKT("PARAMETRICCRS[\"name\",\n" - " CS[parametric,1],\n" - " AXIS[\"time (T)\",future]]"), - ParsingException); + EXPECT_THROW(WKTParser().createFromWKT( + "PARAMETRICCRS[\"name\",\n" + " CS[parametric,1],\n" + " AXIS[\"pressure (hPa)\",up,\n" + " PARAMETRICUNIT[\"HectoPascal\",100]]]"), + ParsingException); // Missing CS EXPECT_THROW(WKTParser().createFromWKT("PARAMETRICCRS[\"name\",\n" @@ -5001,13 +5095,15 @@ TEST(wkt_parse, invalid_ParametricCRS) { ParsingException); // Invalid number of axis for CS - EXPECT_THROW( - WKTParser().createFromWKT("PARAMETRICCRS[\"name\",\n" - " PDATUM[\"name\"],\n" - " CS[parametric,2],\n" - " AXIS[\"time (T)\",future],\n" - " AXIS[\"time (T)\",future]]"), - ParsingException); + EXPECT_THROW(WKTParser().createFromWKT( + "PARAMETRICCRS[\"name\",\n" + " PDATUM[\"name\"],\n" + " CS[parametric,2],\n" + " AXIS[\"pressure (hPa)\",up,\n" + " PARAMETRICUNIT[\"HectoPascal\",100]]" + " AXIS[\"pressure (hPa)\",up,\n" + " PARAMETRICUNIT[\"HectoPascal\",100]]]"), + ParsingException); // Invalid CS type EXPECT_THROW( @@ -5034,7 +5130,8 @@ TEST(wkt_parse, invalid_DERIVEDPROJCRS) { " METHOD[\"PROJ unimplemented\"]],\n" " CS[Cartesian,2],\n" " AXIS[\"(E)\",east],\n" - " AXIS[\"(N)\",north]]")); + " AXIS[\"(N)\",north],\n" + " UNIT[\"metre\",1]]")); EXPECT_THROW( WKTParser().createFromWKT("DERIVEDPROJCRS[\"derived projectedCRS\",\n" @@ -5042,7 +5139,8 @@ TEST(wkt_parse, invalid_DERIVEDPROJCRS) { " METHOD[\"PROJ unimplemented\"]],\n" " CS[Cartesian,2],\n" " AXIS[\"(E)\",east],\n" - " AXIS[\"(N)\",north]]"), + " AXIS[\"(N)\",north],\n" + " UNIT[\"metre\",1]]"), ParsingException); // Missing DERIVINGCONVERSION @@ -5058,7 +5156,8 @@ TEST(wkt_parse, invalid_DERIVEDPROJCRS) { " METHOD[\"PROJ unimplemented\"]]],\n" " CS[Cartesian,2],\n" " AXIS[\"(E)\",east],\n" - " AXIS[\"(N)\",north]]"), + " AXIS[\"(N)\",north],\n" + " UNIT[\"metre\",1]]"), ParsingException); // Missing CS @@ -5087,7 +5186,8 @@ TEST(wkt_parse, invalid_DerivedVerticalCRS) { " DERIVINGCONVERSION[\"unnamed\",\n" " METHOD[\"PROJ unimplemented\"]],\n" " CS[vertical,1],\n" - " AXIS[\"gravity-related height (H)\",up]]")); + " AXIS[\"gravity-related height (H)\",up],\n" + " UNIT[\"metre\",1]]")); // Missing DERIVINGCONVERSION EXPECT_THROW(WKTParser().createFromWKT( @@ -5095,7 +5195,8 @@ TEST(wkt_parse, invalid_DerivedVerticalCRS) { " BASEVERTCRS[\"ODN height\",\n" " VDATUM[\"Ordnance Datum Newlyn\"]],\n" " CS[vertical,1],\n" - " AXIS[\"gravity-related height (H)\",up]]"), + " AXIS[\"gravity-related height (H)\",up],\n" + " UNIT[\"metre\",1]]"), ParsingException); // Missing CS @@ -5115,7 +5216,8 @@ TEST(wkt_parse, invalid_DerivedVerticalCRS) { " DERIVINGCONVERSION[\"unnamed\",\n" " METHOD[\"PROJ unimplemented\"]],\n" " CS[parametric,1],\n" - " AXIS[\"gravity-related height (H)\",up]]"), + " AXIS[\"gravity-related height (H)\",up],\n" + " UNIT[\"metre\",1]]"), ParsingException); } @@ -5381,6 +5483,20 @@ TEST(io, projstringformatter_cart_grs80_wgs84) { // --------------------------------------------------------------------------- +TEST(io, projstringformatter_axisswap_unitconvert_axisswap) { + auto fmt = PROJStringFormatter::create(); + fmt->addStep("axisswap"); + fmt->addParam("order", "2,1"); + fmt->addStep("unitconvert"); + fmt->addParam("xy_in", "rad"); + fmt->addParam("xy_out", "deg"); + fmt->addStep("axisswap"); + fmt->addParam("order", "2,1"); + EXPECT_EQ(fmt->toString(), "+proj=unitconvert +xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + TEST(io, projparse_longlat) { auto expected = "GEODCRS[\"unknown\",\n" @@ -5672,23 +5788,33 @@ TEST(io, projparse_longlat_a_f_non_zero) { PROJStringParser().createFromPROJString("+proj=longlat +a=2 +f=0.5"); auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); ASSERT_TRUE(crs != nullptr); - WKTFormatterNNPtr f(WKTFormatter::create()); - f->simulCurNodeHasId(); - crs->exportToWKT(f.get()); - auto expected = "GEODCRS[\"unknown\",\n" - " DATUM[\"unknown\",\n" - " ELLIPSOID[\"unknown\",2,2,\n" - " LENGTHUNIT[\"metre\",1]]],\n" - " PRIMEM[\"Reference meridian\",0,\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " CS[ellipsoidal,2],\n" - " AXIS[\"longitude\",east,\n" - " ORDER[1],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " AXIS[\"latitude\",north,\n" - " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]"; - EXPECT_EQ(f->toString(), expected); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); + auto rf = crs->ellipsoid()->computedInverseFlattening(); + EXPECT_EQ(rf, 2) << rf; +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_longlat_a_e) { + auto obj = + PROJStringParser().createFromPROJString("+proj=longlat +a=2 +e=0.5"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); + auto rf = crs->ellipsoid()->computedInverseFlattening(); + EXPECT_NEAR(rf, 7.46410161513775, 1e-14) << rf; +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_longlat_a_es) { + auto obj = + PROJStringParser().createFromPROJString("+proj=longlat +a=2 +es=0.5"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); + auto rf = crs->ellipsoid()->computedInverseFlattening(); + EXPECT_EQ(rf, 3.4142135623730958) << rf; } // --------------------------------------------------------------------------- @@ -5697,23 +5823,31 @@ TEST(io, projparse_longlat_R) { auto obj = PROJStringParser().createFromPROJString("+proj=longlat +R=2"); auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); ASSERT_TRUE(crs != nullptr); - WKTFormatterNNPtr f(WKTFormatter::create()); - f->simulCurNodeHasId(); - crs->exportToWKT(f.get()); - auto expected = "GEODCRS[\"unknown\",\n" - " DATUM[\"unknown\",\n" - " ELLIPSOID[\"unknown\",2,0,\n" - " LENGTHUNIT[\"metre\",1]]],\n" - " PRIMEM[\"Reference meridian\",0,\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " CS[ellipsoidal,2],\n" - " AXIS[\"longitude\",east,\n" - " ORDER[1],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]],\n" - " AXIS[\"latitude\",north,\n" - " ORDER[2],\n" - " ANGLEUNIT[\"degree\",0.0174532925199433]]]"; - EXPECT_EQ(f->toString(), expected); + EXPECT_TRUE(crs->ellipsoid()->isSphere()); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_longlat_a) { + auto obj = PROJStringParser().createFromPROJString("+proj=longlat +a=2"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_TRUE(crs->ellipsoid()->isSphere()); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); +} + +// --------------------------------------------------------------------------- + +TEST(io, projparse_longlat_a_override_ellps) { + auto obj = PROJStringParser().createFromPROJString( + "+proj=longlat +a=2 +ellps=WGS84"); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_TRUE(!crs->ellipsoid()->isSphere()); + EXPECT_EQ(crs->ellipsoid()->semiMajorAxis().getSIValue(), 2); + EXPECT_EQ(crs->ellipsoid()->computedInverseFlattening(), 298.25722356300003) + << crs->ellipsoid()->computedInverseFlattening(); } // --------------------------------------------------------------------------- @@ -7433,18 +7567,48 @@ TEST(io, projparse_projected_title) { // --------------------------------------------------------------------------- TEST(io, projparse_init) { + auto dbContext = DatabaseContext::create(); + + // Not allowed in non-compatibillity mode + EXPECT_THROW(PROJStringParser().createFromPROJString("init=epsg:4326"), + ParsingException); + + { + // EPSG:4326 is normally latitude-longitude order with degree, + // but in compatibillity mode it will be long-lat radian + auto obj = createFromUserInput("init=epsg:4326", dbContext, true); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo( + EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::RADIAN) + .get())); + } { - auto obj = PROJStringParser().createFromPROJString("init=epsg:4326"); + // EPSG:3040 is normally northing-easting order, but in compatibillity + // mode it will be easting-northing + auto obj = createFromUserInput("init=epsg:3040", dbContext, true); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo( + CartesianCS::createEastingNorthing(UnitOfMeasure::METRE).get())); + } + + { + auto obj = + PROJStringParser().createFromPROJString("init=ITRF2000:ITRF2005"); auto co = nn_dynamic_pointer_cast<CoordinateOperation>(obj); ASSERT_TRUE(co != nullptr); EXPECT_EQ(co->exportToPROJString(PROJStringFormatter::create().get()), - "+init=epsg:4326"); + "+proj=helmert +x=-0.0001 +y=0.0008 +z=0.0058 +rx=0 +ry=0 " + "+rz=0 +s=-0.0004 +dx=0.0002 +dy=-0.0001 +dz=0.0018 +drx=0 " + "+dry=0 +drz=0 +ds=-8e-06 +t_epoch=2000 " + "+convention=position_vector"); } { - auto obj = PROJStringParser().createFromPROJString( - "title=mytitle init=epsg:4326 ellps=WGS84"); + auto obj = createFromUserInput( + "title=mytitle init=epsg:4326 ellps=WGS84", dbContext, true); auto co = nn_dynamic_pointer_cast<CoordinateOperation>(obj); ASSERT_TRUE(co != nullptr); EXPECT_EQ(co->nameStr(), "mytitle"); @@ -7453,13 +7617,24 @@ TEST(io, projparse_init) { } { - auto obj = PROJStringParser().createFromPROJString( - "proj=pipeline step init=epsg:4326 step proj=longlat"); + auto obj = createFromUserInput( + "proj=pipeline step init=epsg:4326 step proj=longlat", dbContext, + true); auto co = nn_dynamic_pointer_cast<CoordinateOperation>(obj); ASSERT_TRUE(co != nullptr); EXPECT_EQ(co->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline +step +init=epsg:4326 +step +proj=longlat"); } + + { + auto obj = createFromUserInput( + "init=epsg:4326 proj=longlat ellps=GRS80", dbContext, true); + auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=longlat +ellps=GRS80 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); + } } // --------------------------------------------------------------------------- @@ -7491,10 +7666,6 @@ TEST(io, projparse_errors) { EXPECT_THROW(PROJStringParser().createFromPROJString( "proj=pipeline step init=epsg:4326 init=epsg:4326"), ParsingException); - - EXPECT_THROW(PROJStringParser().createFromPROJString( - "proj=pipeline step init=epsg:4326 proj=longlat"), - ParsingException); } // --------------------------------------------------------------------------- @@ -7532,9 +7703,6 @@ TEST(io, projparse_longlat_errors) { PROJStringParser().createFromPROJString("+proj=longlat +R=invalid"), ParsingException); - EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=longlat +a=1"), - ParsingException); - EXPECT_THROW(PROJStringParser().createFromPROJString("+proj=longlat +b=1"), ParsingException); @@ -7607,6 +7775,7 @@ TEST(io, createFromUserInput) { EXPECT_NO_THROW(createFromUserInput("+proj=longlat", nullptr)); EXPECT_NO_THROW(createFromUserInput("EPSG:4326", dbContext)); + EXPECT_NO_THROW(createFromUserInput("epsg:4326", dbContext)); EXPECT_NO_THROW( createFromUserInput("urn:ogc:def:crs:EPSG::4326", dbContext)); EXPECT_NO_THROW(createFromUserInput( diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index e62eddf9..057f1717 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -1142,6 +1142,36 @@ TEST(operation, transformation_createTOWGS84) { // --------------------------------------------------------------------------- +TEST(operation, createAxisOrderReversal) { + + auto latLongDeg = GeographicCRS::create( + PropertyMap(), GeodeticReferenceFrame::EPSG_6326, + EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE)); + auto longLatDeg = GeographicCRS::create( + PropertyMap(), GeodeticReferenceFrame::EPSG_6326, + EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::DEGREE)); + { + auto op = CoordinateOperationFactory::create()->createOperation( + latLongDeg, longLatDeg); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=axisswap +order=2,1"); + } + { + auto longLatRad = GeographicCRS::create( + PropertyMap(), GeodeticReferenceFrame::EPSG_6326, + EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::RADIAN)); + auto op = CoordinateOperationFactory::create()->createOperation( + longLatRad, latLongDeg); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=axisswap +order=2,1 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); + } +} + +// --------------------------------------------------------------------------- + TEST(operation, utm_export) { auto conv = Conversion::createUTM(PropertyMap(), 1, false); EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()), @@ -2986,6 +3016,29 @@ TEST(operation, webmerc_import_from_GDAL_wkt1) { // --------------------------------------------------------------------------- +TEST(operation, webmerc_import_from_GDAL_wkt1_with_EPSG_code) { + + auto projCRS = ProjectedCRS::create( + PropertyMap() + .set(IdentifiedObject::NAME_KEY, "Pseudo-Mercator") + .set(Identifier::CODESPACE_KEY, "EPSG") + .set(Identifier::CODE_KEY, "3857"), + GeographicCRS::EPSG_4326, + Conversion::createPopularVisualisationPseudoMercator( + PropertyMap(), Angle(0), Angle(0), Length(0), Length(0)), + CartesianCS::createEastingNorthing(UnitOfMeasure::METRE)); + + auto wkt1 = projCRS->exportToWKT( + WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL).get()); + EXPECT_TRUE(wkt1.find("3857") != std::string::npos) << wkt1; + auto obj = WKTParser().createFromWKT(wkt1); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + EXPECT_EQ(crs->identifiers().size(), 1); +} + +// --------------------------------------------------------------------------- + TEST(operation, webmerc_import_from_GDAL_wkt1_EPSG_3785_deprecated) { auto wkt1 = @@ -3134,6 +3187,44 @@ TEST(operation, webmerc_import_from_WKT2_EPSG_3785_deprecated) { // --------------------------------------------------------------------------- +TEST(operation, webmerc_import_from_broken_esri_WGS_84_Pseudo_Mercator) { + + // Likely the result of a broken export of GDAL morphToESRI() + auto wkt1 = "PROJCS[\"WGS_84_Pseudo_Mercator\",GEOGCS[\"GCS_WGS_1984\"," + "DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\"," + "6378137,298.257223563]],PRIMEM[\"Greenwich\",0]," + "UNIT[\"Degree\",0.017453292519943295]]," + "PROJECTION[\"Mercator\"],PARAMETER[\"central_meridian\",0]," + "PARAMETER[\"false_easting\",0]," + "PARAMETER[\"false_northing\",0],UNIT[\"Meter\",1]," + "PARAMETER[\"standard_parallel_1\",0.0]]"; + + auto obj = WKTParser().createFromWKT(wkt1); + auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj); + ASSERT_TRUE(crs != nullptr); + + auto convGot = crs->derivingConversion(); + + EXPECT_EQ(convGot->exportToWKT(WKTFormatter::create().get()), + "CONVERSION[\"unnamed\",\n" + " METHOD[\"Popular Visualisation Pseudo Mercator\",\n" + " ID[\"EPSG\",1024]],\n" + " PARAMETER[\"Latitude of natural origin\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8801]],\n" + " PARAMETER[\"Longitude of natural origin\",0,\n" + " ANGLEUNIT[\"degree\",0.0174532925199433],\n" + " ID[\"EPSG\",8802]],\n" + " PARAMETER[\"False easting\",0,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8806]],\n" + " PARAMETER[\"False northing\",0,\n" + " LENGTHUNIT[\"metre\",1],\n" + " ID[\"EPSG\",8807]]]"); +} + +// --------------------------------------------------------------------------- + TEST(operation, mollweide_export) { auto conv = Conversion::createMollweide(PropertyMap(), Angle(1), Length(2), @@ -4215,7 +4306,7 @@ TEST(operation, geogCRS_to_geogCRS_context_ntv1_ntv2_ctable2) { authFactory->createCoordinateReferenceSystem("4267"), // NAD27 authFactory->createCoordinateReferenceSystem("4269"), // NAD83 ctxt); - ASSERT_EQ(list.size(), 6); + ASSERT_EQ(list.size(), 7); EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline +step +proj=axisswap +order=2,1 +step " "+proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=hgridshift " @@ -4447,6 +4538,38 @@ TEST(operation, geogCRS_to_geogCRS_CH1903_to_CH1903plus_context) { // --------------------------------------------------------------------------- +TEST(operation, geogCRS_to_geogCRS_init_IGNF_to_init_IGNF_context) { + + auto dbContext = DatabaseContext::create(); + + auto sourceCRS_obj = PROJStringParser() + .attachDatabaseContext(dbContext) + .setUsePROJ4InitRules(true) + .createFromPROJString("+init=IGNF:NTFG"); + auto sourceCRS = nn_dynamic_pointer_cast<CRS>(sourceCRS_obj); + ASSERT_TRUE(sourceCRS != nullptr); + + auto targetCRS_obj = PROJStringParser() + .attachDatabaseContext(dbContext) + .setUsePROJ4InitRules(true) + .createFromPROJString("+init=IGNF:RGF93G"); + auto targetCRS = nn_dynamic_pointer_cast<CRS>(targetCRS_obj); + ASSERT_TRUE(targetCRS != nullptr); + + auto authFactory = AuthorityFactory::create(dbContext, std::string()); + auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0); + auto list = CoordinateOperationFactory::create()->createOperations( + NN_CHECK_ASSERT(sourceCRS), NN_CHECK_ASSERT(targetCRS), ctxt); + ASSERT_EQ(list.size(), 1); + + EXPECT_EQ(list[0]->nameStr(), + "NOUVELLE TRIANGULATION DE LA FRANCE (NTF) vers RGF93 (ETRS89)"); + EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=hgridshift +grids=ntf_r93.gsb"); +} + +// --------------------------------------------------------------------------- + TEST(operation, geogCRS_to_geogCRS_3D) { auto geogcrs_m_obj = @@ -5080,6 +5203,83 @@ TEST(operation, boundCRS_of_geogCRS_to_unrelated_geogCRS) { // --------------------------------------------------------------------------- +TEST(operation, createOperation_boundCRS_identified_by_datum) { + auto objSrc = + PROJStringParser().createFromPROJString("+proj=longlat +datum=WGS84"); + auto src = nn_dynamic_pointer_cast<GeographicCRS>(objSrc); + ASSERT_TRUE(src != nullptr); + + auto objDest = PROJStringParser().createFromPROJString( + "+proj=utm +zone=32 +a=6378249.2 +b=6356515 " + "+towgs84=-263.0,6.0,431.0 +no_defs"); + auto dest = nn_dynamic_pointer_cast<BoundCRS>(objDest); + ASSERT_TRUE(dest != nullptr); + + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dest)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +proj=cart +ellps=WGS84 " + "+step +proj=helmert +x=263 +y=-6 +z=-431 " + "+step +inv +proj=cart +ellps=clrk80ign " + "+step +proj=utm +zone=32 +ellps=clrk80ign"); + + auto authFactory = + AuthorityFactory::create(DatabaseContext::create(), std::string()); + auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0); + auto list = CoordinateOperationFactory::create()->createOperations( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dest), ctxt); + ASSERT_EQ(list.size(), 1U); + EXPECT_TRUE(list[0]->isEquivalentTo(op.get())); +} + +// --------------------------------------------------------------------------- + +TEST(operation, boundCRS_of_clrk_66_geogCRS_to_nad83_geogCRS) { + auto objSrc = PROJStringParser().createFromPROJString( + "+proj=latlong +ellps=clrk66 +nadgrids=ntv1_can.dat,conus"); + auto src = nn_dynamic_pointer_cast<CRS>(objSrc); + ASSERT_TRUE(src != nullptr); + + auto objDest = + PROJStringParser().createFromPROJString("+proj=latlong +datum=NAD83"); + auto dest = nn_dynamic_pointer_cast<CRS>(objDest); + ASSERT_TRUE(dest != nullptr); + + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dest)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +proj=hgridshift +grids=ntv1_can.dat,conus " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + +TEST(operation, boundCRS_of_clrk_66_projCRS_to_nad83_geogCRS) { + auto objSrc = PROJStringParser().createFromPROJString( + "+proj=utm +zone=17 +ellps=clrk66 +nadgrids=ntv1_can.dat,conus"); + auto src = nn_dynamic_pointer_cast<CRS>(objSrc); + ASSERT_TRUE(src != nullptr); + + auto objDest = + PROJStringParser().createFromPROJString("+proj=latlong +datum=NAD83"); + auto dest = nn_dynamic_pointer_cast<CRS>(objDest); + ASSERT_TRUE(dest != nullptr); + + auto op = CoordinateOperationFactory::create()->createOperation( + NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dest)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +inv +proj=utm +zone=17 +ellps=clrk66 " + "+step +proj=hgridshift +grids=ntv1_can.dat,conus " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + TEST(operation, boundCRS_of_projCRS_to_geogCRS) { auto utm31 = ProjectedCRS::create( PropertyMap(), GeographicCRS::EPSG_4807, @@ -5834,6 +6034,25 @@ TEST(operation, createOperation_on_crs_with_canonical_bound_crs) { // --------------------------------------------------------------------------- +TEST(operation, createOperation_fallback_to_proj4_strings) { + auto objDest = PROJStringParser().createFromPROJString( + "+proj=longlat +geoc +ellps=WGS84"); + auto dest = nn_dynamic_pointer_cast<GeographicCRS>(objDest); + ASSERT_TRUE(dest != nullptr); + + auto op = CoordinateOperationFactory::create()->createOperation( + GeographicCRS::EPSG_4326, NN_CHECK_ASSERT(dest)); + ASSERT_TRUE(op != nullptr); + EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()), + "+proj=pipeline +step +proj=axisswap +order=2,1 " + "+step +proj=unitconvert +xy_in=deg +xy_out=rad " + "+step +inv +proj=longlat +datum=WGS84 " + "+step +proj=longlat +geoc +ellps=WGS84 " + "+step +proj=unitconvert +xy_in=rad +xy_out=deg"); +} + +// --------------------------------------------------------------------------- + TEST(operation, mercator_variant_A_to_variant_B) { auto projCRS = ProjectedCRS::create( PropertyMap(), GeographicCRS::EPSG_4326, |
