aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2020-12-13 15:30:47 +0100
committerKristian Evers <kristianevers@gmail.com>2020-12-13 15:30:47 +0100
commitc3efbd23a5bf26f1dfd5bc55ae3488d5665ace98 (patch)
treea204df79f7057d7d420bf7c5358791347617b9cd
parent126445148d3b742c7f4e31f5f65857be59c48340 (diff)
parent6857d1a4a8eb6fcb7b88b0339413913ba2c3351a (diff)
downloadPROJ-c3efbd23a5bf26f1dfd5bc55ae3488d5665ace98.tar.gz
PROJ-c3efbd23a5bf26f1dfd5bc55ae3488d5665ace98.zip
Merge remote-tracking branch 'osgeo/master'
-rw-r--r--.github/workflows/backport.yml4
-rw-r--r--.github/workflows/clang_linux.yml24
-rwxr-xr-x.github/workflows/clang_linux/start.sh32
-rw-r--r--.github/workflows/clang_static_analyzer.yml15
-rwxr-xr-x.github/workflows/clang_static_analyzer/start.sh (renamed from travis/csa/install.sh)18
-rw-r--r--.github/workflows/code_checks.yml20
-rw-r--r--.github/workflows/conda.yml3
-rw-r--r--.github/workflows/doc_build.yml2
-rw-r--r--.github/workflows/linux_gcc_32bit.yml24
-rwxr-xr-x.github/workflows/linux_gcc_32bit/start.sh56
-rw-r--r--.github/workflows/linux_gcc_4_8.yml29
-rwxr-xr-x.github/workflows/linux_gcc_4_8/start.sh55
-rw-r--r--.github/workflows/mac.yml39
-rwxr-xr-x.github/workflows/mac/before_install.sh13
-rwxr-xr-x.github/workflows/mac/install.sh (renamed from travis/osx/install.sh)5
-rw-r--r--.github/workflows/mingw_w64.yml24
-rwxr-xr-x.github/workflows/mingw_w64/start.sh118
-rw-r--r--.github/workflows/windows.yml62
-rw-r--r--.travis.yml66
-rw-r--r--CMakeLists.txt4
-rw-r--r--COPYING18
-rw-r--r--Makefile.am2
-rw-r--r--appveyor.yml6
-rw-r--r--cmake/ProjInstallPath.cmake2
-rw-r--r--data/sql/alias_name.sql17
-rw-r--r--data/sql/conversion.sql2
-rw-r--r--data/sql/customizations.sql6
-rw-r--r--data/sql/esri.sql7
-rw-r--r--data/sql/extent.sql5
-rw-r--r--data/sql/geodetic_crs.sql8
-rw-r--r--data/sql/geodetic_datum.sql4
-rw-r--r--data/sql/grid_transformation.sql10
-rw-r--r--data/sql/helmert_transformation.sql16
-rw-r--r--data/sql/metadata.sql15
-rw-r--r--data/sql/proj_db_table_defs.sql4
-rw-r--r--data/sql/projected_crs.sql2
-rw-r--r--data/sql/scope.sql1
-rw-r--r--data/sql/supersession.sql2
-rw-r--r--data/sql/vertical_crs.sql4
-rw-r--r--docs/Makefile27
-rw-r--r--docs/source/apps/cct.rst50
-rw-r--r--docs/source/apps/cs2cs.rst46
-rw-r--r--docs/source/apps/projinfo.rst14
-rw-r--r--docs/source/development/index.rst5
-rw-r--r--docs/source/development/reference/deprecated.rst270
-rw-r--r--docs/source/development/reference/functions.rst18
-rw-r--r--docs/source/development/reference/index.rst1
-rw-r--r--docs/source/news.rst156
-rw-r--r--docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.pngbin0 -> 30731 bytes
-rw-r--r--docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg348
-rw-r--r--docs/source/operations/conversions/index.rst1
-rw-r--r--docs/source/operations/conversions/topocentric.rst115
-rw-r--r--docs/source/operations/projections/isea.rst6
-rw-r--r--docs/source/operations/projections/merc.rst30
-rw-r--r--docs/source/operations/projections/utm.rst2
-rw-r--r--include/proj/crs.hpp11
-rw-r--r--include/proj/internal/coordinateoperation_constants.hpp41
-rw-r--r--include/proj/io.hpp18
-rw-r--r--include/proj/util.hpp8
-rwxr-xr-xscripts/build_db.py5
-rwxr-xr-xscripts/build_db_create_ignf.py527
-rwxr-xr-xscripts/build_db_from_esri.py5
-rwxr-xr-xscripts/cppcheck.sh2
-rw-r--r--scripts/reference_exported_symbols.txt112
-rw-r--r--src/4D_api.cpp83
-rw-r--r--src/Makefile.am13
-rw-r--r--src/aasincos.cpp8
-rw-r--r--src/apps/cct.cpp97
-rw-r--r--src/apps/cs2cs.cpp190
-rw-r--r--src/apps/emess.cpp6
-rw-r--r--src/apps/geod.cpp1
-rw-r--r--src/apps/geod_set.cpp2
-rw-r--r--src/apps/gie.cpp10
-rw-r--r--src/apps/proj.cpp31
-rw-r--r--src/apps/projinfo.cpp43
-rw-r--r--src/auth.cpp2
-rw-r--r--src/bin_projinfo.cmake4
-rw-r--r--src/conversions/axisswap.cpp2
-rw-r--r--src/conversions/set.cpp2
-rw-r--r--src/conversions/topocentric.cpp165
-rw-r--r--src/conversions/unitconvert.cpp2
-rw-r--r--src/ctx.cpp163
-rw-r--r--src/datum_set.cpp22
-rw-r--r--src/dmstor.cpp6
-rw-r--r--src/ell_set.cpp46
-rw-r--r--src/errno.cpp18
-rw-r--r--src/fileapi.cpp240
-rw-r--r--src/filemanager.cpp149
-rw-r--r--src/gauss.cpp6
-rw-r--r--src/generic_inverse.cpp2
-rw-r--r--src/geodesic.c149
-rw-r--r--src/geodesic.h6
-rw-r--r--src/grids.cpp123
-rw-r--r--src/init.cpp155
-rw-r--r--src/initcache.cpp20
-rw-r--r--src/internal.cpp13
-rw-r--r--src/iso19111/c_api.cpp70
-rw-r--r--src/iso19111/coordinateoperation.cpp575
-rw-r--r--src/iso19111/crs.cpp97
-rw-r--r--src/iso19111/datum.cpp30
-rw-r--r--src/iso19111/factory.cpp391
-rw-r--r--src/iso19111/io.cpp201
-rw-r--r--src/lib_proj.cmake6
-rw-r--r--src/log.cpp6
-rw-r--r--src/malloc.cpp138
-rw-r--r--src/mlfn.cpp4
-rw-r--r--src/mlfn.hpp4
-rw-r--r--src/mutex.cpp25
-rw-r--r--src/networkfilemanager.cpp6
-rw-r--r--src/param.cpp8
-rw-r--r--src/phi2.cpp182
-rw-r--r--src/pipeline.cpp12
-rw-r--r--src/pj_list.h1
-rw-r--r--src/pr_list.cpp8
-rw-r--r--src/proj.h13
-rw-r--r--src/proj_api.h227
-rw-r--r--src/proj_constants.h20
-rw-r--r--src/proj_internal.h123
-rw-r--r--src/proj_mdist.cpp4
-rw-r--r--src/projections/adams.cpp2
-rw-r--r--src/projections/aea.cpp6
-rw-r--r--src/projections/aeqd.cpp4
-rw-r--r--src/projections/airy.cpp2
-rw-r--r--src/projections/aitoff.cpp6
-rw-r--r--src/projections/bacon.cpp6
-rw-r--r--src/projections/bertin1953.cpp2
-rw-r--r--src/projections/bipc.cpp2
-rw-r--r--src/projections/bonne.cpp4
-rw-r--r--src/projections/calcofi.cpp1
-rw-r--r--src/projections/cass.cpp4
-rw-r--r--src/projections/ccon.cpp4
-rw-r--r--src/projections/cea.cpp4
-rw-r--r--src/projections/chamb.cpp6
-rw-r--r--src/projections/col_urban.cpp2
-rw-r--r--src/projections/comill.cpp2
-rw-r--r--src/projections/eck3.cpp8
-rw-r--r--src/projections/eqc.cpp2
-rw-r--r--src/projections/eqdc.cpp4
-rw-r--r--src/projections/eqearth.cpp6
-rw-r--r--src/projections/fouc_s.cpp2
-rw-r--r--src/projections/geos.cpp2
-rw-r--r--src/projections/gn_sinu.cpp10
-rw-r--r--src/projections/gnom.cpp2
-rw-r--r--src/projections/goode.cpp6
-rw-r--r--src/projections/gstmerc.cpp20
-rw-r--r--src/projections/hammer.cpp2
-rw-r--r--src/projections/healpix.cpp14
-rw-r--r--src/projections/igh.cpp2
-rw-r--r--src/projections/igh_o.cpp2
-rw-r--r--src/projections/imw_p.cpp4
-rw-r--r--src/projections/isea.cpp2
-rw-r--r--src/projections/krovak.cpp4
-rw-r--r--src/projections/labrd.cpp2
-rw-r--r--src/projections/laea.cpp4
-rw-r--r--src/projections/lagrng.cpp2
-rw-r--r--src/projections/lcc.cpp12
-rw-r--r--src/projections/lcca.cpp4
-rw-r--r--src/projections/loxim.cpp2
-rw-r--r--src/projections/lsat.cpp2
-rw-r--r--src/projections/merc.cpp30
-rw-r--r--src/projections/misrsom.cpp2
-rw-r--r--src/projections/mod_ster.cpp10
-rw-r--r--src/projections/moll.cpp6
-rw-r--r--src/projections/natearth.cpp2
-rw-r--r--src/projections/natearth2.cpp2
-rw-r--r--src/projections/nsper.cpp4
-rw-r--r--src/projections/ob_tran.cpp17
-rw-r--r--src/projections/ocea.cpp2
-rw-r--r--src/projections/oea.cpp2
-rw-r--r--src/projections/omerc.cpp2
-rw-r--r--src/projections/ortho.cpp4
-rw-r--r--src/projections/patterson.cpp2
-rw-r--r--src/projections/poly.cpp4
-rw-r--r--src/projections/putp3.cpp4
-rw-r--r--src/projections/putp4p.cpp4
-rw-r--r--src/projections/putp5.cpp4
-rw-r--r--src/projections/putp6.cpp4
-rw-r--r--src/projections/qsc.cpp2
-rw-r--r--src/projections/robin.cpp2
-rw-r--r--src/projections/rouss.cpp4
-rw-r--r--src/projections/rpoly.cpp2
-rw-r--r--src/projections/sch.cpp2
-rw-r--r--src/projections/sconics.cpp2
-rw-r--r--src/projections/somerc.cpp2
-rw-r--r--src/projections/stere.cpp9
-rw-r--r--src/projections/sterea.cpp4
-rw-r--r--src/projections/sts.cpp8
-rw-r--r--src/projections/tmerc.cpp43
-rw-r--r--src/projections/tobmerc.cpp19
-rw-r--r--src/projections/tpeqd.cpp2
-rw-r--r--src/projections/urm5.cpp2
-rw-r--r--src/projections/urmfps.cpp4
-rw-r--r--src/projections/vandg2.cpp4
-rw-r--r--src/projections/wag3.cpp2
-rw-r--r--src/projections/wink1.cpp2
-rw-r--r--src/projections/wink2.cpp2
-rw-r--r--src/strerrno.cpp15
-rw-r--r--src/tests/multistresstest.cpp172
-rw-r--r--src/tests/test228.cpp113
-rw-r--r--src/transform.cpp1850
-rw-r--r--src/transformations/affine.cpp2
-rw-r--r--src/transformations/helmert.cpp2
-rw-r--r--src/transformations/horner.cpp10
-rw-r--r--src/transformations/molodensky.cpp2
-rw-r--r--src/tsfn.cpp32
-rw-r--r--src/utils.cpp182
-rw-r--r--src/wkt2_generated_parser.c1932
-rw-r--r--src/wkt2_grammar.y1
-rw-r--r--test/cli/Makefile.am6
-rw-r--r--test/cli/td_out.dist12
-rwxr-xr-xtest/cli/testcct127
-rw-r--r--test/cli/testcct_out.dist23
-rwxr-xr-xtest/cli/testdatumfile21
-rwxr-xr-xtest/cli/testprojinfo4
-rw-r--r--test/cli/testprojinfo_out.dist221
-rwxr-xr-xtest/cli/testvarious13
-rw-r--r--test/cli/tv_out.dist7
-rwxr-xr-xtest/fuzzers/build.sh4
-rw-r--r--test/fuzzers/standard_fuzzer.cpp218
-rw-r--r--test/gie/builtins.gie376
-rw-r--r--test/unit/CMakeLists.txt11
-rw-r--r--test/unit/Makefile.am10
-rw-r--r--test/unit/gie_self_tests.cpp2
-rw-r--r--test/unit/pj_phi2_test.cpp87
-rw-r--r--test/unit/pj_transform_test.cpp740
-rw-r--r--test/unit/test_c_api.cpp82
-rw-r--r--test/unit/test_crs.cpp182
-rw-r--r--test/unit/test_factory.cpp62
-rw-r--r--test/unit/test_io.cpp330
-rw-r--r--test/unit/test_operation.cpp206
-rwxr-xr-xtravis/after_success.sh7
-rwxr-xr-xtravis/csa/before_install.sh13
-rwxr-xr-xtravis/install.sh15
-rwxr-xr-xtravis/linux_clang/after_success.sh5
-rwxr-xr-xtravis/linux_clang/install.sh9
-rwxr-xr-xtravis/linux_gcc/before_install.sh22
-rwxr-xr-xtravis/linux_gcc/install.sh8
-rwxr-xr-xtravis/linux_gcc8/after_success.sh5
-rwxr-xr-xtravis/linux_gcc8/before_install.sh21
-rwxr-xr-xtravis/linux_gcc8/install.sh8
-rwxr-xr-xtravis/mingw32/after_success.sh5
-rwxr-xr-xtravis/mingw32/before_install.sh15
-rwxr-xr-xtravis/mingw32/install.sh59
-rwxr-xr-xtravis/osx/after_success.sh5
-rwxr-xr-xtravis/osx/before_install.sh22
-rwxr-xr-xtravis/publish_doc/after_success.sh (renamed from travis/linux_gcc/after_success.sh)0
-rwxr-xr-xtravis/publish_doc/before_install.sh (renamed from travis/linux_clang/before_install.sh)3
-rwxr-xr-xtravis/publish_doc/install.sh (renamed from travis/csa/after_success.sh)2
248 files changed, 6499 insertions, 7673 deletions
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index aa48cff3..f937c2ce 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -11,8 +11,8 @@ jobs:
name: Backport
steps:
- name: Backport Bot
- if: contains( join(github.event.pull_request.labels.*.name), 'backport')
- uses: Gaurav0/backport@v1.0.24
+ if: github.event.pull_request.merged && ( ( github.event.action == 'closed' && contains( join( github.event.pull_request.labels.*.name ), 'backport') ) || contains( github.event.label.name, 'backport' ) )
+ uses: Gaurav0/backport@v1.0.26
with:
bot_username: PROJ-BOT
bot_token: c1c49a5799d0a3a3885db8a4792880cbe509c1d6
diff --git a/.github/workflows/clang_linux.yml b/.github/workflows/clang_linux.yml
new file mode 100644
index 00000000..ba52cc95
--- /dev/null
+++ b/.github/workflows/clang_linux.yml
@@ -0,0 +1,24 @@
+name: CLang Linux
+
+on: [push, pull_request]
+
+jobs:
+
+ clang_linux:
+ runs-on: ubuntu-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: |
+ ${{ github.workspace }}/ccache.tar.gz
+ key: ${{ runner.os }}-cache-clang-${{ github.run_id }}
+ restore-keys: ${{ runner.os }}-cache-clang-
+
+ - name: Run
+ run: docker run -e CI -e TRAVIS_BUILD_DIR="$PWD" -e WORK_DIR="$PWD" -e TRAVIS_OS_NAME=linux -e BUILD_NAME=linux_clang -v $PWD:$PWD ubuntu:20.04 $PWD/.github/workflows/clang_linux/start.sh
diff --git a/.github/workflows/clang_linux/start.sh b/.github/workflows/clang_linux/start.sh
new file mode 100755
index 00000000..83d2f8c2
--- /dev/null
+++ b/.github/workflows/clang_linux/start.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+apt-get update -y
+DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ sudo autoconf automake libtool clang++-10 python3-clang-10 make cmake ccache pkg-config tar zip \
+ sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev jq python3-pip
+
+pip3 install --user jsonschema
+
+cd "$WORK_DIR"
+
+if test -f "$WORK_DIR/ccache.tar.gz"; then
+ echo "Restoring ccache..."
+ (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz")
+fi
+
+export CCACHE_CPP2=yes
+export PROJ_DB_CACHE_DIR="$HOME/.ccache"
+
+ccache -M 500M
+ccache -s
+
+# -fno-use-cxa-atexit is needed to build with -coverage
+CC="ccache clang-10" CXX="ccache clang++-10" CFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" CXXFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" LDFLAGS="-fsanitize=address" ./travis/install.sh
+
+ccache -s
+
+echo "Saving ccache..."
+rm -f "$WORK_DIR/ccache.tar.gz"
+(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache)
diff --git a/.github/workflows/clang_static_analyzer.yml b/.github/workflows/clang_static_analyzer.yml
new file mode 100644
index 00000000..47dfc4ad
--- /dev/null
+++ b/.github/workflows/clang_static_analyzer.yml
@@ -0,0 +1,15 @@
+name: CLang Static Analyzer
+
+on: [push, pull_request]
+
+jobs:
+
+ clang_static_analyzer:
+ runs-on: ubuntu-16.04
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Run
+ run: .github/workflows/clang_static_analyzer/start.sh
diff --git a/travis/csa/install.sh b/.github/workflows/clang_static_analyzer/start.sh
index 349afcb1..3a06c46a 100755
--- a/travis/csa/install.sh
+++ b/.github/workflows/clang_static_analyzer/start.sh
@@ -2,16 +2,28 @@
set -e
+sudo apt update
+
+DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --no-install-recommends \
+ autoconf automake libtool g++ make sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev jq
+
+CLANG_LLVM=clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04
+wget http://releases.llvm.org/9.0.0/$CLANG_LLVM.tar.xz
+tar xJf $CLANG_LLVM.tar.xz
+mv $CLANG_LLVM clang+llvm-9
+
# prepare build files
./autogen.sh
+NPROC=$(nproc)
+echo "NPROC=${NPROC}"
+export MAKEFLAGS="-j ${NPROC}"
+
export PATH=$PWD/clang+llvm-9/bin:$PATH
CXXFLAGS="-std=c++11" scan-build -o scanbuildoutput -plist -v ./configure
rm -rf scanbuildoutput
TOPDIR=$PWD
-scan-build -o $TOPDIR/scanbuildoutput -sarif -v -enable-checker alpha.unix.cstring.OutOfBounds,alpha.unix.cstring.BufferOverlap,optin.cplusplus.VirtualCall,optin.cplusplus.UninitializedObject make -j2
-
-sudo apt-get install jq
+scan-build -o $TOPDIR/scanbuildoutput -sarif -v -enable-checker alpha.unix.cstring.OutOfBounds,alpha.unix.cstring.BufferOverlap,optin.cplusplus.VirtualCall,optin.cplusplus.UninitializedObject make
rm -f filtered_scanbuild.txt
files=$(find scanbuildoutput -name "*.sarif")
diff --git a/.github/workflows/code_checks.yml b/.github/workflows/code_checks.yml
new file mode 100644
index 00000000..dc2cc6e4
--- /dev/null
+++ b/.github/workflows/code_checks.yml
@@ -0,0 +1,20 @@
+name: Code Checks
+
+on: [push, pull_request]
+
+jobs:
+
+ cppcheck_2004:
+ runs-on: ubuntu-20.04
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Install Requirements
+ run: |
+ sudo apt update
+ sudo apt install -y --no-install-recommends cppcheck
+
+ - name: Run cppcheck test
+ run: ./scripts/cppcheck.sh
diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml
index 80828772..596aaad2 100644
--- a/.github/workflows/conda.yml
+++ b/.github/workflows/conda.yml
@@ -7,6 +7,7 @@ on:
jobs:
build:
name: Conda ${{ matrix.platform }}
+ if: github.repository == 'OSGeo/PROJ'
runs-on: ${{ matrix.platform }}
strategy:
@@ -20,7 +21,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- - uses: goanpeca/setup-miniconda@v1
+ - uses: conda-incubator/setup-miniconda@v2
with:
channels: conda-forge
auto-update-conda: true
diff --git a/.github/workflows/doc_build.yml b/.github/workflows/doc_build.yml
index fa4546b2..52bf2b63 100644
--- a/.github/workflows/doc_build.yml
+++ b/.github/workflows/doc_build.yml
@@ -11,7 +11,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- - uses: goanpeca/setup-miniconda@v1
+ - uses: conda-incubator/setup-miniconda@v2
with:
channels: conda-forge
auto-update-conda: true
diff --git a/.github/workflows/linux_gcc_32bit.yml b/.github/workflows/linux_gcc_32bit.yml
new file mode 100644
index 00000000..455bf301
--- /dev/null
+++ b/.github/workflows/linux_gcc_32bit.yml
@@ -0,0 +1,24 @@
+name: Linux GCC 32bit
+
+on: [push, pull_request]
+
+jobs:
+
+ linux_gcc_32bit:
+ runs-on: ubuntu-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: |
+ ${{ github.workspace }}/ccache.tar.gz
+ key: ${{ runner.os }}-cache-gcc32bit-${{ github.run_id }}
+ restore-keys: ${{ runner.os }}-cache-gcc32bit-
+
+ - name: Run
+ run: docker run -e CI -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:20.04 $PWD/.github/workflows/linux_gcc_32bit/start.sh
diff --git a/.github/workflows/linux_gcc_32bit/start.sh b/.github/workflows/linux_gcc_32bit/start.sh
new file mode 100755
index 00000000..42746fe8
--- /dev/null
+++ b/.github/workflows/linux_gcc_32bit/start.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+set -e
+
+export TRAVIS_OS_NAME=linux
+export BUILD_NAME=linux_gcc_32bit
+export TRAVIS_BUILD_DIR="$WORK_DIR"
+
+ARCH=i386
+
+dpkg --add-architecture i386
+apt update -y
+
+DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ autoconf automake libtool gcc-multilib g++-multilib g++ sqlite3 \
+ python3-pip \
+ make cmake ccache pkg-config tar zip \
+ libsqlite3-dev:$ARCH libtiff-dev:$ARCH libcurl4-openssl-dev:$ARCH \
+ jq
+
+pip3 install --user jsonschema
+export PATH=$HOME/.local/bin:$PATH
+
+export CXXFLAGS='-g -O2 -m32 -D_GLIBCXX_ASSERTIONS'
+export CFLAGS='-g -O2 -m32'
+export TIFF_CFLAGS=-I/usr/include/i386-linux-gnu
+export TIFF_LIBS="-L/usr/lib/i386-linux-gnu -ltiff"
+export SQLITE3_CFLAGS=-I/usr/include/i386-linux-gnu
+export SQLITE3_LIBS="-L/usr/lib/i386-linux-gnu -lsqlite3"
+export CC="ccache gcc"
+export CXX="ccache g++"
+
+NPROC=$(nproc)
+echo "NPROC=${NPROC}"
+export MAKEFLAGS="-j ${NPROC}"
+
+cd "$WORK_DIR"
+
+if test -f "$WORK_DIR/ccache.tar.gz"; then
+ echo "Restoring ccache..."
+ (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz")
+fi
+
+export CCACHE_CPP2=yes
+export PROJ_DB_CACHE_DIR="$HOME/.ccache"
+
+ccache -M 500M
+ccache -s
+
+CFLAGS="-Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh
+
+ccache -s
+
+echo "Saving ccache..."
+rm -f "$WORK_DIR/ccache.tar.gz"
+(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache)
diff --git a/.github/workflows/linux_gcc_4_8.yml b/.github/workflows/linux_gcc_4_8.yml
new file mode 100644
index 00000000..1f37785c
--- /dev/null
+++ b/.github/workflows/linux_gcc_4_8.yml
@@ -0,0 +1,29 @@
+name: Linux GCC 4.8
+
+on: [push, pull_request]
+
+jobs:
+
+ linux_gcc_4_8:
+ runs-on: ubuntu-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: |
+ ${{ github.workspace }}/ccache.tar.gz
+ key: ${{ runner.os }}-cache-gcc-4-8-${{ github.run_id }}
+ restore-keys: ${{ runner.os }}-cache-gcc-4-8-
+
+ - name: Run
+ run: docker run -e CI -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:16.04 $PWD/.github/workflows/linux_gcc_4_8/start.sh
+
+ - name: Coveralls
+ uses: coverallsapp/github-action@v1.1.2
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/linux_gcc_4_8/start.sh b/.github/workflows/linux_gcc_4_8/start.sh
new file mode 100755
index 00000000..2493ea1a
--- /dev/null
+++ b/.github/workflows/linux_gcc_4_8/start.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+set -e
+
+export TRAVIS_OS_NAME=linux
+export BUILD_NAME=linux_gcc
+export TRAVIS_BUILD_DIR="$WORK_DIR"
+
+apt update -y
+
+DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ autoconf automake libtool g++-4.8 sqlite3 \
+ python3-pip python3-setuptools \
+ make cmake ccache pkg-config tar zip \
+ libsqlite3-dev libtiff-dev libcurl4-openssl-dev \
+ jq lcov
+
+pip3 install --user --upgrade pip
+echo `pip3 --version`
+pip3 config --user set global.progress_bar off
+pip3 install --user jsonschema
+pip3 install --user cmake==3.9.6
+
+export PATH=$HOME/.local/bin:$PATH
+
+export CC="ccache gcc-4.8"
+export CXX="ccache g++-4.8"
+
+NPROC=$(nproc)
+echo "NPROC=${NPROC}"
+export MAKEFLAGS="-j ${NPROC}"
+
+cd "$WORK_DIR"
+
+if test -f "$WORK_DIR/ccache.tar.gz"; then
+ echo "Restoring ccache..."
+ (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz")
+fi
+
+export CCACHE_CPP2=yes
+export PROJ_DB_CACHE_DIR="$HOME/.ccache"
+
+ccache -M 500M
+ccache -s
+
+CFLAGS="-Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh
+
+ccache -s
+
+echo "Saving ccache..."
+rm -f "$WORK_DIR/ccache.tar.gz"
+(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache)
+
+mkdir -p coverage
+lcov --no-external --capture --directory src --output-file coverage/lcov.info
diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml
new file mode 100644
index 00000000..1ccbd938
--- /dev/null
+++ b/.github/workflows/mac.yml
@@ -0,0 +1,39 @@
+name: MacOS build
+
+on: [push, pull_request]
+
+jobs:
+
+ macos_build:
+ runs-on: macos-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+
+ - uses: actions/checkout@v2
+
+ - uses: conda-incubator/setup-miniconda@v2
+ with:
+ channels: conda-forge
+ auto-update-conda: true
+
+ - name: Cache
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: ~/.ccache
+ key: ${{ runner.os }}-cache-mac-${{ github.run_id }}
+ restore-keys: ${{ runner.os }}-cache-mac-
+
+ - name: Install Requirements
+ shell: bash -l {0}
+ run: |
+ source .github/workflows/mac/before_install.sh
+
+ - name: Build
+ shell: bash -l {0}
+ run: |
+ export TRAVIS_BUILD_DIR=$PWD
+ source .github/workflows/mac/install.sh
+ env:
+ TRAVIS_OS_NAME: osx
+ BUILD_NAME: osx
diff --git a/.github/workflows/mac/before_install.sh b/.github/workflows/mac/before_install.sh
new file mode 100755
index 00000000..217039fe
--- /dev/null
+++ b/.github/workflows/mac/before_install.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -e
+
+
+conda update -n base -c defaults conda
+conda install compilers -y
+
+conda config --set channel_priority strict
+conda install --yes --quiet python=3.8 autoconf automake libtool ccache -y
+conda install --yes --quiet proj=7.1.1=h45baca5_3 --only-deps -y
+
+./travis/before_install_pip.sh
diff --git a/travis/osx/install.sh b/.github/workflows/mac/install.sh
index ff5266f6..ed27150f 100755
--- a/travis/osx/install.sh
+++ b/.github/workflows/mac/install.sh
@@ -5,6 +5,9 @@ set -e
export CCACHE_CPP2=yes
export PROJ_DB_CACHE_DIR="$HOME/.ccache"
-export PATH=$HOME/Library/Python/3.6/bin:$PATH
+ccache -M 200M
+ccache -s
CC="ccache clang" CXX="ccache clang++" CFLAGS="-Werror -O2" CXXFLAGS="-Werror -O2" ./travis/install.sh
+
+ccache -s
diff --git a/.github/workflows/mingw_w64.yml b/.github/workflows/mingw_w64.yml
new file mode 100644
index 00000000..8e323efa
--- /dev/null
+++ b/.github/workflows/mingw_w64.yml
@@ -0,0 +1,24 @@
+name: mingw_w64 build
+
+on: [push, pull_request]
+
+jobs:
+
+ mingw_w64_build:
+ runs-on: ubuntu-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: Cache
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: |
+ ${{ github.workspace }}/ccache.tar.gz
+ key: ${{ runner.os }}-cache-mingw_w64-${{ github.run_id }}
+ restore-keys: ${{ runner.os }}-cache-mingw_w64-
+
+ - name: Build
+ run: docker run -e CI -e TRAVIS_OS_NAME=linux -e BUILD_NAME=mingw_w64 -e WORK_DIR="$PWD" -v $PWD:$PWD ubuntu:18.04 $PWD/.github/workflows/mingw_w64/start.sh
diff --git a/.github/workflows/mingw_w64/start.sh b/.github/workflows/mingw_w64/start.sh
new file mode 100755
index 00000000..2b42381f
--- /dev/null
+++ b/.github/workflows/mingw_w64/start.sh
@@ -0,0 +1,118 @@
+#!/bin/sh
+
+set -e
+
+SCRIPT_DIR=$(dirname "$0")
+case $SCRIPT_DIR in
+ "/"*)
+ ;;
+ ".")
+ SCRIPT_DIR=$(pwd)
+ ;;
+ *)
+ SCRIPT_DIR=$(pwd)/$(dirname "$0")
+ ;;
+esac
+
+apt-get update -y
+DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
+ sudo wget tzdata
+
+USER=root
+export USER
+
+cd "$WORK_DIR"
+
+if test -f "$WORK_DIR/ccache.tar.gz"; then
+ echo "Restoring ccache..."
+ (cd $HOME && tar xzf "$WORK_DIR/ccache.tar.gz")
+fi
+
+export PROJ_DB_CACHE_DIR="$HOME/.ccache"
+
+sudo apt-get install -y --no-install-recommends \
+ ccache \
+ binutils-mingw-w64-x86-64 \
+ gcc-mingw-w64-x86-64 \
+ g++-mingw-w64-x86-64 \
+ g++-mingw-w64 \
+ mingw-w64-tools \
+ wine-stable \
+ make autoconf automake libtool zip \
+ sqlite3 \
+ curl ca-certificates
+
+# Select posix/pthread for std::mutex
+update-alternatives --set x86_64-w64-mingw32-gcc /usr/bin/x86_64-w64-mingw32-gcc-posix
+update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix
+
+ccache -M 500M
+ccache -s
+
+MINGW_ARCH=x86_64-w64-mingw32
+MINGW_PREFIX=/usr/lib/gcc/$MINGW_ARCH/7.3-posix
+
+export CCACHE_CPP2=yes
+export CC="ccache $MINGW_ARCH-gcc"
+export CXX="ccache $MINGW_ARCH-g++"
+export LD=$MINGW_ARCH-ld
+
+UNAME="$(uname)" || UNAME=""
+NPROC=$(nproc);
+echo "NPROC=${NPROC}"
+export MAKEFLAGS="-j ${NPROC}"
+
+# prepare wine environment
+export WINE_PREFIX="$HOME/.wine"
+WINE_SYSDIR=$WINE_PREFIX/drive_c/windows
+wine64 cmd /c dir
+ln -s $MINGW_PREFIX/libstdc++-6.dll $WINE_SYSDIR
+ln -s $MINGW_PREFIX/libgcc_s_seh-1.dll $WINE_SYSDIR
+ln -s $MINGW_PREFIX/libgcc_s_sjlj-1.dll $WINE_SYSDIR
+ln -s /usr/$MINGW_ARCH/lib/libwinpthread-1.dll $WINE_SYSDIR
+
+# build zlib
+wget https://github.com/madler/zlib/archive/v1.2.11.tar.gz
+tar xzf v1.2.11.tar.gz
+(cd zlib-1.2.11 && sudo make install -fwin32/Makefile.gcc SHARED_MODE=1 PREFIX=x86_64-w64-mingw32- DESTDIR=/usr/$MINGW_ARCH/)
+sudo mkdir -p /usr/$MINGW_ARCH/include
+sudo mkdir -p /usr/$MINGW_ARCH/lib
+sudo cp /usr/$MINGW_ARCH/*.h /usr/$MINGW_ARCH/include
+sudo cp /usr/$MINGW_ARCH/libz.* /usr/$MINGW_ARCH/lib
+ln -s /usr/$MINGW_ARCH/zlib1.dll $WINE_SYSDIR
+
+# build libtiff
+wget https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz
+tar xzf tiff-4.1.0.tar.gz
+(cd tiff-4.1.0 && ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install)
+ln -s /usr/$MINGW_ARCH/bin/libtiff-5.dll $WINE_SYSDIR
+
+# build sqlite3
+wget https://sqlite.org/2020/sqlite-autoconf-3330000.tar.gz
+tar xzf sqlite-autoconf-3330000.tar.gz
+# Build with SQLITE_DQS=0 to ensure we properly use single quotes and double quotes (cf issue #2480)
+(cd sqlite-autoconf-3330000 &&
+CFLAGS="-DSQLITE_DQS=0" ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make && sudo make install)
+ln -s /usr/$MINGW_ARCH/bin/libsqlite3-0.dll $WINE_SYSDIR
+
+# prepare build files
+./autogen.sh
+# autoconf build
+mkdir build_autoconf
+cd build_autoconf
+CFLAGS="-Werror" CXXFLAGS="-Werror" ../configure --host=$MINGW_ARCH --prefix=/tmp/proj_autoconf_install --without-curl
+make
+make install
+make dist-all
+find /tmp/proj_autoconf_install
+(cd test; make)
+cp -r ../data/tests /tmp/proj_autoconf_install/share/proj
+cp ../data/tests/egm96_15_downsampled.gtx /tmp/proj_autoconf_install/share/proj/egm96_15.gtx
+cp ../data/tests/ntv2_0_downsampled.gsb /tmp/proj_autoconf_install/share/proj/ntv2_0.gsb
+wine64 test/unit/test_cpp_api.exe
+
+ccache -s
+
+echo "Saving ccache..."
+rm -f "$WORK_DIR/ccache.tar.gz"
+(cd $HOME && tar czf "$WORK_DIR/ccache.tar.gz" .ccache)
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
new file mode 100644
index 00000000..13179c18
--- /dev/null
+++ b/.github/workflows/windows.yml
@@ -0,0 +1,62 @@
+name: Windows build
+
+on: [push, pull_request]
+
+jobs:
+
+ MSVC:
+ runs-on: windows-latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]')"
+
+ env:
+ ARCH: x64
+ BUILD_SHARED_LIBS: ON
+
+ steps:
+
+ - uses: actions/checkout@v2
+ - uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Cache vcpkg packages
+ uses: actions/cache@v2
+ id: cache
+ with:
+ path: c:\vcpkg\installed
+ key: ${{ runner.os }}-vcpkg-${{ hashFiles('.github/workflows/windows.yml') }}
+
+ - name: Install build requirements
+ shell: cmd
+ if: steps.cache.outputs.cache-hit != 'true'
+ run: |
+ vcpkg install sqlite3[core,tool]:${{ env.ARCH }}-windows
+ vcpkg install tiff:${{ env.ARCH }}-windows
+ vcpkg install curl:${{ env.ARCH }}-windows
+
+ - name: Build
+ shell: cmd
+ run: |
+ set VCPKG_INSTALLED=c:\vcpkg\installed\${{ env.ARCH }}-windows
+ dir %VCPKG_INSTALLED%\bin
+ set PATH=%VCPKG_INSTALLED%\bin;%PATH%
+ set PROJ_BUILD=%GITHUB_WORKSPACE%\build
+ mkdir %PROJ_BUILD%
+ cd %PROJ_BUILD%
+ set PROJ_DIR=%GITHUB_WORKSPACE%\proj_dir
+ cmake -GNinja .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="{{ env.BUILD_SHARED_LIBS }}" -DCMAKE_C_FLAGS="/WX" -DCMAKE_CXX_FLAGS="/WX" -DCMAKE_TOOLCHAIN_FILE=c:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX="%PROJ_DIR%"
+ ninja -v
+ ninja install
+ dir %PROJ_DIR%\bin
+
+ - name: Run tests
+ shell: cmd
+ run: |
+ set VCPKG_INSTALLED=c:\vcpkg\installed\${{ env.ARCH }}-windows
+ set PATH=%VCPKG_INSTALLED%\bin;%PATH%
+ set PROJ_DIR=%GITHUB_WORKSPACE%\proj_dir
+ set PROJ_LIB=%PROJ_DIR%\share\proj
+ set PROJ_BUILD=%GITHUB_WORKSPACE%\build
+ cd %PROJ_BUILD%
+ ctest -V -C Release
+ set PATH=%PROJ_DIR%\bin;%PATH%
+ call %GITHUB_WORKSPACE%\test\postinstall\test_cmake.bat %PROJ_DIR%
+ proj
diff --git a/.travis.yml b/.travis.yml
index dc5356ad..bf53a57c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,51 +20,8 @@ matrix:
services:
- docker
env:
- - BUILD_NAME=linux_gcc
- - DETAILS="linux, gcc-4.8"
- - CC=gcc-4.8
- - CXX=g++-4.8
- addons:
- apt:
- packages:
- - g++-4.8
-
- - os: linux
- dist: bionic
- compiler: gcc
- services:
- - docker
- env:
- - BUILD_NAME=linux_gcc8
- - DETAILS="linux, gcc8"
- - DETAILS="linux, gcc8, i386"
- - ARCH=i386
- - CC=gcc-8
- - CXX=g++-8
- - CXXFLAGS='-g -O2 -m32 -D_GLIBCXX_ASSERTIONS'
- - CFLAGS='-g -O2 -m32'
- - TIFF_CFLAGS=-I/usr/include/i386-linux-gnu
- - TIFF_LIBS="-L/usr/lib/i386-linux-gnu -ltiff"
- - SQLITE3_CFLAGS=-I/usr/include/i386-linux-gnu
- - SQLITE3_LIBS="-L/usr/lib/i386-linux-gnu -lsqlite3"
- addons:
- apt:
- sources:
- - sourceline: 'ppa:ubuntu-toolchain-r/test'
- packages:
- - g++-8-multilib
- - make
- - autoconf
- - automake
-
- - os: linux
- dist: xenial
- compiler: clang
- services:
- - docker
- env:
- - BUILD_NAME=linux_clang
- - DETAILS="linux, clang"
+ - BUILD_NAME=publish_doc
+ - DETAILS="publish_doc"
- os: linux
dist: bionic
@@ -82,25 +39,6 @@ matrix:
- BUILD_NAME=linux_generic
- DETAILS="linux, arm64"
- - os: osx
- env:
- - BUILD_NAME=osx
- - DETAILS="osx"
-
- - os: linux
- dist: xenial
- compiler: gcc
- env:
- - BUILD_NAME=mingw32
- - DETAILS="mingw32"
-
- - os: linux
- compiler: gcc
- dist: xenial
- env:
- - BUILD_NAME=csa
- - DETAILS="CLang Static Analyzer"
-
allow_failures:
- env: BUILD_NAME=mingw32
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a75aa578..ee1444a4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -277,3 +277,7 @@ add_subdirectory(cmake)
if(BUILD_TESTING)
add_subdirectory(test)
endif()
+
+set(docfiles COPYING NEWS AUTHORS)
+install(FILES ${docfiles}
+ DESTINATION "${DOCDIR}")
diff --git a/COPYING b/COPYING
index fa371748..d46f95cd 100644
--- a/COPYING
+++ b/COPYING
@@ -1,18 +1,19 @@
-All source, data files and other contents of the PROJ.4 package are
+All source, data files and other contents of the PROJ package are
available under the following terms. Note that the PROJ 4.3 and earlier
was "public domain" as is common with US government work, but apparently
-this is not a well defined legal term in many countries. I am placing
-everything under the following MIT style license because I believe it is
+this is not a well defined legal term in many countries. Frank Warmerdam placed
+everything under the following MIT style license because he believed it is
effectively the same as public domain, allowing anyone to use the code as
-they wish, including making proprietary derivatives.
+they wish, including making proprietary derivatives.
-Though I have put my own name as copyright holder, I don't mean to imply
-I did the work. Essentially all work was done by Gerald Evenden.
+Initial PROJ 4.3 public domain code was put as Frank Warmerdam as copyright
+holder, but he didn't mean to imply he did the work. Essentially all work was
+done by Gerald Evenden.
- --------------
+Copyright information can be found in source files.
- Copyright (c) 2000, Frank Warmerdam
+ --------------
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -31,4 +32,3 @@ I did the work. Essentially all work was done by Gerald Evenden.
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.
-
diff --git a/Makefile.am b/Makefile.am
index 8507afe9..4f78ff32 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,8 @@ DIST_SUBDIRS = include src man data cmake test
EXTRA_DIST = CMakeLists.txt CITATION README.md
+dist_doc_DATA = COPYING NEWS AUTHORS
+
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = proj.pc
diff --git a/appveyor.yml b/appveyor.yml
index dad1f35d..17447a64 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -11,9 +11,9 @@ environment:
BUILD_SHARED_LIBS: OFF
# VS 2017
- - platform: x64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- BUILD_SHARED_LIBS: ON
+# - platform: x64
+# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+# BUILD_SHARED_LIBS: ON
shallow_clone: true
diff --git a/cmake/ProjInstallPath.cmake b/cmake/ProjInstallPath.cmake
index 4c63d658..b7f7b821 100644
--- a/cmake/ProjInstallPath.cmake
+++ b/cmake/ProjInstallPath.cmake
@@ -29,7 +29,7 @@ if(UNIX)
set(DEFAULT_LIB_SUBDIR ${CMAKE_INSTALL_LIBDIR})
set(DEFAULT_DATA_SUBDIR ${CMAKE_INSTALL_DATAROOTDIR}/proj)
set(DEFAULT_INCLUDE_SUBDIR ${CMAKE_INSTALL_INCLUDEDIR})
- set(DEFAULT_DOC_SUBDIR ${CMAKE_INSTALL_DOCDIR})
+ set(DEFAULT_DOC_SUBDIR share/doc/${PROJECT_NAME_LOWER})
set(DEFAULT_CMAKE_SUBDIR ${CMAKE_INSTALL_LIBDIR}/cmake)
else()
# Common locations for Unix and Mac OS X
diff --git a/data/sql/alias_name.sql b/data/sql/alias_name.sql
index 88826f25..6dcb36c1 100644
--- a/data/sql/alias_name.sql
+++ b/data/sql/alias_name.sql
@@ -609,6 +609,8 @@ INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1130','JGD2000 (vertica
INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1129','JSLD72','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','1132','RDN2008','EPSG');
INSERT INTO "alias_name" VALUES('vertical_datum','EPSG','1288','BI','EPSG');
+INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6258','European Terrestrial Reference System 1989','EPSG');
+INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6326','World Geodetic System 1984','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','21100','Genuk / NEIEZ','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2140','NAD83(CSRS98) / SCoPQ zone 3','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2141','NAD83(CSRS98) / SCoPQ zone 4','EPSG');
@@ -720,7 +722,6 @@ INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5701','Newlyn height','EP
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5702','National Geodetic Vertical Datum of 1929 height (ftUS)','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5703','North American Vertical Datum of 1988 height (m)','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5709','Normaal Amsterdams Peil height','EPSG');
-INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','Australian Height Datum height','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5712','Australian Height Datum (Tasmania) height','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5713','Canadian Geodetic Vertical Datum of 1928 height','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5714','mean sea level height','EPSG');
@@ -4244,8 +4245,6 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3088','NAD83 / KY1Z (m)'
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9379','726','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3857','WGS 84 / Popular Visualisation Pseudo-Mercator','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9379','IGb14 - LatLonEHt','EPSG');
-INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','725','EPSG');
-INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','IGb14 - LatLon','EPSG');
INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','3886','National Elevation Network height','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','3893','ED50 / Iraq Nat. Grid','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4743','Karbala 1979 (Polservice)','EPSG');
@@ -5086,8 +5085,6 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8383','NCRS Las Vegas (m
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8387','NCRS Las Vegas high (ftUS)','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','8433','Macao 1920 Grid System','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','5514','S-JTSK [JTSK] / Krovak East North','EPSG');
-INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD71 height','EPSG');
-INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD-TAS83 height','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','GGN93 / Guam Map Grid','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','Guam Geodetic Network 1993 / Guam Map Grid','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','4414','NAD83 / Guam Map Grid','EPSG');
@@ -5608,8 +5605,6 @@ INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4202','298','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4202','AGD66 - LatLon','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4203','350','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4203','AGD84 - LatLon','EPSG');
-INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','339','EPSG');
-INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD - NOHt','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7844','284','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7844','GDA2020 - LatLon','EPSG');
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','7843','329','EPSG');
@@ -7194,3 +7189,11 @@ INSERT INTO "alias_name" VALUES('projected_crs','EPSG','6708','RDN2008 / TM33','
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','6709','RDN2008 / TM34','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2062','Madrid (Madrid) / Spain LCC','EPSG');
INSERT INTO "alias_name" VALUES('projected_crs','EPSG','2062','Madrid - LCC','EPSG');
+INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','725','EPSG');
+INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','9380','IGb14 - LatLon','EPSG');
+INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','Australian Height Datum height','EPSG');
+INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD71 height','EPSG');
+INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD-TAS83 height','EPSG');
+INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','339','EPSG');
+INSERT INTO "alias_name" VALUES('vertical_crs','EPSG','5711','AHD - NOHt','EPSG');
+INSERT INTO "alias_name" VALUES('projected_crs','EPSG','9498','CABA-P07','EPSG');
diff --git a/data/sql/conversion.sql b/data/sql/conversion.sql
index e515f198..76a4bfc1 100644
--- a/data/sql/conversion.sql
+++ b/data/sql/conversion.sql
@@ -1734,6 +1734,8 @@ INSERT INTO "conversion" VALUES('EPSG','9385','AbInvA96_2020-TM','In conjunction
INSERT INTO "usage" VALUES('EPSG','14062','conversion','EPSG','9385','EPSG','4589','EPSG','1196');
INSERT INTO "conversion" VALUES('EPSG','9455','GBK19-TM','In conjunction with transformation ETRS89 to GBK19-IRF (1) (code 9454), emulates the TPEN11 Snake projection.','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',55.45,'EPSG','9110','EPSG','8802','Longitude of natural origin',-4.21,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',93720.394,'EPSG','9001','EPSG','8807','False northing',113870.493,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO "usage" VALUES('EPSG','14130','conversion','EPSG','9455','EPSG','4607','EPSG','1141');
+INSERT INTO "conversion" VALUES('EPSG','9497','Gauss-Kruger CABA 2019','Projection created in 2017 for the purpose of modernizing the city''s cadastre and linking it to modern reference frames. Origin approximates the 1919 origin of the cross of the main tower of the San José de Flores church ("0 de Flores" plane grid).','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',-34.374536,'EPSG','9110','EPSG','8802','Longitude of natural origin',-58.274791,'EPSG','9110','EPSG','8805','Scale factor at natural origin',1.0,'EPSG','9201','EPSG','8806','False easting',20000.0,'EPSG','9001','EPSG','8807','False northing',70000.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
+INSERT INTO "usage" VALUES('EPSG','14242','conversion','EPSG','9497','EPSG','4610','EPSG','1056');
INSERT INTO "conversion" VALUES('EPSG','10101','Alabama CS27 East zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',30.3,'EPSG','9110','EPSG','8802','Longitude of natural origin',-85.5,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.99996,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
INSERT INTO "usage" VALUES('EPSG','11101','conversion','EPSG','10101','EPSG','2154','EPSG','1142');
INSERT INTO "conversion" VALUES('EPSG','10102','Alabama CS27 West zone','','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',30.0,'EPSG','9110','EPSG','8802','Longitude of natural origin',-87.3,'EPSG','9110','EPSG','8805','Scale factor at natural origin',0.999933333,'EPSG','9201','EPSG','8806','False easting',500000.0,'EPSG','9003','EPSG','8807','False northing',0.0,'EPSG','9003',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);
diff --git a/data/sql/customizations.sql b/data/sql/customizations.sql
index beaaf8fd..c53a324d 100644
--- a/data/sql/customizations.sql
+++ b/data/sql/customizations.sql
@@ -274,12 +274,6 @@ INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6277','OSGB36','PROJ');
-- to the EPSG:4326 CRS, as this is a common use case (https://github.com/OSGeo/PROJ/issues/2216)
INSERT INTO "alias_name" VALUES('geodetic_crs','EPSG','4326','WGS84','PROJ');
----- Aliases from old datum names to new datum ensemble names -----
-
--- Those have been reported to IOGP and will hopefully be integrated in a later EPSG release
-INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6326','World Geodetic System 1984','PROJ');
-INSERT INTO "alias_name" VALUES('geodetic_datum','EPSG','6258','European Terrestrial Reference System 1989','PROJ');
-
---- PROJ unit short names -----
-- Linear units
diff --git a/data/sql/esri.sql b/data/sql/esri.sql
index 90e61f02..8b969bc4 100644
--- a/data/sql/esri.sql
+++ b/data/sql/esri.sql
@@ -17290,8 +17290,9 @@ VALUES
('c1hpgn', 'us_noaa_c1hpgn.tif', 'c1hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c1hpgn.tif', 1, 1, NULL),
('c2hpgn', 'us_noaa_c2hpgn.tif', 'c2hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c2hpgn.tif', 1, 1, NULL),
('spain/100800401','es_cat_icgc_100800401.tif','100800401.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_cat_icgc_100800401.tif',1,1,NULL),
-('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL) -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage."
-;
+('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL), -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage."
+('spain/PENR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL),
+('spain/BALR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL);
-- 'france/RGNC1991_IGN72GrandeTerre' : we have a 3D geocentric corresponding one: no need for mapping
-- 'france/RGNC1991_NEA74Noumea' : we have a 3D geocentric corresponding one: no need for mapping
-- 'gc_nad83_harn_2007_conus_shifts': no mapping
@@ -17301,8 +17302,6 @@ VALUES
-- 'gc_nad83_2007_2011_alaska_shifts': no mapping
-- 'gc_nad83_2007_2011_prvi_shifts': no mapping
-- 'uk/osgb36_xrail84': no mapping
--- 'spain/PENR2009': no mapping
--- 'spain/BALR2009': no mapping
-- 'japan/tky2jgd': no mapping
-- 'spain/baleares': no mapping
-- 'spain/peninsula': no mapping
diff --git a/data/sql/extent.sql b/data/sql/extent.sql
index d82a8ff9..1c94827d 100644
--- a/data/sql/extent.sql
+++ b/data/sql/extent.sql
@@ -2442,7 +2442,7 @@ INSERT INTO "extent" VALUES('EPSG','3462','Mexico - offshore GoM - Campeche area
INSERT INTO "extent" VALUES('EPSG','3463','World - 86°S to 86°N','World between 86°S and 86°N.',-86.0,86.0,-180.0,180.0,0);
INSERT INTO "extent" VALUES('EPSG','3464','World - N hemisphere - 12°E to 18°E - by country and WGS 72BE','Between 12°E and 18°E, northern hemisphere between equator and 84°N, onshore and offshore. Chad - west of 18°E.',0.0,84.0,12.0,18.0,0);
INSERT INTO "extent" VALUES('EPSG','3465','World - N hemisphere - 18°E to 24°E - by country and WGS 72BE','Between 12°E and 18°E, northern hemisphere between equator and 84°N, onshore and offshore. Chad - east of 18°E.',0.0,84.0,18.0,24.0,0);
-INSERT INTO "extent" VALUES('EPSG','3466','China - Ordos - 108°E to 108.5°E and 37.75°N to 38.25°N','China - Ordos basin.',35.0,39.0,107.0,110.01,0);
+INSERT INTO "extent" VALUES('EPSG','3466','China - Ordos basin','China - Ordos basin.',35.0,39.0,107.0,110.007,0);
INSERT INTO "extent" VALUES('EPSG','3467','North America - Great Lakes basin','Canada and United States (USA) - Great Lakes basin.',40.99,50.74,-93.17,-74.47,0);
INSERT INTO "extent" VALUES('EPSG','3468','North America - Great Lakes basin and St Lawrence Seaway','Canada and United States (USA) - Great Lakes basin and St Lawrence Seaway.',40.99,52.22,-93.17,-54.75,0);
INSERT INTO "extent" VALUES('EPSG','3469','China - offshore - Yellow Sea','China - offshore - Huang Hai (Yellow Sea).',31.23,37.4,119.23,125.06,0);
@@ -3518,7 +3518,7 @@ INSERT INTO "extent" VALUES('EPSG','4539','Angola - east of 18°E','Angola - eas
INSERT INTO "extent" VALUES('EPSG','4540','Africa - South Africa, Lesotho and Eswatini.','Eswatini (Swaziland); Lesotho; South Africa - onshore and offshore.',-50.32,-22.13,13.33,42.85,0);
INSERT INTO "extent" VALUES('EPSG','4541','Vietnam - Dien Bien and Lai Chau','Vietnam - Dien Bien and Lai Chau provinces.',20.89,22.82,102.14,103.99,0);
INSERT INTO "extent" VALUES('EPSG','4542','Kosovo','Kosovo.',41.85,43.25,19.97,21.8,0);
-INSERT INTO "extent" VALUES('EPSG','4543','Serbia','Serbia including Vojvodinja.',42.23,46.19,18.81,23.01,0);
+INSERT INTO "extent" VALUES('EPSG','4543','Serbia','Serbia including Vojvodina.',42.232494354248,46.18111038208,18.81702041626,23.004997253418,0);
INSERT INTO "extent" VALUES('EPSG','4544','North America - Canada, US (Conus+AK), PRVI','North America - onshore and offshore: Canada - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon. Puerto Rico. United States (USA) - Alabama; Alaska; Arizona; Arkansas; California; Colorado; Connecticut; Delaware; Florida; Georgia; Idaho; Illinois; Indiana; Iowa; Kansas; Kentucky; Louisiana; Maine; Maryland; Massachusetts; Michigan; Minnesota; Mississippi; Missouri; Montana; Nebraska; Nevada; New Hampshire; New Jersey; New Mexico; New York; North Carolina; North Dakota; Ohio; Oklahoma; Oregon; Pennsylvania; Rhode Island; South Carolina; South Dakota; Tennessee; Texas; Utah; Vermont; Virginia; Washington; West Virginia; Wisconsin; Wyoming. US Virgin Islands.',14.92,86.46,167.65,-47.74,0);
INSERT INTO "extent" VALUES('EPSG','4545','Vietnam - Ca Mau and Kien Giang','Vietnam - Ca Mau and Kien Giang provinces.',8.33,10.55,103.4,105.54,0);
INSERT INTO "extent" VALUES('EPSG','4546','Vietnam - An Giang, Lao Cai, Nghe An, Phu Tho, Yen Bai','Vietnam - An Giang, Lao Cai, Nghe An, Phu Tho and Yen Bai provinces.',10.18,22.85,103.53,105.86,0);
@@ -3585,3 +3585,4 @@ INSERT INTO "extent" VALUES('EPSG','4606','Europe - British Isles - UK and Irela
INSERT INTO "extent" VALUES('EPSG','4607','UK - Glasgow to Kilmarnock','UK - on or related to the rail route from Glasgow via Barrhead to Kilmarnock and the branch to East Kilbride.',55.55,55.95,-4.65,-4.05,0);
INSERT INTO "extent" VALUES('EPSG','4608','Europe - EVRF2019','Europe - onshore - Andorra; Austria; Belarus; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Czechia; Denmark; Estonia; Finland; France - mainland; Germany; Gibraltar, Hungary; Italy - mainland and Sicily; Latvia; Liechtenstein; Lithuania; Luxembourg; Netherlands; North Macedonia; Norway; Poland; Portugal - mainland; Romania; Russia – west of approximately 60°E; San Marino; Slovakia; Slovenia; Spain - mainland; Sweden; Switzerland; United Kingdom (UK) - Great Britain mainland; Ukraine; Vatican City State.',35.95,77.07,-9.56,69.15,0);
INSERT INTO "extent" VALUES('EPSG','4609','Europe - ETRF EVRF2019','Europe - onshore - Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Czechia; Denmark; Estonia; Finland; France - mainland; Germany; Gibraltar, Hungary; Italy - mainland and Sicily; Latvia; Liechtenstein; Lithuania; Luxembourg; Netherlands; North Macedonia; Norway; Poland; Portugal - mainland; Romania; San Marino; Slovakia; Slovenia; Spain - mainland; Sweden; Switzerland; United Kingdom (UK) - Great Britain mainland; Vatican City State.',35.95,71.21,-9.56,31.59,0);
+INSERT INTO "extent" VALUES('EPSG','4610','Argentina - Buenos Aires city','Argentina - autonomous city of Buenos Aires.',-34.705314975913,-34.506992229796,-58.531465195974,-58.29240989685,0);
diff --git a/data/sql/geodetic_crs.sql b/data/sql/geodetic_crs.sql
index d2aecc13..545e8c91 100644
--- a/data/sql/geodetic_crs.sql
+++ b/data/sql/geodetic_crs.sql
@@ -2090,8 +2090,8 @@ INSERT INTO "geodetic_crs" VALUES('EPSG','9378','IGb14',NULL,'geocentric','EPSG'
INSERT INTO "usage" VALUES('EPSG','13999','geodetic_crs','EPSG','9378','EPSG','2830','EPSG','1027');
INSERT INTO "geodetic_crs" VALUES('EPSG','9379','IGb14',NULL,'geographic 3D','EPSG','6423','EPSG','1272',NULL,0);
INSERT INTO "usage" VALUES('EPSG','14000','geodetic_crs','EPSG','9379','EPSG','1262','EPSG','1027');
-INSERT INTO "geodetic_crs" VALUES('EPSG','9380','IGb14',NULL,'geographic 2D','EPSG','6422','EPSG','1191',NULL,0);
-INSERT INTO "usage" VALUES('EPSG','14001','geodetic_crs','EPSG','9380','EPSG','1262','EPSG','1027');
+INSERT INTO "geodetic_crs" VALUES('EPSG','9380','IGb14',NULL,'geographic 2D','EPSG','6422','EPSG','1272',NULL,0);
+INSERT INTO "usage" VALUES('EPSG','14213','geodetic_crs','EPSG','9380','EPSG','1262','EPSG','1027');
INSERT INTO "geodetic_crs" VALUES('EPSG','9384','AbInvA96_2020-IRF',NULL,'geographic 2D','EPSG','6422','EPSG','1273',NULL,0);
INSERT INTO "usage" VALUES('EPSG','14028','geodetic_crs','EPSG','9384','EPSG','4589','EPSG','1196');
INSERT INTO "geodetic_crs" VALUES('EPSG','9403','PN68',NULL,'geographic 2D','EPSG','6422','EPSG','1286',NULL,0);
@@ -2104,3 +2104,7 @@ INSERT INTO "geodetic_crs" VALUES('EPSG','9469','SRGI2013',NULL,'geographic 3D',
INSERT INTO "usage" VALUES('EPSG','14151','geodetic_crs','EPSG','9469','EPSG','1122','EPSG','1027');
INSERT INTO "geodetic_crs" VALUES('EPSG','9470','SRGI2013',NULL,'geographic 2D','EPSG','6422','EPSG','1293',NULL,0);
INSERT INTO "usage" VALUES('EPSG','14152','geodetic_crs','EPSG','9470','EPSG','1122','EPSG','1183');
+INSERT INTO "geodetic_crs" VALUES('EPSG','9474','PZ-90.02',NULL,'geographic 2D','EPSG','6422','EPSG','1157',NULL,0);
+INSERT INTO "usage" VALUES('EPSG','14195','geodetic_crs','EPSG','9474','EPSG','1262','EPSG','1183');
+INSERT INTO "geodetic_crs" VALUES('EPSG','9475','PZ-90.11',NULL,'geographic 2D','EPSG','6422','EPSG','1158',NULL,0);
+INSERT INTO "usage" VALUES('EPSG','14194','geodetic_crs','EPSG','9475','EPSG','1262','EPSG','1183');
diff --git a/data/sql/geodetic_datum.sql b/data/sql/geodetic_datum.sql
index 5ccc5410..47b4c498 100644
--- a/data/sql/geodetic_datum.sql
+++ b/data/sql/geodetic_datum.sql
@@ -1177,6 +1177,6 @@ INSERT INTO "usage" VALUES('EPSG','13848','geodetic_datum','EPSG','6903','EPSG',
INSERT INTO "geodetic_datum" VALUES('EPSG','6904','Lisbon 1890 (Lisbon)',NULL,'EPSG','7004','EPSG','8902','1937-01-01',NULL,NULL,0);
INSERT INTO "usage" VALUES('EPSG','13849','geodetic_datum','EPSG','6904','EPSG','1294','EPSG','1153');
INSERT INTO "geodetic_datum" VALUES('EPSG','6258','European Terrestrial Reference System 1989 ensemble',NULL,'EPSG','7019','EPSG','8901',NULL,NULL,0.1,0);
-INSERT INTO "usage" VALUES('EPSG','13599','geodetic_datum','EPSG','6258','EPSG','1298','EPSG','1026');
+INSERT INTO "usage" VALUES('EPSG','14235','geodetic_datum','EPSG','6258','EPSG','1298','EPSG','1026');
INSERT INTO "geodetic_datum" VALUES('EPSG','6326','World Geodetic System 1984 ensemble',NULL,'EPSG','7030','EPSG','8901',NULL,NULL,2.0,0);
-INSERT INTO "usage" VALUES('EPSG','13661','geodetic_datum','EPSG','6326','EPSG','1262','EPSG','1245');
+INSERT INTO "usage" VALUES('EPSG','14343','geodetic_datum','EPSG','6326','EPSG','1262','EPSG','1245');
diff --git a/data/sql/grid_transformation.sql b/data/sql/grid_transformation.sql
index 80b310f8..5bd59179 100644
--- a/data/sql/grid_transformation.sql
+++ b/data/sql/grid_transformation.sql
@@ -277,7 +277,7 @@ INSERT INTO "usage" VALUES('EPSG','8673','grid_transformation','EPSG','1752','EP
INSERT INTO "grid_transformation" VALUES('EPSG','1803','AGD66 to GDA94 (11)','Replaces AGD66 to GDA94 variants 6, 7 and 10 (codes 1506 1507 1596). Input expects longitudes to be positive west; EPSG GeogCRS AGD66 (code 4202) and GDA94 (code 4283) both have longitudes positive east. May be used as tfm to WGS 84 - see code 15786.','EPSG','9615','NTv2','EPSG','4202','EPSG','4283',0.1,'EPSG','8656','Latitude and longitude difference file','A66 National (13.09.01).gsb',NULL,NULL,NULL,NULL,NULL,NULL,'ICSM-Aus 0.1m',0);
INSERT INTO "usage" VALUES('EPSG','8724','grid_transformation','EPSG','1803','EPSG','2575','EPSG','1031');
INSERT INTO "grid_transformation" VALUES('EPSG','1804','AGD84 to GDA94 (5)','Replaces AGD84 to GDA94 (4) (code 1593) which itself replaced variant 3 (code 1559). Input expects longitudes to be + west; EPSG GeogCRS AGD84 (code 4203) and GDA94 (code 4283) both have longitudes positive east. May be used as tfm to WGS 84 - see 15785','EPSG','9615','NTv2','EPSG','4203','EPSG','4283',0.1,'EPSG','8656','Latitude and longitude difference file','National 84 (02.07.01).gsb',NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 0.1m',0);
-INSERT INTO "usage" VALUES('EPSG','8725','grid_transformation','EPSG','1804','EPSG','2576','EPSG','1031');
+INSERT INTO "usage" VALUES('EPSG','14199','grid_transformation','EPSG','1804','EPSG','2576','EPSG','1031');
INSERT INTO "grid_transformation" VALUES('EPSG','1841','ATS77 to NAD83(CSRS) (1)','Introduced in 1999. Can be taken as an approximate transformation ATS77 to WGS 84 - see code 1688.','EPSG','9615','NTv2','EPSG','4122','EPSG','4617',1.5,'EPSG','8656','Latitude and longitude difference file','NB7783v2.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'GIC-Can NB',1);
INSERT INTO "usage" VALUES('EPSG','8762','grid_transformation','EPSG','1841','EPSG','1447','EPSG','1231');
INSERT INTO "grid_transformation" VALUES('EPSG','1843','NAD83 to NAD83(CSRS) (1)','Uses NT method which expects longitudes positive west; EPSG GeogCRSs NAD83 (code 4269) and NAD83(CSRS) (code 4617) have longitudes positive east. Can be taken as an approximate transformation NAD83 to WGS 84 - see code 1696.','EPSG','9615','NTv2','EPSG','4269','EPSG','4617',1.5,'EPSG','8656','Latitude and longitude difference file','NAD83-98.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'SGQ-Can QC',1);
@@ -826,6 +826,14 @@ INSERT INTO "grid_transformation" VALUES('EPSG','9466','GDA2020 to GDA2020 + AHD
INSERT INTO "usage" VALUES('EPSG','14146','grid_transformation','EPSG','9466','EPSG','4493','EPSG','1133');
INSERT INTO "grid_transformation" VALUES('EPSG','9467','GDA94 to GDA94 + AHD height (1)','Reversible alternative to GDA94 to AHD height (1) (code 5656). Uses AUSGeoid09 model which uses bi-cubic interpolation; bi-linear interpolation of the grid file will give results agreeing to within 1cm 99.97% of the time.','EPSG','1083','Geog3D to Geog2D+Vertical (AUSGeoid v2)','EPSG','4939','EPSG','9464',0.15,'EPSG','8666','Geoid (height correction) model file','AUSGeoid09_V1.01.gsb',NULL,NULL,NULL,NULL,'EPSG','4283','GA-Aus09',0);
INSERT INTO "usage" VALUES('EPSG','14147','grid_transformation','EPSG','9467','EPSG','4493','EPSG','1133');
+INSERT INTO "grid_transformation" VALUES('EPSG','9483','Canada velocity grid v7','','EPSG','1070','Point motion by grid (Canada NTv2_Vel)','EPSG','8254','EPSG','8254',0.01,'EPSG','1050','Point motion velocity grid file','cvg70.cvb',NULL,NULL,NULL,NULL,NULL,NULL,'NRC-Can cvg7.0',0);
+INSERT INTO "usage" VALUES('EPSG','14214','grid_transformation','EPSG','9483','EPSG','1061','EPSG','1131');
+INSERT INTO "grid_transformation" VALUES('EPSG','9484','ETRS89 to NN54 height (1)','','EPSG','9665','Geographic3D to GravityRelatedHeight (gtx)','EPSG','4937','EPSG','5776',0.02,'EPSG','8666','Geoid (height correction) model file','href2008a.gtx',NULL,NULL,NULL,NULL,NULL,NULL,'SK-Nor 2008',0);
+INSERT INTO "usage" VALUES('EPSG','14215','grid_transformation','EPSG','9484','EPSG','1352','EPSG','1133');
+INSERT INTO "grid_transformation" VALUES('EPSG','9485','ETRS89 to NN2000 height (1)','','EPSG','9665','Geographic3D to GravityRelatedHeight (gtx)','EPSG','4937','EPSG','5941',0.02,'EPSG','8666','Geoid (height correction) model file','HREF2018B_NN2000_EUREF89.gtx',NULL,NULL,NULL,NULL,NULL,NULL,'SK-Nor 2018',0);
+INSERT INTO "usage" VALUES('EPSG','14216','grid_transformation','EPSG','9485','EPSG','1352','EPSG','1133');
+INSERT INTO "grid_transformation" VALUES('EPSG','9496','MGI 1901 to SRB-ETRS89 (9)','','EPSG','9615','NTv2','EPSG','3906','EPSG','8685',0.03,'EPSG','8656','Latitude and longitude difference file','MGI1901_TO_SRBETRS89_NTv2.gsb',NULL,NULL,NULL,NULL,NULL,NULL,'RGZ-Srb 0.1m 2020',0);
+INSERT INTO "usage" VALUES('EPSG','14226','grid_transformation','EPSG','9496','EPSG','4543','EPSG','1185');
INSERT INTO "grid_transformation" VALUES('EPSG','10000','RGF93 to NGF-IGN69 height (1)','May be used for transformations from WGS 84 to NGF-IGN69 height. Accuracy at each 0.1 deg x 0.1 degree grid node is given within the geoid model file.','EPSG','9664','Geographic3D to GravityRelatedHeight (IGN1997)','EPSG','4965','EPSG','5720',0.5,'EPSG','8666','Geoid (height correction) model file','ggf97a.txt',NULL,NULL,NULL,NULL,NULL,NULL,'IGN Fra',0);
INSERT INTO "usage" VALUES('EPSG','11001','grid_transformation','EPSG','10000','EPSG','1326','EPSG','1133');
INSERT INTO "grid_transformation" VALUES('EPSG','10001','ETRS89 to NGF-IGN69 height (1)','Parameter values taken from RGF93 to NGF-IGN69 height (1) (code 10000) assuming that RGF93 is equivalent to ETRS89 within the accuracy of the transformation. Accuracy at each 0.1 deg x 0.1 degree grid node is given within the geoid model file.','EPSG','9664','Geographic3D to GravityRelatedHeight (IGN1997)','EPSG','4937','EPSG','5720',0.5,'EPSG','8666','Geoid (height correction) model file','ggf97a.txt',NULL,NULL,NULL,NULL,NULL,NULL,'IGN Fra',0);
diff --git a/data/sql/helmert_transformation.sql b/data/sql/helmert_transformation.sql
index b3238817..ff7e9a42 100644
--- a/data/sql/helmert_transformation.sql
+++ b/data/sql/helmert_transformation.sql
@@ -416,7 +416,7 @@ INSERT INTO "usage" VALUES('EPSG','8199','helmert_transformation','EPSG','1278',
INSERT INTO "helmert_transformation" VALUES('EPSG','1279','AGD84 to GDA94 (1)','Derived at 327 stations. May be taken as approximate transformation AGD84 to WGS 84 - see code 15789. For higher accuracy use AGD84 to GDA94 (2) (code 1280). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4203','EPSG','4283',5.0,-128.5,-53.0,153.4,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 5m',0);
INSERT INTO "usage" VALUES('EPSG','8200','helmert_transformation','EPSG','1279','EPSG','2576','EPSG','1045');
INSERT INTO "helmert_transformation" VALUES('EPSG','1280','AGD84 to GDA94 (2)','Replaces AGD84 to WGS 84 (2) (code 1236). May be taken as approximate transformation AGD84 to WGS 84 - see code 1669. Note: although applicable nationwide, AGD84 officially adopted only in Queensland, South Australia and Western Australia.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4203','EPSG','4283',1.0,-117.763,-51.51,139.061,'EPSG','9001',-0.292,-0.443,-0.277,'EPSG','9104',-0.191,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'Auslig-Aus 1m',0);
-INSERT INTO "usage" VALUES('EPSG','8201','helmert_transformation','EPSG','1280','EPSG','2576','EPSG','1041');
+INSERT INTO "usage" VALUES('EPSG','14198','helmert_transformation','EPSG','1280','EPSG','2576','EPSG','1041');
INSERT INTO "helmert_transformation" VALUES('EPSG','1281','Pulkovo 1995 to WGS 84 (1)','Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4200','EPSG','4326',1.0,24.82,-131.21,-82.66,'EPSG','9001',0.0,0.0,-0.16,'EPSG','9104',-0.12,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'GOST-Rus',0);
INSERT INTO "usage" VALUES('EPSG','8202','helmert_transformation','EPSG','1281','EPSG','1198','EPSG','1041');
INSERT INTO "helmert_transformation" VALUES('EPSG','1282','Samboja to WGS 84 (1)','Datum shift derived through ITRF93.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4125','EPSG','4326',NULL,-404.78,685.68,45.47,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'TOT-Idn Mah',1);
@@ -2036,8 +2036,8 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','8270','Saint Pierre et Mique
INSERT INTO "usage" VALUES('EPSG','10463','helmert_transformation','EPSG','8270','EPSG','3299','EPSG','1041');
INSERT INTO "helmert_transformation" VALUES('EPSG','8365','ETRS89 to S-JTSK [JTSK03] (1)','Derived at 684 points with known S-JTSK and ETRS89 (ETRF2000 realization) coordinates. Scale parameter was constrained to be zero. UGKK consider this transformation to not be reversible at the 1mm accuracy level: for reverse see transformation code 8367.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4258','EPSG','8351',0.001,-485.014055,-169.473618,-483.842943,'EPSG','9001',7.78625453,4.39770887,4.10248899,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0);
INSERT INTO "usage" VALUES('EPSG','10512','helmert_transformation','EPSG','8365','EPSG','1211','EPSG','1115');
-INSERT INTO "helmert_transformation" VALUES('EPSG','8366','ITRF2014 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m. See ITRF2014 to ETRF2014 (2) (code 8407) for an exactly equivalent transformation but with the transformation''s parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',0.0,0.0,0.0,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',1989.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur',0);
-INSERT INTO "usage" VALUES('EPSG','10513','helmert_transformation','EPSG','8366','EPSG','1298','EPSG','1129');
+INSERT INTO "helmert_transformation" VALUES('EPSG','8366','ITRF2014 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m. See ITRF2014 to ETRF2014 (2) (code 8880) for an exactly equivalent transformation but with the transformation''s parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',0.0,0.0,0.0,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',1989.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur',0);
+INSERT INTO "usage" VALUES('EPSG','14203','helmert_transformation','EPSG','8366','EPSG','1298','EPSG','1129');
INSERT INTO "helmert_transformation" VALUES('EPSG','8367','S-JTSK [JTSK03] to ETRS89 (1)','Derived at 684 points. At the 1mm accuracy level this transformation is not reversible: for reverse see transformation code 8365. May be taken as approximate transformation to WGS 84 - see code 8368.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8351','EPSG','4258',0.001,485.021,169.465,483.839,'EPSG','9001',-7.786342,-4.397554,-4.102655,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0);
INSERT INTO "usage" VALUES('EPSG','10514','helmert_transformation','EPSG','8367','EPSG','1211','EPSG','1027');
INSERT INTO "helmert_transformation" VALUES('EPSG','8368','S-JTSK [JTSK03] to WGS 84 (1)','Parameter values taken from S-JTSK [JTSK03] to ETRS89 (1) (code 8367) assuming that ETRS89 (ETRF2000 realization) is coincident with WGS 84 within the accuracy of the transformation. Within the 1m accuracy of this transformation, it is reversible.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8351','EPSG','4326',1.0,485.021,169.465,483.839,'EPSG','9001',-7.786342,-4.397554,-4.102655,'EPSG','9104',0.0,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'UGKK-Svk',0);
@@ -2172,8 +2172,8 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','8878','ITRF90 to ETRF2014 (1
INSERT INTO "usage" VALUES('EPSG','10820','helmert_transformation','EPSG','8878','EPSG','1298','EPSG','1027');
INSERT INTO "helmert_transformation" VALUES('EPSG','8879','ITRF89 to ETRF2014 (1)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9 or nm/m.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','4911','EPSG','8401',0.0,-30.4,-35.5,130.8,'EPSG','1025',1.785,11.151,-16.43,'EPSG','1031',-8.19,'EPSG','1028',-0.1,0.5,3.3,'EPSG','1027',0.085,0.531,-0.79,'EPSG','1032',-0.12,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0);
INSERT INTO "usage" VALUES('EPSG','10821','helmert_transformation','EPSG','8879','EPSG','1298','EPSG','1027');
-INSERT INTO "helmert_transformation" VALUES('EPSG','8880','ITRF2014 to ETRF2014 (2)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9. See ITRF2014 to ETRF2014 (1) (code 8366) for transformation which defines ETRF2014. Transformation 8407 is equivalent to 8366 but with parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',1.785,11.151,-16.17,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0);
-INSERT INTO "usage" VALUES('EPSG','10822','helmert_transformation','EPSG','8880','EPSG','1298','EPSG','1027');
+INSERT INTO "helmert_transformation" VALUES('EPSG','8880','ITRF2014 to ETRF2014 (2)','Scale difference in ppb and scale difference rate in ppb/yr where 1/billion = 1E-9. See ITRF2014 to ETRF2014 (1) (code 8366) for transformation which defines ETRF2014. Transformation 8880 is equivalent to 8366 but with parameter values at epoch 2010.00.','EPSG','1053','Time-dependent Position Vector tfm (geocentric)','EPSG','7789','EPSG','8401',0.0,0.0,0.0,0.0,'EPSG','1025',1.785,11.151,-16.17,'EPSG','1031',0.0,'EPSG','1028',0.0,0.0,0.0,'EPSG','1027',0.085,0.531,-0.77,'EPSG','1032',0.0,'EPSG','1030',2010.0,'EPSG','1029',NULL,NULL,NULL,NULL,NULL,'EUREF-Eur 2014',0);
+INSERT INTO "usage" VALUES('EPSG','14204','helmert_transformation','EPSG','8880','EPSG','1298','EPSG','1027');
INSERT INTO "helmert_transformation" VALUES('EPSG','8882','Camacupa 2015 to WGS 84 (11)','Used by CIDDEMA for delimitation of Angola''s EEZ boundary. Derived by Univ. of Lisbon using 38 REPANGOL points. Average horizontal error 1m, vertical 3m; max radial error 6m. Application offshore differs from Camacupa 1948 to WGS 84 by approx 25m.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','8694','EPSG','4326',3.0,-93.799,-132.737,-219.073,'EPSG','9001',1.844,-0.648,6.37,'EPSG','9104',-0.169,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'CIDDEMA-Ago',0);
INSERT INTO "usage" VALUES('EPSG','10823','helmert_transformation','EPSG','8882','EPSG','1029','EPSG','1053');
INSERT INTO "helmert_transformation" VALUES('EPSG','8883','Camacupa 1948 to RSAO13 (1)','Parameter values taken from Camacupa 1948 to WGS 84 (7) (code 1324) assuming that RSAO13 is coincident with WGS 84 within the accuracy of the transformation.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4220','EPSG','8699',3.0,-48.0,-345.0,-231.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ELF-Ago B15',0);
@@ -2406,6 +2406,10 @@ INSERT INTO "helmert_transformation" VALUES('EPSG','9460','ITRF2014 to ATRF2014
INSERT INTO "usage" VALUES('EPSG','14140','helmert_transformation','EPSG','9460','EPSG','4177','EPSG','1268');
INSERT INTO "helmert_transformation" VALUES('EPSG','9472','DGN95 to SRGI2013 (1)','Derived at 533 stations. Mean residual 0.218m. Note: information source gives rotations given in radians.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4755','EPSG','9470',0.2,-0.2773,0.0534,0.4819,'EPSG','9001',0.0935,-0.0286,0.00969,'EPSG','9109',-0.028,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'SRGI-Idn',0);
INSERT INTO "usage" VALUES('EPSG','14154','helmert_transformation','EPSG','9472','EPSG','1122','EPSG','1026');
+INSERT INTO "helmert_transformation" VALUES('EPSG','9486','MGI 1901 to WGS 84 (15)','Parameter values from MGI 1901 to ETRS89 (8) (code 9495). Assumes SRB-ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','3906','EPSG','4326',1.0,577.84843,165.45019,390.43652,'EPSG','9001',-4.93131,0.96052,13.05072,'EPSG','9104',7.86546,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'IOGP-Srb 2020',0);
+INSERT INTO "usage" VALUES('EPSG','14220','helmert_transformation','EPSG','9486','EPSG','4543','EPSG','1041');
+INSERT INTO "helmert_transformation" VALUES('EPSG','9495','MGI 1901 to SRB-ETRS89 (8)','','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','3906','EPSG','8685',0.46,577.84843,165.45019,390.43652,'EPSG','9001',-4.93131,0.96052,13.05072,'EPSG','9104',7.86546,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'RGZ-Srb 0.5m 2020',0);
+INSERT INTO "usage" VALUES('EPSG','14227','helmert_transformation','EPSG','9495','EPSG','4543','EPSG','1153');
INSERT INTO "helmert_transformation" VALUES('EPSG','10085','Trinidad 1903 to WGS 84 (2)','Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4302','EPSG','4326',3.0,-61.0,285.2,471.6,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'EOG-Tto Trin',0);
INSERT INTO "usage" VALUES('EPSG','11086','helmert_transformation','EPSG','10085','EPSG','1339','EPSG','1136');
INSERT INTO "helmert_transformation" VALUES('EPSG','10086','JAD69 to WGS 72 (1)','Derived in 1977 through Transit observations at 2 stations by US DMA.','EPSG','9603','Geocentric translations (geog2D domain)','EPSG','4242','EPSG','4322',15.0,48.0,208.0,382.0,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'SD-Jam',0);
@@ -2896,7 +2900,7 @@ INSERT INTO "usage" VALUES('EPSG','11987','helmert_transformation','EPSG','15977
INSERT INTO "helmert_transformation" VALUES('EPSG','15978','NAD27 to WGS 84 (88)','','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4267','EPSG','4326',1.0,2.478,149.752,197.726,'EPSG','9001',-0.526,-0.498,0.501,'EPSG','9104',0.685,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ONHG-Cub',0);
INSERT INTO "usage" VALUES('EPSG','11988','helmert_transformation','EPSG','15978','EPSG','1077','EPSG','1041');
INSERT INTO "helmert_transformation" VALUES('EPSG','15979','AGD66 to GDA94 (12)','Use only offshore: onshore, tfms 1458 (ACT), 1594 (Tas), 1460 (NSW and Vic) and 1595 (NT) are more accurate.May be used as a tfm to WGS 84 - see code 15980.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4202','EPSG','4283',3.0,-117.808,-51.536,137.784,'EPSG','9001',-0.303,-0.446,-0.234,'EPSG','9104',-0.29,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'ICSM-Aus off',0);
-INSERT INTO "usage" VALUES('EPSG','11989','helmert_transformation','EPSG','15979','EPSG','3559','EPSG','1043');
+INSERT INTO "usage" VALUES('EPSG','14200','helmert_transformation','EPSG','15979','EPSG','3559','EPSG','1043');
INSERT INTO "helmert_transformation" VALUES('EPSG','15980','AGD66 to WGS 84 (18)','Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4202','EPSG','4326',3.0,-117.808,-51.536,137.784,'EPSG','9001',-0.303,-0.446,-0.234,'EPSG','9104',-0.29,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'EPSG-Aus off',0);
INSERT INTO "usage" VALUES('EPSG','11990','helmert_transformation','EPSG','15980','EPSG','3559','EPSG','1043');
INSERT INTO "helmert_transformation" VALUES('EPSG','15981','MGI to Slovenia 1996 (1)','Info source also gives a separate reverse tfm with slightly different parameter values. Given the tfm accuracy these differences are not significant and this tfm can be considered reversible. May be taken as approximate tfm MGI to WGS 84 (see code 15982)','EPSG','9607','Coordinate Frame rotation (geog2D domain)','EPSG','4312','EPSG','4765',1.0,409.545,72.164,486.872,'EPSG','9001',-3.085957,-5.46911,11.020289,'EPSG','9104',17.919665,'EPSG','9202',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'GuRS-Svn',1);
diff --git a/data/sql/metadata.sql b/data/sql/metadata.sql
index 8db35745..adcee507 100644
--- a/data/sql/metadata.sql
+++ b/data/sql/metadata.sql
@@ -1,2 +1,13 @@
-INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.003');
-INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-10-05');
+-- Version of the database structure.
+-- The major number indicates an incompatible change (e.g. table or column
+-- removed or renamed).
+-- The minor number is incremented if a backward compatible change done, that
+-- is the new database can still work with an older PROJ version.
+-- When updating those numbers, the DATABASE_LAYOUT_VERSION_MAJOR and
+-- DATABASE_LAYOUT_VERSION_MINOR constants in src/iso19111/factory.cpp must be
+-- updated as well.
+INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MAJOR', 1);
+INSERT INTO "metadata" VALUES('DATABASE.LAYOUT.VERSION.MINOR', 0);
+
+INSERT INTO "metadata" VALUES('EPSG.VERSION', 'v10.007');
+INSERT INTO "metadata" VALUES('EPSG.DATE', '2020-11-18');
diff --git a/data/sql/proj_db_table_defs.sql b/data/sql/proj_db_table_defs.sql
index 05c64e45..b879cab8 100644
--- a/data/sql/proj_db_table_defs.sql
+++ b/data/sql/proj_db_table_defs.sql
@@ -1460,9 +1460,9 @@ CREATE VIEW object_view AS
UNION ALL
SELECT 'prime_meridian', auth_name, code, name, NULL, deprecated FROM prime_meridian
UNION ALL
- SELECT 'geodetic_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN "ensemble" ELSE "datum" END, deprecated FROM geodetic_datum
+ SELECT 'geodetic_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN 'ensemble' ELSE 'datum' END, deprecated FROM geodetic_datum
UNION ALL
- SELECT 'vertical_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN "ensemble" ELSE "datum" END, deprecated FROM vertical_datum
+ SELECT 'vertical_datum', auth_name, code, name, CASE WHEN ensemble_accuracy IS NOT NULL THEN 'ensemble' ELSE 'datum' END, deprecated FROM vertical_datum
UNION ALL
SELECT 'axis', auth_name, code, name, NULL, 0 as deprecated FROM axis
UNION ALL
diff --git a/data/sql/projected_crs.sql b/data/sql/projected_crs.sql
index ea7c9b71..a2adb443 100644
--- a/data/sql/projected_crs.sql
+++ b/data/sql/projected_crs.sql
@@ -7302,6 +7302,8 @@ INSERT INTO "projected_crs" VALUES('EPSG','9493','SRGI2013 / UTM zone 53S',NULL,
INSERT INTO "usage" VALUES('EPSG','14171','projected_crs','EPSG','9493','EPSG','1662','EPSG','1266');
INSERT INTO "projected_crs" VALUES('EPSG','9494','SRGI2013 / UTM zone 54S',NULL,'EPSG','4400','EPSG','9470','EPSG','16154',NULL,0);
INSERT INTO "usage" VALUES('EPSG','14172','projected_crs','EPSG','9494','EPSG','1663','EPSG','1266');
+INSERT INTO "projected_crs" VALUES('EPSG','9498','POSGAR 2007 / CABA 2019',NULL,'EPSG','4500','EPSG','5340','EPSG','9497',NULL,0);
+INSERT INTO "usage" VALUES('EPSG','14243','projected_crs','EPSG','9498','EPSG','4610','EPSG','1056');
INSERT INTO "projected_crs" VALUES('EPSG','20004','Pulkovo 1995 / Gauss-Kruger zone 4',NULL,'EPSG','4530','EPSG','4200','EPSG','16204',NULL,0);
INSERT INTO "usage" VALUES('EPSG','6177','projected_crs','EPSG','20004','EPSG','1763','EPSG','1211');
INSERT INTO "projected_crs" VALUES('EPSG','20005','Pulkovo 1995 / Gauss-Kruger zone 5',NULL,'EPSG','4530','EPSG','4200','EPSG','16205',NULL,0);
diff --git a/data/sql/scope.sql b/data/sql/scope.sql
index 993057f7..9f314f37 100644
--- a/data/sql/scope.sql
+++ b/data/sql/scope.sql
@@ -107,6 +107,7 @@ INSERT INTO "scope" VALUES('EPSG','1127','Geodesy. Defines ETRF2000.',0);
INSERT INTO "scope" VALUES('EPSG','1128','Geodesy. Defines ETRF2005.',0);
INSERT INTO "scope" VALUES('EPSG','1129','Geodesy. Defines ETRF2014.',0);
INSERT INTO "scope" VALUES('EPSG','1130','EEZ delimitation.',0);
+INSERT INTO "scope" VALUES('EPSG','1131','Change of coordinate epoch for points referenced to NAD83(CSRS)v7.',0);
INSERT INTO "scope" VALUES('EPSG','1132','Derivation of approximate gravity-related heights from GNSS observations.',0);
INSERT INTO "scope" VALUES('EPSG','1133','Derivation of gravity-related heights from GNSS observations.',0);
INSERT INTO "scope" VALUES('EPSG','1134','Description of the use or purpose of the CRS.',0);
diff --git a/data/sql/supersession.sql b/data/sql/supersession.sql
index 0ed78ad6..8148c911 100644
--- a/data/sql/supersession.sql
+++ b/data/sql/supersession.sql
@@ -246,3 +246,5 @@ INSERT INTO "supersession" VALUES('grid_transformation','EPSG','9168','grid_tran
INSERT INTO "supersession" VALUES('grid_transformation','EPSG','9169','grid_transformation','EPSG','9174','EPSG',0);
INSERT INTO "supersession" VALUES('grid_transformation','EPSG','15932','grid_transformation','EPSG','9409','EPSG',1);
INSERT INTO "supersession" VALUES('grid_transformation','EPSG','15932','grid_transformation','EPSG','9408','EPSG',1);
+INSERT INTO "supersession" VALUES('helmert_transformation','EPSG','7675','helmert_transformation','EPSG','9495','EPSG',0);
+INSERT INTO "supersession" VALUES('helmert_transformation','EPSG','7676','helmert_transformation','EPSG','9486','EPSG',1);
diff --git a/data/sql/vertical_crs.sql b/data/sql/vertical_crs.sql
index 0a30c44f..ab265193 100644
--- a/data/sql/vertical_crs.sql
+++ b/data/sql/vertical_crs.sql
@@ -85,7 +85,7 @@ INSERT INTO "usage" VALUES('EPSG','4152','vertical_crs','EPSG','5709','EPSG','11
INSERT INTO "vertical_crs" VALUES('EPSG','5710','Ostend height',NULL,'EPSG','6499','EPSG','5110',0);
INSERT INTO "usage" VALUES('EPSG','4153','vertical_crs','EPSG','5710','EPSG','1347','EPSG','1179');
INSERT INTO "vertical_crs" VALUES('EPSG','5711','AHD height',NULL,'EPSG','6499','EPSG','5111',0);
-INSERT INTO "usage" VALUES('EPSG','4154','vertical_crs','EPSG','5711','EPSG','4493','EPSG','1263');
+INSERT INTO "usage" VALUES('EPSG','14230','vertical_crs','EPSG','5711','EPSG','4493','EPSG','1263');
INSERT INTO "vertical_crs" VALUES('EPSG','5712','AHD (Tasmania) height',NULL,'EPSG','6499','EPSG','5112',0);
INSERT INTO "usage" VALUES('EPSG','4155','vertical_crs','EPSG','5712','EPSG','2947','EPSG','1179');
INSERT INTO "vertical_crs" VALUES('EPSG','5713','CGVD28 height',NULL,'EPSG','6499','EPSG','5114',0);
@@ -481,6 +481,6 @@ INSERT INTO "usage" VALUES('EPSG','14041','vertical_crs','EPSG','9402','EPSG','4
INSERT INTO "vertical_crs" VALUES('EPSG','9451','BI height',NULL,'EPSG','6499','EPSG','1288',0);
INSERT INTO "usage" VALUES('EPSG','14087','vertical_crs','EPSG','9451','EPSG','4606','EPSG','1026');
INSERT INTO "vertical_crs" VALUES('EPSG','9458','AVWS height',NULL,'EPSG','6499','EPSG','1292',0);
-INSERT INTO "usage" VALUES('EPSG','14138','vertical_crs','EPSG','9458','EPSG','4177','EPSG','1264');
+INSERT INTO "usage" VALUES('EPSG','14231','vertical_crs','EPSG','9458','EPSG','4177','EPSG','1264');
INSERT INTO "vertical_crs" VALUES('EPSG','9471','INAGeoid2020 height',NULL,'EPSG','6499','EPSG','1294',0);
INSERT INTO "usage" VALUES('EPSG','14153','vertical_crs','EPSG','9471','EPSG','1122','EPSG','1178');
diff --git a/docs/Makefile b/docs/Makefile
index b9fa8257..22399302 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -4,18 +4,43 @@
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
+HTMLOPTS ?= -W
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
+.PHONY: clean
+clean:
+ rm -rf $(BUILDDIR)/*
+ rm -rf .doxygen_up_to_date
+
+.doxygen_up_to_date:
+ ../scripts/doxygen.sh
+ touch .doxygen_up_to_date
+
+.PHONY: html
+html: .doxygen_up_to_date
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(HTMLOPTS) $(BUILDDIR)/html
+ # Undoes the hack done in scripts/doxygen.sh
+ @sed "s/io::Convention_/io::Convention/g" < $(BUILDDIR)/html/development/reference/cpp/io.html | sed "s/>Convention_/>Convention/g" | sed "s/_WKT2/WKT2/g" | sed "s/_WKT1/WKT1/g" > $(BUILDDIR)/html/development/reference/cpp/io.html.tmp
+ @mv $(BUILDDIR)/html/development/reference/cpp/io.html.tmp $(BUILDDIR)/html/development/reference/cpp/io.html
+ # Undoes the hacks of scripts/generate_breathe_friendly_general_doc.py
+ @sed "s/<em class=\"property\">namespace <\/em>//g" < $(BUILDDIR)/html/development/reference/cpp/cpp_general.html > $(BUILDDIR)/html/development/reference/cpp/cpp_general.html.tmp
+ @mv $(BUILDDIR)/html/development/reference/cpp/cpp_general.html.tmp $(BUILDDIR)/html/development/reference/cpp/cpp_general.html
+ @cp -r ../schemas $(BUILDDIR)/html/schemas
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
-
diff --git a/docs/source/apps/cct.rst b/docs/source/apps/cct.rst
index 1d2aef20..b8504b8d 100644
--- a/docs/source/apps/cct.rst
+++ b/docs/source/apps/cct.rst
@@ -15,6 +15,42 @@ Synopsis
**cct** [**-cIostvz** [args]] *+opt[=arg]* ... file ...
+or
+
+ **cct** [**-cIostvz** [args]] {object_definition} file ...
+
+Where {object_definition} is one of the possibilities accepted
+by :c:func:`proj_create`, provided it expresses a coordinate operation
+
+ - a proj-string,
+ - a WKT string,
+ - an object code (like "EPSG:1671" "urn:ogc:def:coordinateOperation:EPSG::1671"),
+ - an object name. e.g "ITRF2014 to ETRF2014 (1)". In that case as
+ uniqueness is not guaranteed, heuristics are applied to determine the appropriate best match.
+ - a OGC URN combining references for concatenated operations
+ (e.g. "urn:ogc:def:coordinateOperation,coordinateOperation:EPSG::3895,coordinateOperation:EPSG::1618")
+ - a PROJJSON string. The jsonschema is at https://proj.org/schemas/v0.2/projjson.schema.json
+
+ .. versionadded:: 8.0.0
+
+ .. note::
+
+ Before version 8.0.0 only proj-strings could be used to instantiate
+ operations in :program:`cct`.
+
+
+or
+
+ **cct** [**-cIostvz** [args]] {object_reference} file ...
+
+where {object_reference} is a filename preceded by the '@' character. The
+file referenced by the {object_reference} must contain a valid
+{object_definition}.
+
+ .. versionadded:: 8.0.0
+
+
+
Description
***********
@@ -158,6 +194,20 @@ Should give results comparable to the classic :program:`proj` command
$ echo 12 56 100 2018.0 auxiliary data | cct +proj=merc
1335833.8895 7522963.2411 100.0000 2018.0000 auxiliary data
+7. Coordinate operation referenced through its code
+
+.. code-block:: console
+
+ $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct EPSG:8366
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
+
+8. Coordinate operation referenced through its name
+
+.. code-block:: console
+
+ $ echo 3541657.3778 948984.2343 5201383.5231 2020.5 | cct "ITRF2014 to ETRF2014 (1)"
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
+
Background
**********
diff --git a/docs/source/apps/cs2cs.rst b/docs/source/apps/cs2cs.rst
index e214a5c0..7df8890f 100644
--- a/docs/source/apps/cs2cs.rst
+++ b/docs/source/apps/cs2cs.rst
@@ -11,11 +11,11 @@ cs2cs
Synopsis
********
- **cs2cs** [**-eEfIlrstvwW** [args]] [*+opt[=arg]* ...] [+to *+opt[=arg]* ...] file ...
-
-or
-
- **cs2cs** [**-eEfIlrstvwW** [args]] {source_crs} {target_crs} file ...
+ | **cs2cs** [**-eEfIlrstvwW** [args]]
+ | [[--area <name_or_code>] | [--bbox <west_long,south_lat,east_long,north_lat>]]
+ | [--authority <name>]
+ | ([*+opt[=arg]* ...] [+to *+opt[=arg]* ...] | {source_crs} {target_crs})
+ | file ...
where {source_crs} or {target_crs} is one of the possibilities accepted
by :c:func:`proj_create`, provided it expresses a CRS
@@ -144,6 +144,42 @@ The following control parameters can appear in any order:
Causes a listing of cartographic control parameters tested for and used by
the program to be printed prior to input data.
+.. option:: --area <name_or_code>
+
+ .. versionadded:: 8.0.0
+
+ Specify an area of interest to restrict the results when researching
+ coordinate operations between 2 CRS. The area of interest can be specified either
+ as a name (e.g "Denmark - onshore") or a AUTHORITY:CODE (EPSG:3237)
+
+ This option is mutually exclusive with :option:`--bbox`.
+
+.. option:: --bbox <west_long,south_lat,east_long,north_lat>
+
+ .. versionadded:: 8.0.0
+
+ Specify an area of interest to restrict the results when researching
+ coordinate operations between 2 CRS. The area of interest is specified as a
+ bounding box with geographic coordinates, expressed in degrees in a
+ unspecified geographic CRS.
+ `west_long` and `east_long` should be in the [-180,180] range, and
+ `south_lat` and `north_lat` in the [-90,90]. `west_long` is generally lower than
+ `east_long`, except in the case where the area of interest crosses the antimeridian.
+
+.. option:: --authority <name>
+
+ .. versionadded:: 8.0.0
+
+ This option can be used to restrict the authority of coordinate operations
+ looked up in the database. When not specified, coordinate
+ operations from any authority will be searched, with the restrictions set
+ in the ``authority_to_authority_preference`` database table related to the authority
+ of the source/target CRS themselves.
+ If authority is set to ``any``, then coordinate operations from any authority will be searched
+ If authority is a non-empty string different of ``any``, then coordinate operations
+ will be searched only in that authority namespace (e.g ``EPSG``).
+
+ This option is mutually exclusive with :option:`--bbox`.
.. only:: man
diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst
index 05184ef9..803c0a65 100644
--- a/docs/source/apps/projinfo.rst
+++ b/docs/source/apps/projinfo.rst
@@ -16,13 +16,14 @@ Synopsis
********
| **projinfo**
- | [-o formats] [-k crs|operation|datum|ellipsoid] [--summary] [-q]
+ | [-o formats] [-k crs|operation|datum|ensemble|ellipsoid] [--summary] [-q]
| [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]
| [--spatial-test contains|intersects]
| [--crs-extent-use none|both|intersection|smallest]
| [--grid-check none|discard_missing|sort|known_available]
| [--pivot-crs always|if_no_direct_transformation|never|{auth:code[,auth:code]*}]
| [--show-superseded] [--hide-ballpark]
+ | [--allow-ellipsoidal-height-as-vertical-crs]
| [--boundcrs-to-wgs84]
| [--main-db-path path] [--aux-db-path path]*
| [--identify] [--3d]
@@ -86,7 +87,7 @@ The following control parameters can appear in any order:
.. note:: Before PROJ 6.3.0, WKT1:GDAL was implicitly calling --boundcrs-to-wgs84.
This is no longer the case.
-.. option:: -k crs|operation|datum|ellipsoid
+.. option:: -k crs|operation|datum|ensemble|ellipsoid
When used to query a single object with a AUTHORITY:CODE, determines the (k)ind of the object
in case there are CRS, coordinate operations or ellipsoids with the same CODE.
@@ -212,6 +213,15 @@ The following control parameters can appear in any order:
.. note:: only used for coordinate operation computation
+.. option:: --allow-ellipsoidal-height-as-vertical-crs
+
+ .. versionadded:: 8.0
+
+ Allow to export a geographic or projected 3D CRS as a compound CRS whose
+ vertical CRS represents the ellipsoidal height.
+
+ .. note:: only used for CRS, and with WKT1:GDAL output format
+
.. option:: --boundcrs-to-wgs84
When specified, this option researches a coordinate operation from the
diff --git a/docs/source/development/index.rst b/docs/source/development/index.rst
index 85c10c6d..f985279f 100644
--- a/docs/source/development/index.rst
+++ b/docs/source/development/index.rst
@@ -39,9 +39,8 @@ are maintained in a `separate git repository <https://github.com/OSGeo/proj-datu
.. attention::
The ``proj_api.h`` header and the functions related to it is
- considered deprecated from version 5.0.0 and onwards. The header will be
- removed from PROJ in version 7.0.0 scheduled for release March 1st
- 2020.
+ considered deprecated from version 5.0.0 and onwards. The header has been
+ removed in version 8.0.0 released March 1st 2021.
.. attention::
diff --git a/docs/source/development/reference/deprecated.rst b/docs/source/development/reference/deprecated.rst
deleted file mode 100644
index 19f43b41..00000000
--- a/docs/source/development/reference/deprecated.rst
+++ /dev/null
@@ -1,270 +0,0 @@
-.. _api:
-
-********************************************************************************
-Deprecated API
-********************************************************************************
-
-.. contents:: Contents
- :depth: 3
- :backlinks: none
-
-Introduction
-------------
-
-Procedure ``pj_init()`` selects and initializes a cartographic
-projection with its argument control parameters. ``argc`` is the number
-of elements in the array of control strings argv that each contain
-individual cartographic control keyword assignments (+ proj arguments).
-The list must contain at least the proj=projection and Earth’s radius or
-elliptical parameters. If the initialization of the projection is
-successful a valid address is returned otherwise a NULL value.
-
-The ``pj_init_plus()`` function operates similarly to ``pj_init()`` but
-takes a single string containing the definition, with each parameter
-prefixed with a plus sign. For example
-``+proj=utm +zone=11 +ellps=WGS84``.
-
-Once initialization is performed either forward or inverse projections
-can be performed with the returned value of ``pj_init()`` used as the
-argument proj. The argument structure projUV values u and v contain
-respective longitude and latitude or x and y. Latitude and longitude are
-in radians. If a projection operation fails, both elements of projUV are
-set to ``HUGE_VAL`` (defined in ``math.h``).
-
-Note: all projections have a forward mode, but some do not have an
-inverse projection. If the projection does not have an inverse the
-projPJ structure element inv will be ``NULL``.
-
-The ``pj_transform`` function may be used to transform points between
-the two provided coordinate systems. In addition to converting between
-cartographic projection coordinates and geographic coordinates, this
-function also takes care of datum shifts if possible between the source
-and destination coordinate system. Unlike ``pj_fwd()`` and ``pj_inv()``
-it is also allowable for the coordinate system definitions
-``(projPJ *)`` to be geographic coordinate systems (defined as
-``+proj=latlong``).
-The x, y and z arrays contain the input values of the points, and are replaced with the output values.
-The function returns zero on success, or the error number (also in ``pj_errno``)
-on failure.
-
-Memory associated with the projection may be freed with ``pj_free()``.
-
-Example
--------
-
-The following program reads latitude and longitude values in decimal
-degrees, performs Mercator projection with a Clarke 1866 ellipsoid and a
-33° latitude of true scale and prints the projected cartesian values in
-meters:
-
-.. code::
-
- #include <proj_api.h>
-
- main(int argc, char **argv) {
- projPJ pj_merc, pj_latlong;
- double x, y;
-
- if (!(pj_merc = pj_init_plus("+proj=merc +ellps=clrk66 +lat_ts=33")) )
- exit(1);
- if (!(pj_latlong = pj_init_plus("+proj=latlong +ellps=clrk66")) )
- exit(1);
- while (scanf("%lf %lf", &x, &y) == 2) {
- x *= DEG_TO_RAD;
- y *= DEG_TO_RAD;
- p = pj_transform(pj_latlong, pj_merc, 1, 1, &x, &y, NULL );
- printf("%.2f\t%.2f\n", x, y);
- }
- exit(0);
- }
-
-
-For this program, an input of ``-16 20.25`` would give a result of
-``-1495284.21 1920596.79``.
-
-API Functions
--------------
-
-pj_transform
-============
-
-::
-
- int pj_transform( projPJ srcdefn,
- projPJ dstdefn,
- long point_count,
- int point_offset,
- double *x,
- double *y,
- double *z );
-
-
-Transform the x/y/z points from the source coordinate system to the
-destination coordinate system.
-
-``srcdefn``: source (input) coordinate system.
-
-``dstdefn``: destination (output) coordinate system.
-
-``point_count``: the number of points to be processed (the size of the
-x/y/z arrays).
-
-``point_offset``: the step size from value to value (measured in
-doubles) within the x/y/z arrays - normally 1 for a packed array. May be
-used to operate on xyz interleaved point arrays.
-
-``x``/``y``/``z``: The array of X, Y and Z coordinate values passed as
-input, and modified in place for output. The Z may optionally be NULL.
-
-``return``: The return is zero on success, or a PROJ.4 error code.
-
-The ``pj_transform()`` function transforms the passed in list of points
-from the source coordinate system to the destination coordinate system.
-Note that geographic locations need to be passed in radians, not decimal
-degrees, and will be returned similarly. The ``z`` array may be passed
-as NULL if Z values are not available.
-
-If there is an overall failure, an error code will be returned from the
-function. If individual points fail to transform - for instance due to
-being over the horizon - then those x/y/z values will be set to
-``HUGE_VAL`` on return. Input values that are ``HUGE_VAL`` will not be
-transformed.
-
-
-pj_init_plus
-============
-
-::
-
- projPJ pj_init_plus(const char *definition);
-
-This function converts a string representation of a coordinate system
-definition into a projPJ object suitable for use with other API
-functions. On failure the function will return NULL and set pj_errno.
-The definition should be of the general form
-``+proj=tmerc +lon_0 +datum=WGS84``. Refer to PROJ.4 documentation and
-the :ref:`transformation` notes for additional detail.
-
-Coordinate system objects allocated with ``pj_init_plus()`` should be
-deallocated with ``pj_free()``.
-
-
-pj_free
-=======
-
-::
-
- void pj_free( projPJ pj );
-
-Frees all resources associated with pj.
-
-
-pj_is_latlong
-=============
-
-::
-
- int pj_is_latlong( projPJ pj );
-
-Returns TRUE if the passed coordinate system is geographic
-(``proj=latlong``).
-
-
-pj_is_geocent
-=============
-
-::
-
- int pj_is_geocent( projPJ pj );``
-
-Returns TRUE if the coordinate system is geocentric (``proj=geocent``).
-
-pj_get_def
-==========
-
-::
-
- char *pj_get_def( projPJ pj, int options);``
-
-Returns the PROJ.4 initialization string suitable for use with
-``pj_init_plus()`` that would produce this coordinate system, but with
-the definition expanded as much as possible (for instance ``+init=`` and
-``+datum=`` definitions).
-
-pj_latlong_from_proj
-====================
-
-::
-
- projPJ pj_latlong_from_proj( projPJ pj_in );``
-
-Returns a new coordinate system definition which is the geographic
-coordinate (lat/long) system underlying ``pj_in``.
-
-pj_set_finder
-==============
-
-::
-
- void pj_set_finder( const char *(*new_finder)(const char *) );``
-
-Install a custom function for finding init and grid shift files.
-
-pj_set_searchpath
-=================
-
-::
-
- void pj_set_searchpath ( int count, const char **path );``
-
-Set a list of directories to search for init and grid shift files.
-
-
-pj_deallocate_grids
-===================
-
-::
-
- void pj_deallocate_grids( void );``
-
-Frees all resources associated with loaded and cached datum shift grids.
-
-
-pj_strerrno
-===========
-
-::
-
- char *pj_strerrno( int );``
-
-Returns the error text associated with the passed in error code.
-
-pj_get_errno_ref
-================
-
-::
-
- int *pj_get_errno_ref( void );``
-
-Returns a pointer to the global pj\_errno error variable.
-
-pj_get_release
-==============
-
-::
-
- const char *pj_get_release( void );``
-
-Returns an internal string describing the release version.
-
-Obsolete Functions
-~~~~~~~~~~~~~~~~~~
-
-``XY pj_fwd( LP lp, PJ *P );``
-
-``LP pj_inv( XY xy, PJ *P );``
-
-``projPJ pj_init(int argc, char **argv);``
-
-.. _more info: pj_transform
-
diff --git a/docs/source/development/reference/functions.rst b/docs/source/development/reference/functions.rst
index cc29743c..b37eacdd 100644
--- a/docs/source/development/reference/functions.rst
+++ b/docs/source/development/reference/functions.rst
@@ -182,7 +182,19 @@ paragraph for more details.
This is the same as :c:func:`proj_create_crs_to_crs` except that the source and
target CRS are passed as PJ* objects which must of the CRS variety.
- :param `options`: should be set to NULL currently.
+ :param `options`: a list of NUL terminated options, or NULL.
+
+ The list of supported options is:
+
+ - AUTHORITY=name: to restrict the authority of coordinate operations
+ looked up in the database. When not specified, coordinate
+ ``operations from any authority`` will be searched, with the restrictions set
+ in the authority_to_authority_preference database table related to the authority
+ of the source/target CRS themselves.
+ If authority is set to "any", then coordinate operations from any authority will be searched
+ If authority is a non-empty string different of ``any``, then coordinate operations
+ will be searched only in that authority namespace (e.g ``EPSG``).
+
.. doxygenfunction:: proj_normalize_for_visualization
:project: doxygen_api
@@ -352,7 +364,7 @@ Coordinate transformation
-.. c:function:: size_t proj_trans_array(PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord)
+.. c:function:: int proj_trans_array(PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord)
Batch transform an array of :c:type:`PJ_COORD`.
@@ -362,7 +374,7 @@ Coordinate transformation
:type `direction`: PJ_DIRECTION
:param n: Number of coordinates in :c:data:`coord`
:type n: `size_t`
- :returns: :c:type:`size_t` 0 if all observations are transformed without error, otherwise returns error number
+ :returns: `int` 0 if all observations are transformed without error, otherwise returns error number
Error reporting
diff --git a/docs/source/development/reference/index.rst b/docs/source/development/reference/index.rst
index 1d39b1d0..caa893c3 100644
--- a/docs/source/development/reference/index.rst
+++ b/docs/source/development/reference/index.rst
@@ -10,4 +10,3 @@ Reference
datatypes
functions
cpp/index.rst
- deprecated
diff --git a/docs/source/news.rst b/docs/source/news.rst
index 4275dd11..65c027f1 100644
--- a/docs/source/news.rst
+++ b/docs/source/news.rst
@@ -13,72 +13,72 @@ Updates
+ **Command line tools**
* Add multi-line PROJ string export capability, and use it by default in
- :program:`projinfo` (unless ``--single-line`` is specified) (`#2381 <https://github.com/OSGeo/issues/2381>`_)
+ :program:`projinfo` (unless ``--single-line`` is specified) (`#2381 <https://github.com/OSGeo/PROJ/issues/2381>`_)
+ **Coordinate operations**
* :ref:`col_urban` projection, implementing a EPSG projection method
- used by a number of projected CRS in Colombia (`#2395 <https://github.com/OSGeo/issues/2395>`_)
+ used by a number of projected CRS in Colombia (`#2395 <https://github.com/OSGeo/PROJ/issues/2395>`_)
- * :ref:`tinshift` for triangulation-based transformations (`#2344 <https://github.com/OSGeo/issues/2344>`_)
+ * :ref:`tinshift` for triangulation-based transformations (`#2344 <https://github.com/OSGeo/PROJ/issues/2344>`_)
- * Added ellipsoidal formulation of :ref:`ortho` (`#2361 <https://github.com/OSGeo/issues/2361>`_)
+ * Added ellipsoidal formulation of :ref:`ortho` (`#2361 <https://github.com/OSGeo/PROJ/issues/2361>`_)
+ **Database**
* Update to EPSG 10.003 and make code base robust to dealing with
- WKT CRS with DatumEnsemble (`#2370 <https://github.com/OSGeo/issues/2370>`_)
+ WKT CRS with DatumEnsemble (`#2370 <https://github.com/OSGeo/PROJ/issues/2370>`_)
- * Added Finland tinshift operations (`#2392 <https://github.com/OSGeo/issues/2392>`_)
+ * Added Finland tinshift operations (`#2392 <https://github.com/OSGeo/PROJ/issues/2392>`_)
* Added transformation from JGD2011 Geographic 3D to JGD2011
- height using GSIGEO2011 (`#2393 <https://github.com/OSGeo/issues/2393>`_)
+ height using GSIGEO2011 (`#2393 <https://github.com/OSGeo/PROJ/issues/2393>`_)
* Improve CompoundCRS identification and name morphing in VerticalCRS
- with ESRI WKT1 (`#2386 <https://github.com/OSGeo/issues/2386>`_)
+ with ESRI WKT1 (`#2386 <https://github.com/OSGeo/PROJ/issues/2386>`_)
* Added OGC:CRS27 and OGC:CRS83 CRS entries for NAD27 and NAD83
- in longitude, latitude order (`#2350 <https://github.com/OSGeo/issues/2350>`_)
+ in longitude, latitude order (`#2350 <https://github.com/OSGeo/PROJ/issues/2350>`_)
+ **API**
- * Added temporal, engineering, and parametric datum :c:type:`PJ_TYPE` enumerations (`#2274 <https://github.com/OSGeo/issues/2274>`_)
+ * Added temporal, engineering, and parametric datum :c:type:`PJ_TYPE` enumerations (`#2274 <https://github.com/OSGeo/PROJ/issues/2274>`_)
* Various improvements to context handling (#2329, #2331)
* :c:func:`proj_create_vertical_crs_ex()`: add a ``ACCURACY`` option to provide
an explicit accuracy, or derive it from the grid name if it is
- known (`#2342 <https://github.com/OSGeo/issues/2342>`_)
+ known (`#2342 <https://github.com/OSGeo/PROJ/issues/2342>`_)
* :c:func:`proj_crs_create_bound_crs_to_WGS84()`: make it work on
verticalCRS/compoundCRS such as EPSG:4326+5773 and
- EPSG:4326+3855 (`#2365 <https://github.com/OSGeo/issues/2365>`_)
+ EPSG:4326+3855 (`#2365 <https://github.com/OSGeo/PROJ/issues/2365>`_)
- * :cpp:func:`promoteTo3D()`: add a remark with the original CRS identifier (`#2369 <https://github.com/OSGeo/issues/2369>`_)
+ * :cpp:func:`promoteTo3D()`: add a remark with the original CRS identifier (`#2369 <https://github.com/OSGeo/PROJ/issues/2369>`_)
- * Added :c:func:`proj_context_clone` (`#2383 <https://github.com/OSGeo/issues/2383>`_)
+ * Added :c:func:`proj_context_clone` (`#2383 <https://github.com/OSGeo/PROJ/issues/2383>`_)
Bug fixes
---------
-* Avoid core dumps when copying contexts in certain scenarios (`#2324 <https://github.com/OSGeo/issues/2324>`_)
+* Avoid core dumps when copying contexts in certain scenarios (`#2324 <https://github.com/OSGeo/PROJ/issues/2324>`_)
* :c:func:`proj_trans()`: reset errno before attemptying a retry with a new
- coordinate operation (`#2353 <https://github.com/OSGeo/issues/2353>`_)
+ coordinate operation (`#2353 <https://github.com/OSGeo/PROJ/issues/2353>`_)
* PROJJSON schema corrected to allow prime meridians values with
- explicitly stating a unit (degrees assumed) (`#2354 <https://github.com/OSGeo/issues/2354>`_)
+ explicitly stating a unit (degrees assumed) (`#2354 <https://github.com/OSGeo/PROJ/issues/2354>`_)
* Adjust :cpp:func:`createBoundCRSToWGS84IfPossible()` and operation filtering
- (for POSGAR 2007 to WGS84 issues) (`#2357 <https://github.com/OSGeo/issues/2357>`_)
+ (for POSGAR 2007 to WGS84 issues) (`#2357 <https://github.com/OSGeo/PROJ/issues/2357>`_)
-* :cpp:func:`createOperations()`: several fixes affecting NAD83 -> NAD83(2011) (`#2364 <https://github.com/OSGeo/issues/2364>`_)
+* :cpp:func:`createOperations()`: several fixes affecting NAD83 -> NAD83(2011) (`#2364 <https://github.com/OSGeo/PROJ/issues/2364>`_)
* WKT2:2019 import/export: handle DATUM (at top level object) with PRIMEM
-* WKT1_ESRI: fix import and export of CompoundCRS (`#2389 <https://github.com/OSGeo/issues/2389>`_)
+* WKT1_ESRI: fix import and export of CompoundCRS (`#2389 <https://github.com/OSGeo/PROJ/issues/2389>`_)
7.1.1 Release Notes
@@ -89,36 +89,36 @@ Bug fixes
Updates
-------
-* Added various Brazillian grids to the database (`#2277 <https://github.com/OSGeo/issues/2277>`_)
+* Added various Brazillian grids to the database (`#2277 <https://github.com/OSGeo/PROJ/issues/2277>`_)
-* Added geoid file for Canary Islands to the database (`#2312 <https://github.com/OSGeo/issues/2312>`_)
+* Added geoid file for Canary Islands to the database (`#2312 <https://github.com/OSGeo/PROJ/issues/2312>`_)
-* Updated EPSG database to version 9.8.15 (`#2310 <https://github.com/OSGeo/issues/2310>`_)
+* Updated EPSG database to version 9.8.15 (`#2310 <https://github.com/OSGeo/PROJ/issues/2310>`_)
Bug fixes
---------
* WKT parser: do not raise warning when parsing a WKT2:2015 TIMECRS
- whose TIMEUNIT is at the CS level, and not inside (`#2281 <https://github.com/OSGeo/issues/2281>`_)
+ whose TIMEUNIT is at the CS level, and not inside (`#2281 <https://github.com/OSGeo/PROJ/issues/2281>`_)
* Parse '+proj=something_not_latlong +vunits=' without +geoidgrids as a
- Projected3D CRS and not a compound CRS with a unknown datum (`#2289 <https://github.com/OSGeo/issues/2289>`_)
+ Projected3D CRS and not a compound CRS with a unknown datum (`#2289 <https://github.com/OSGeo/PROJ/issues/2289>`_)
-* C API: Avoid crashing due to missing SANITIZE_CTX() in entry points (`#2293 <https://github.com/OSGeo/issues/2293>`_)
+* C API: Avoid crashing due to missing SANITIZE_CTX() in entry points (`#2293 <https://github.com/OSGeo/PROJ/issues/2293>`_)
-* CMake build: Check "target_clones" before use (`#2297 <https://github.com/OSGeo/issues/2297>`_)
+* CMake build: Check "target_clones" before use (`#2297 <https://github.com/OSGeo/PROJ/issues/2297>`_)
-* PROJ string export of +proj=krovak +czech: make sure we export +czech… (`#2301 <https://github.com/OSGeo/issues/2301>`_)
+* PROJ string export of +proj=krovak +czech: make sure we export +czech… (`#2301 <https://github.com/OSGeo/PROJ/issues/2301>`_)
-* Helmert 2D: do not require a useless +convention= parameter (`#2305 <https://github.com/OSGeo/issues/2305>`_)
+* Helmert 2D: do not require a useless +convention= parameter (`#2305 <https://github.com/OSGeo/PROJ/issues/2305>`_)
-* Fix a few spelling errors ("vgridshit" vs. "vgridshift") (`#2307 <https://github.com/OSGeo/issues/2307>`_)
+* Fix a few spelling errors ("vgridshit" vs. "vgridshift") (`#2307 <https://github.com/OSGeo/PROJ/issues/2307>`_)
-* Fix ability to identify EPSG:2154 as a candidate for 'RGF93_Lambert_93' (`#2316 <https://github.com/OSGeo/issues/2316>`_)
+* Fix ability to identify EPSG:2154 as a candidate for 'RGF93_Lambert_93' (`#2316 <https://github.com/OSGeo/PROJ/issues/2316>`_)
-* WKT importer: tune for Oracle WKT and 'Lambert Conformal Conic' (`#2322 <https://github.com/OSGeo/issues/2322>`_)
+* WKT importer: tune for Oracle WKT and 'Lambert Conformal Conic' (`#2322 <https://github.com/OSGeo/PROJ/issues/2322>`_)
-* Revert compiler generated Fused Multiply Addition optimized routines (`#2328 <https://github.com/OSGeo/issues/2328>`_)
+* Revert compiler generated Fused Multiply Addition optimized routines (`#2328 <https://github.com/OSGeo/PROJ/issues/2328>`_)
@@ -135,7 +135,7 @@ Updates
+ **New projections**
- * Add square conformal projections from libproject (`#2148 <https://github.com/OSGeo/issues/2148>`_):
+ * Add square conformal projections from libproject (`#2148 <https://github.com/OSGeo/PROJ/issues/2148>`_):
- :ref:`adams_hemi`
@@ -148,117 +148,117 @@ Updates
- :ref:`peirce_q`
* Adams Square II: map ESRI WKT to PROJ string, and implement iterative
- inverse method (`#2157 <https://github.com/OSGeo/issues/2157>`_)
+ inverse method (`#2157 <https://github.com/OSGeo/PROJ/issues/2157>`_)
- * Added :ref:`igh_o` projection (`#2226 <https://github.com/OSGeo/issues/2226>`_)
+ * Added :ref:`igh_o` projection (`#2226 <https://github.com/OSGeo/PROJ/issues/2226>`_)
- * Add :ref:`wink2` inverse by generic inversion of forward method (`#2243 <https://github.com/OSGeo/issues/2243>`_)
+ * Add :ref:`wink2` inverse by generic inversion of forward method (`#2243 <https://github.com/OSGeo/PROJ/issues/2243>`_)
+ **Database**
* Update to EPSG 9.8.12, ESRI 10.8.1 and import scope and remarks for
- conversion (`#2238 <https://github.com/OSGeo/issues/2238>`_) (#2267)
+ conversion (`#2238 <https://github.com/OSGeo/PROJ/issues/2238>`_) (#2267)
- * Map the Behrman projection to ``cae`` when converting ESRI CRSes (`#1986 <https://github.com/OSGeo/issues/1986>`_)
+ * Map the Behrman projection to ``cae`` when converting ESRI CRSes (`#1986 <https://github.com/OSGeo/PROJ/issues/1986>`_)
- * Support conversion of Flat_Polar_Quartic projection method (`#1987 <https://github.com/OSGeo/issues/1987>`_)
+ * Support conversion of Flat_Polar_Quartic projection method (`#1987 <https://github.com/OSGeo/PROJ/issues/1987>`_)
* Register 4 new Austrian height grids (see https://github.com/OSGeo/PROJ-data/pull/13)
- and handle 'Vertical Offset by Grid Interpolation (BEV AT)' method (`#1989 <https://github.com/OSGeo/issues/1989>`_)
+ and handle 'Vertical Offset by Grid Interpolation (BEV AT)' method (`#1989 <https://github.com/OSGeo/PROJ/issues/1989>`_)
* Add ESRI projection method mappings for Mercator_Variant_A, Mercator_Variant_B
- and Transverse_Cylindrical_Equal_Area and various grid mappings (`#2020 <https://github.com/OSGeo/issues/2020>`_) (#2195)
+ and Transverse_Cylindrical_Equal_Area and various grid mappings (`#2020 <https://github.com/OSGeo/PROJ/issues/2020>`_) (#2195)
- * Map ESRI Transverse_Mercator_Complex to Transverse Mercator (`#2040 <https://github.com/OSGeo/issues/2040>`_)
+ * Map ESRI Transverse_Mercator_Complex to Transverse Mercator (`#2040 <https://github.com/OSGeo/PROJ/issues/2040>`_)
- * Register grids for New Caledonia (see https://github.com/OSGeo/PROJ-data/pull/16) (`#2051 <https://github.com/OSGeo/issues/2051>`_) (#2239)
+ * Register grids for New Caledonia (see https://github.com/OSGeo/PROJ-data/pull/16) (`#2051 <https://github.com/OSGeo/PROJ/issues/2051>`_) (#2239)
- * Register NZGD2000 -> ITRF96 transformation for NZGD2000 database (`#2248 <https://github.com/OSGeo/issues/2248>`_)
+ * Register NZGD2000 -> ITRF96 transformation for NZGD2000 database (`#2248 <https://github.com/OSGeo/PROJ/issues/2248>`_)
* Register geoid file for UK added
- (see https://github.com/OSGeo//PROJ-data/pull/25() (`#2250 <https://github.com/OSGeo/issues/2250>`_)
+ (see https://github.com/OSGeo//PROJ-data/pull/25() (`#2250 <https://github.com/OSGeo/PROJ/issues/2250>`_)
- * Register Slovakian geoid transformations with needed code changes (`#2259 <https://github.com/OSGeo/issues/2259>`_)
+ * Register Slovakian geoid transformations with needed code changes (`#2259 <https://github.com/OSGeo/PROJ/issues/2259>`_)
- * Register Spanish SPED2ETV2 grid for ED50->ETRS89 (`#2261 <https://github.com/OSGeo/issues/2261>`_)
+ * Register Spanish SPED2ETV2 grid for ED50->ETRS89 (`#2261 <https://github.com/OSGeo/PROJ/issues/2261>`_)
+ **API**
- * Add API function :c:func:`proj_get_units_from_database()` (`#2065 <https://github.com/OSGeo/issues/2065>`_)
+ * Add API function :c:func:`proj_get_units_from_database()` (`#2065 <https://github.com/OSGeo/PROJ/issues/2065>`_)
- * Add API function :c:func:`proj_get_suggested_operation()` (`#2068 <https://github.com/OSGeo/issues/2068>`_)
+ * Add API function :c:func:`proj_get_suggested_operation()` (`#2068 <https://github.com/OSGeo/PROJ/issues/2068>`_)
- * Add API functions :c:func:`proj_degree_input()` and :c:func:`proj_degree_output()` (`#2144 <https://github.com/OSGeo/issues/2144>`_)
+ * Add API functions :c:func:`proj_degree_input()` and :c:func:`proj_degree_output()` (`#2144 <https://github.com/OSGeo/PROJ/issues/2144>`_)
* Moved :c:func:`proj_context_get_url_endpoint()` & :c:func:`proj_context_get_user_writable_directory()`
- from ``proj_experimental.h`` to ``proj.h`` (`#2162 <https://github.com/OSGeo/issues/2162>`_)
+ from ``proj_experimental.h`` to ``proj.h`` (`#2162 <https://github.com/OSGeo/PROJ/issues/2162>`_)
* :c:func:`createFromUserInput()`: allow compound CRS with the 2 parts given by names,
- e.g. 'WGS 84 + EGM96 height' (`#2126 <https://github.com/OSGeo/issues/2126>`_)
+ e.g. 'WGS 84 + EGM96 height' (`#2126 <https://github.com/OSGeo/PROJ/issues/2126>`_)
* :c:func:`createOperations()`: when converting CompoundCRS<-->Geographic3DCrs, do not
use discard change of ellipsoidal height if a Helmert transformation is
- involved (`#2227 <https://github.com/OSGeo/issues/2227>`_)
+ involved (`#2227 <https://github.com/OSGeo/PROJ/issues/2227>`_)
+ **Optimizations**
- * ``tmerc/utm``: add a +algo=auto/evenden_snyder/poder_engsager parameter (`#2030 <https://github.com/OSGeo/issues/2030>`_)
+ * ``tmerc/utm``: add a +algo=auto/evenden_snyder/poder_engsager parameter (`#2030 <https://github.com/OSGeo/PROJ/issues/2030>`_)
- * Extended ``tmerc`` (Poder/Engsager): speed optimizations (`#2036 <https://github.com/OSGeo/issues/2036>`_)
+ * Extended ``tmerc`` (Poder/Engsager): speed optimizations (`#2036 <https://github.com/OSGeo/PROJ/issues/2036>`_)
- * Approximate ``tmerc`` (Snyder): speed optimizations (`#2039 <https://github.com/OSGeo/issues/2039>`_)
+ * Approximate ``tmerc`` (Snyder): speed optimizations (`#2039 <https://github.com/OSGeo/PROJ/issues/2039>`_)
- * :c:func:`pj_phi2()`: speed-up computation (and thus inverse ellipsoidal Mercator and LCC) (`#2052 <https://github.com/OSGeo/issues/2052>`_)
+ * :c:func:`pj_phi2()`: speed-up computation (and thus inverse ellipsoidal Mercator and LCC) (`#2052 <https://github.com/OSGeo/PROJ/issues/2052>`_)
- * Inverse ``cart``: speed-up computation by 33% (`#2145 <https://github.com/OSGeo/issues/2145>`_)
+ * Inverse ``cart``: speed-up computation by 33% (`#2145 <https://github.com/OSGeo/PROJ/issues/2145>`_)
- * Extended ``tmerc``: speed-up forward path by ~5% (`#2147 <https://github.com/OSGeo/issues/2147>`_)
+ * Extended ``tmerc``: speed-up forward path by ~5% (`#2147 <https://github.com/OSGeo/PROJ/issues/2147>`_)
+ **Various**
- * Follow PDAL's CMake RPATH strategy (`#2009 <https://github.com/OSGeo/issues/2009>`_)
+ * Follow PDAL's CMake RPATH strategy (`#2009 <https://github.com/OSGeo/PROJ/issues/2009>`_)
- * WKT import/export: add support for WKT1_ESRI VERTCS synta (`#2024 <https://github.com/OSGeo/issues/2024>`_)
+ * WKT import/export: add support for WKT1_ESRI VERTCS synta (`#2024 <https://github.com/OSGeo/PROJ/issues/2024>`_)
- * :program:`projinfo`: add a ``--hide-ballpark`` option (`#2127 <https://github.com/OSGeo/issues/2127>`_)
+ * :program:`projinfo`: add a ``--hide-ballpark`` option (`#2127 <https://github.com/OSGeo/PROJ/issues/2127>`_)
- * :program:`gie`: implement a strict mode with ``<gie-strict> </gie-strict>`` (`#2168 <https://github.com/OSGeo/issues/2168>`_)
+ * :program:`gie`: implement a strict mode with ``<gie-strict> </gie-strict>`` (`#2168 <https://github.com/OSGeo/PROJ/issues/2168>`_)
- * Allow importing WKT1 COMPD_CS with a VERT_DATUM[Ellipsoid,2002] (`#2229 <https://github.com/OSGeo/issues/2229>`_)
+ * Allow importing WKT1 COMPD_CS with a VERT_DATUM[Ellipsoid,2002] (`#2229 <https://github.com/OSGeo/PROJ/issues/2229>`_)
- * Add runtime checking that sqlite3 is >= 3.11 (`#2235 <https://github.com/OSGeo/issues/2235>`_)
+ * Add runtime checking that sqlite3 is >= 3.11 (`#2235 <https://github.com/OSGeo/PROJ/issues/2235>`_)
Bug fixes
---------
* :cpp:func:`createOperations()`: do not remove ballpark transformation if there are only grid
- based operations, even if they cover the whole area of use (`#2155 <https://github.com/OSGeo/issues/2155>`_)
+ based operations, even if they cover the whole area of use (`#2155 <https://github.com/OSGeo/PROJ/issues/2155>`_)
* :cpp:func:`createFromProjString()`: handle default parameters of '+krovak +type=crs', and
- handle ``+czech`` correctly (`#2200 <https://github.com/OSGeo/issues/2200>`_)
+ handle ``+czech`` correctly (`#2200 <https://github.com/OSGeo/PROJ/issues/2200>`_)
-* :cpp:func:`ProjectedCRS::identify()`: fix identification of EPSG:3059 (`#2215 <https://github.com/OSGeo/issues/2215>`_)
+* :cpp:func:`ProjectedCRS::identify()`: fix identification of EPSG:3059 (`#2215 <https://github.com/OSGeo/PROJ/issues/2215>`_)
-* Database: add a 'WGS84' alias for the EPSG:4326 CRS (`#2218 <https://github.com/OSGeo/issues/2218>`_)
+* Database: add a 'WGS84' alias for the EPSG:4326 CRS (`#2218 <https://github.com/OSGeo/PROJ/issues/2218>`_)
-* Fixes related to CompoundCRS and BoundCRS (`#2222 <https://github.com/OSGeo/issues/2222>`_)
+* Fixes related to CompoundCRS and BoundCRS (`#2222 <https://github.com/OSGeo/PROJ/issues/2222>`_)
-* Avoid 2 warnings about missing database indices (`#2223 <https://github.com/OSGeo/issues/2223>`_)
+* Avoid 2 warnings about missing database indices (`#2223 <https://github.com/OSGeo/PROJ/issues/2223>`_)
-* Make ``projinfo --3d --boundcrs-to-wgs84`` work better (`#2224 <https://github.com/OSGeo/issues/2224>`_)
+* Make ``projinfo --3d --boundcrs-to-wgs84`` work better (`#2224 <https://github.com/OSGeo/PROJ/issues/2224>`_)
* Many fixes regarding BoundCRS, CompoundCRS, Geographic3D CRS with
- non-metre units (`#2234 <https://github.com/OSGeo/issues/2234>`_)
+ non-metre units (`#2234 <https://github.com/OSGeo/PROJ/issues/2234>`_)
-* Fix identification of (one of the) ESRI WKT formulations of EPSG:3035 (`#2240 <https://github.com/OSGeo/issues/2240>`_)
+* Fix identification of (one of the) ESRI WKT formulations of EPSG:3035 (`#2240 <https://github.com/OSGeo/PROJ/issues/2240>`_)
-* Avoid using deprecated and removed Windows API function with Mingw32 (`#2246 <https://github.com/OSGeo/issues/2246>`_)
+* Avoid using deprecated and removed Windows API function with Mingw32 (`#2246 <https://github.com/OSGeo/PROJ/issues/2246>`_)
* :cpp:func:`normalizeForVisualization()`: make it switch axis for EPSG:5482
- (RSRGD2000 / RSPS2000) (`#2256 <https://github.com/OSGeo/issues/2256>`_)
+ (RSRGD2000 / RSPS2000) (`#2256 <https://github.com/OSGeo/PROJ/issues/2256>`_)
-* Fix access violation in :c:func:`proj_context_get_database_metadata()` (`#2260 <https://github.com/OSGeo/issues/2260>`_)
+* Fix access violation in :c:func:`proj_context_get_database_metadata()` (`#2260 <https://github.com/OSGeo/PROJ/issues/2260>`_)
7.0.1 Release Notes
diff --git a/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png
new file mode 100644
index 00000000..224ff738
--- /dev/null
+++ b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.png
Binary files differ
diff --git a/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg
new file mode 100644
index 00000000..c97ca181
--- /dev/null
+++ b/docs/source/operations/conversions/images/ECEF_ENU_Longitude_Latitude_relationships.svg
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="520"
+ height="500"
+ id="svg2"
+ xml:space="preserve"><defs
+ id="defs6"><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow2Mend"
+ style="overflow:visible"><path
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6,-0.6)"
+ id="path3759"
+ style="font-size:12px;fill:#0d6299;fill-rule:evenodd;stroke:#0d6299;stroke-width:0.625;stroke-linejoin:round" /></marker><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow1Mstart"
+ style="overflow:visible"><path
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ transform="matrix(0.4,0,0,0.4,4,0)"
+ id="path3738"
+ style="fill:#00b800;fill-rule:evenodd;stroke:#00b800;stroke-width:1pt;marker-start:none" /></marker><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow1Mend"
+ style="overflow:visible"><path
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ id="path3741"
+ style="fill:#00b800;fill-rule:evenodd;stroke:#00b800;stroke-width:1pt;marker-start:none" /></marker><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow2Mstart"
+ style="overflow:visible"><path
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(0.6,0.6)"
+ id="path3756"
+ style="font-size:12px;fill:#0d6299;fill-rule:evenodd;stroke:#0d6299;stroke-width:0.625;stroke-linejoin:round" /></marker><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow1Lstart"
+ style="overflow:visible"><path
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ transform="matrix(0.8,0,0,0.8,10,0)"
+ id="path3732"
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;marker-start:none" /></marker><marker
+ refX="0"
+ refY="0"
+ orient="auto"
+ id="Arrow1Lend"
+ style="overflow:visible"><path
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ id="path3735"
+ style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;marker-start:none" /></marker></defs><g
+ transform="matrix(1.25,0,0,-1.25,-136.61316,788.09803)"
+ id="g12"><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g18"
+ style="stroke:#808080;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 8;stroke-dashoffset:0"><path
+ d="m 283.32,265.39 1.08,0 0.96,0.36 1.08,0.48 0.96,0.72 0.96,0.84 0.96,1.08 1.08,1.32 0.96,1.44 0.96,1.68 0.96,1.8 0.96,2.04 0.84,2.28 0.96,2.4 0.96,2.64 0.84,2.76 0.84,2.88 0.84,3.12 0.84,3.24 0.84,3.48 0.84,3.48 0.72,3.84 0.72,3.84 0.72,4.08 0.72,4.08 0.72,4.32 0.6,4.44 0.6,4.56 0.6,4.68 0.6,4.8 0.6,4.93 0.48,5.03 0.48,5.16 0.48,5.16 0.36,5.28 0.36,5.4 0.36,5.4 0.36,5.52 0.24,5.52 0.24,5.64 0.24,5.64 0.24,5.76 0.12,5.76 0.12,5.76 0.12,5.76 0,5.76 0,5.88 0,5.76 0,5.76 -0.12,5.76 -0.12,5.88 -0.12,5.64 -0.24,5.77 -0.24,5.63 -0.24,5.64 -0.24,5.52 -0.36,5.52 -0.36,5.4 -0.36,5.4 -0.36,5.28 -0.48,5.16 -0.48,5.16 -0.48,5.04 -0.6,4.92 -0.6,4.8 -0.6,4.68 -0.6,4.56 -0.6,4.44 -0.72,4.32 -0.72,4.08 -0.72,4.08 -0.72,3.96 -0.72,3.72 -0.84,3.6 -0.84,3.36 -0.84,3.24 -0.84,3.12 -0.84,3 -0.84,2.76 -0.96,2.52 -0.96,2.4 -0.84,2.28 -0.96,2.04 -0.96,1.8 -0.96,1.68 -0.96,1.44 -1.08,1.32 -0.96,1.08 -0.96,0.84 -0.96,0.72 -1.08,0.49 -0.96,0.35 -1.08,0"
+ id="path20"
+ style="fill:none;stroke:#808080;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 8;stroke-dashoffset:0" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g22"
+ style="stroke:#808080;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 283.32,605.35 -0.96,0 -0.96,-0.35 -1.08,-0.49 -0.96,-0.72 -0.96,-0.84 -1.08,-1.08 -0.96,-1.32 -0.96,-1.44 -0.96,-1.68 -0.96,-1.8 -0.96,-2.04 -0.96,-2.28 -0.84,-2.4 -0.96,-2.52 -0.84,-2.76 -0.84,-3 -0.96,-3.12 -0.72,-3.24 -0.84,-3.36 -0.84,-3.6 -0.72,-3.72 -0.84,-3.96 -0.72,-4.08 -0.6,-4.08 -0.72,-4.32 -0.6,-4.44 -0.72,-4.56 -0.6,-4.68 -0.48,-4.8 -0.6,-4.92 -0.48,-5.04 -0.48,-5.16 -0.48,-5.16 -0.36,-5.28 -0.36,-5.4 -0.36,-5.4 -0.36,-5.52 -0.24,-5.52 -0.36,-5.64 -0.12,-5.63 -0.24,-5.77 -0.12,-5.64 -0.12,-5.88 -0.12,-5.76 0,-5.76 -0.12,-5.76 0.12,-5.88 0,-5.76 0.12,-5.76 0.12,-5.76 0.12,-5.76 0.24,-5.76 0.12,-5.64 0.36,-5.64 0.24,-5.52 0.36,-5.52 0.36,-5.4 0.36,-5.4 0.36,-5.28 0.48,-5.16 0.48,-5.16 0.48,-5.03 0.6,-4.93 0.48,-4.8 0.6,-4.68 0.72,-4.56 0.6,-4.44 0.72,-4.32 0.6,-4.08 0.72,-4.08 0.84,-3.84 0.72,-3.84 0.84,-3.48 0.84,-3.48 0.72,-3.24 0.96,-3.12 0.84,-2.88 0.84,-2.76 0.96,-2.64 0.84,-2.4 0.96,-2.28 0.96,-2.04 0.96,-1.8 0.96,-1.68 0.96,-1.44 0.96,-1.32 1.08,-1.08 0.96,-0.84 0.96,-0.72 1.08,-0.48 0.96,-0.36 0.96,0"
+ id="path24"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g26"
+ style="stroke:#808080;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 283.32,605.35 -8.88,-0.12 -8.88,-0.72 -8.76,-1.2 -8.76,-1.56 -8.64,-2.16 -8.52,-2.52 -8.4,-3 -8.28,-3.36 -8.04,-3.84 -7.8,-4.2 -7.56,-4.67 -7.32,-5.05 -7.08,-5.4 -6.84,-5.76 -6.36,-6.24 -6.24,-6.36 -5.76,-6.84 -5.4,-7.08 -5.04,-7.32 -4.68,-7.56 -4.2,-7.8 -3.84,-8.04 -3.36,-8.28 -3,-8.4 -2.52,-8.52 -2.16,-8.64 -1.56,-8.76 -1.2,-8.76 -0.72,-8.88 -0.12,-8.88 0.12,-9 0.72,-8.88 1.2,-8.76 1.56,-8.76 2.16,-8.64 2.52,-8.52 3,-8.4 3.36,-8.28 3.84,-8.04 4.2,-7.8 4.68,-7.56 5.04,-7.32 5.4,-7.08 5.76,-6.84 6.24,-6.36 6.36,-6.12 6.84,-5.88 7.08,-5.4 7.32,-5.04 7.56,-4.68 7.8,-4.2 8.04,-3.84 8.28,-3.36 8.4,-3 8.52,-2.52 8.64,-2.04 8.76,-1.68 8.76,-1.2 8.88,-0.6 8.88,-0.24"
+ id="path28"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g30"
+ style="stroke:#808080;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 453.36,435.43 0,0.96 -0.36,0.96 -0.48,1.08 -0.72,0.96 -0.84,0.96 -1.08,1.08 -1.32,0.96 -1.44,0.96 -1.68,0.96 -1.92,0.96 -2.04,0.96 -2.16,0.96 -2.52,0.84 -2.52,0.97 -2.76,0.83 -3,0.96 -3.12,0.84 -3.24,0.84 -3.48,0.84 -3.6,0.72 -3.72,0.84 -3.96,0.72 -3.96,0.72 -4.2,0.72 -4.32,0.6 -4.56,0.72 -4.56,0.6 -4.68,0.6 -4.8,0.6 -4.92,0.48 -5.04,0.48 -5.16,0.48 -5.16,0.48 -5.28,0.48 -5.4,0.36 -5.52,0.36 -5.52,0.24 -5.52,0.36 -5.64,0.24 -5.64,0.24 -5.76,0.12 -5.76,0.12 -5.76,0.12 -5.88,0.12 -5.76,0.12 -5.76,0 -5.88,-0.12 -5.76,0 -5.88,-0.12 -5.76,-0.12 -5.76,-0.12"
+ id="path32"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g46"
+ style="stroke:#ff9900;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 270.6,392.35 -0.24,3.48 -0.36,3.6 -0.24,3.6 -0.24,3.72 -0.24,3.72 -0.24,3.84 -0.12,3.96 -0.12,3.84 -0.12,3.96 0,3.96 -0.12,4.08 0,3.96 0.12,3.96 0,3.97 0.12,3.95"
+ id="path48"
+ style="fill:none;stroke:#ff9900;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><path
+ d="m 481.68,406.99 -198.36,0 -33.84,-34.44"
+ id="path16"
+ style="fill:none;stroke:#0d6299;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart);marker-end:url(#Arrow2Mend)" /><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g34"
+ style="stroke:#ff9900;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 363,358.51 -79.68,76.92"
+ id="path36"
+ style="fill:none;stroke:#ff9900;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g38"
+ style="stroke:#808080;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 453.36,435.43 -0.12,-3.96 -0.48,-3.96 -0.96,-3.96 -1.2,-3.84 -1.56,-3.84 -1.92,-3.84 -2.16,-3.84 -2.64,-3.72 -2.88,-3.6 -3.24,-3.6 -3.48,-3.48 -3.84,-3.48 -4.08,-3.24 -4.44,-3.24 -4.68,-3.12 -5.04,-3 -5.16,-2.88 -5.52,-2.88 -5.76,-2.64 -5.88,-2.4 -6.24,-2.4 -6.36,-2.28 -6.48,-2.04 -6.84,-1.92 -6.84,-1.68 -7.08,-1.68 -7.2,-1.44 -7.2,-1.2 -7.44,-1.08 -7.44,-0.96 -7.56,-0.72 -7.68,-0.6 -7.68,-0.36 -7.68,-0.24 -7.68,0 -7.68,0.12 -7.68,0.36 -7.68,0.48"
+ id="path40"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g42"
+ style="stroke:#ff9900;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 257.88,349.27 25.44,86.16"
+ id="path44"
+ style="fill:none;stroke:#ff9900;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g50"
+ style="stroke:#ff9900;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 274.92,406.63 4.44,-0.24 4.56,0 4.44,0.12 4.56,0.24 4.32,0.48 4.44,0.72 4.2,0.84 4.08,0.96"
+ id="path52"
+ style="fill:none;stroke:#ff9900;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g58"><path
+ d="m 337.92,327.31 0,48.72 50.16,13.56 0,-48.72 -50.16,-13.56 z"
+ id="path60"
+ style="fill:none;stroke:#00b800;stroke-width:0.72000003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none" /></g><path
+ d="m 342.72,461.59 -13.56,50.16 48.72,0 13.56,-50.16 -48.72,0 z"
+ id="path72"
+ style="fill:#ffffff;fill-opacity:1;stroke:#00b800;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none" /><g
+ transform="matrix(0,1,-1,0,718.75,123.67)"
+ id="g74"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path
+ d="m 283.32,265.39 9,0.24 8.88,0.6 8.76,1.2 8.76,1.68 8.64,2.04 8.52,2.52 8.4,3 8.28,3.36 8.04,3.84 7.8,4.2 7.56,4.68 7.32,5.04 7.08,5.4 6.84,5.88 6.36,6.12 6.12,6.36 5.88,6.84 5.4,7.08 5.04,7.32 4.68,7.56 4.2,7.8 3.84,8.04 3.36,8.28 3,8.4 2.52,8.52 2.04,8.64 1.68,8.76 1.2,8.76 0.6,8.88 0.24,9 -0.24,8.88 -0.6,8.88 -1.2,8.76 -1.68,8.76 -2.04,8.64 -2.52,8.52 -3,8.4 -3.36,8.28 -3.84,8.04 -4.2,7.8 -4.68,7.56 -5.04,7.32 -5.4,7.08 -5.88,6.84 -6.12,6.36 -6.36,6.24 -6.84,5.76 -7.08,5.4 -7.32,5.05 -7.56,4.67 -7.8,4.2 -8.04,3.84 -8.28,3.36 -8.4,3 -8.52,2.52 -8.64,2.16 -8.76,1.56 -8.76,1.2 -8.88,0.72 -9,0.12"
+ id="path76"
+ style="fill:none;stroke:#808080;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><path
+ d="m 283.32,406.99 0,198.36"
+ id="path56"
+ style="fill:none;stroke:#0d6299;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-mid:none;marker-end:url(#Arrow2Mend)" /><path
+ d="m 360.24,486.67 97.44,0"
+ id="path68"
+ style="fill:none;stroke:#00b800;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" /><path
+ d="M 411.6,539.71 360.24,486.67 333.12,586.75"
+ id="path64"
+ style="fill:none;stroke:#00b800;stroke-width:1.60000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart);marker-mid:none;marker-end:url(#Arrow1Mend)" /><text
+ x="277.50943"
+ y="-613.04358"
+ transform="scale(1,-1)"
+ id="text3721"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="277.50943"
+ y="-613.04358"
+ id="tspan3727">Z</tspan></text>
+
+
+
+
+
+
+<text
+ x="488.21332"
+ y="-399.92703"
+ transform="scale(1,-1)"
+ id="text3721-4"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="488.21332"
+ y="-399.92703"
+ id="tspan4386">Y</tspan></text>
+
+
+
+
+
+
+<text
+ x="238.70586"
+ y="-350.1015"
+ transform="scale(1,-1)"
+ id="text3721-4-9"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="238.70586"
+ y="-350.1015"
+ id="tspan4386-4">X</tspan></text>
+
+
+
+
+
+
+<text
+ x="341.8902"
+ y="-575.89331"
+ transform="scale(1,-1)"
+ id="text3721-8"
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="341.8902"
+ y="-575.89331"
+ id="tspan3727-8">North</tspan></text>
+
+
+
+
+
+
+<text
+ x="435.72714"
+ y="-491.9921"
+ transform="scale(1,-1)"
+ id="text3721-8-2"
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="435.72714"
+ y="-491.9921"
+ id="tspan3727-8-4">East</tspan></text>
+
+
+
+
+
+
+<text
+ x="414.17657"
+ y="-527.3114"
+ transform="scale(1,-1)"
+ id="text3721-8-2-5"
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="414.17657"
+ y="-527.3114"
+ id="tspan3727-8-4-5">Up</tspan></text>
+
+
+
+
+
+
+<text
+ x="290.61334"
+ y="-612.47876"
+ transform="scale(1,-1)"
+ id="text3721-0"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="290.61334"
+ y="-612.47876"
+ id="tspan3727-9"
+ style="font-size:11.19999981px">ecef</tspan></text>
+
+
+<text
+ x="501.1416"
+ y="-400.26947"
+ transform="scale(1,-1)"
+ id="text3721-0-4"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="501.1416"
+ y="-400.26947"
+ id="tspan3727-9-8"
+ style="font-size:11.19999981px">ecef</tspan></text>
+
+
+<text
+ x="253.27524"
+ y="-351.07462"
+ transform="scale(1,-1)"
+ id="text3721-0-2"
+ xml:space="preserve"
+ style="font-size:19.20000076px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="253.27524"
+ y="-351.07462"
+ id="tspan3727-9-4"
+ style="font-size:11.19999981px">ecef</tspan></text>
+
+
+<g
+ transform="matrix(-1,0,0,1,314.12527,7.5684393)"
+ id="text4066"
+ style="font-size:32px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><path
+ d="m 63.106132,443.21212 11.436928,0.6089 -0.229685,4.3142 c -0.04044,0.75933 -0.107718,1.3373 -0.201842,1.73391 -0.123533,0.55671 -0.326725,1.01791 -0.609576,1.38361 -0.282873,0.36568 -0.667108,0.65164 -1.152709,0.8579 -0.485618,0.20623 -1.011876,0.29427 -1.578773,0.26409 -0.972587,-0.0518 -1.779164,-0.40506 -2.419733,-1.05983 -0.64058,-0.65478 -0.917809,-1.79091 -0.83169,-3.40841 l 0.156169,-2.93334 -4.649665,-0.24755 z m 5.91874,1.83288 -0.157415,2.95675 c -0.05206,0.97778 0.09301,1.6818 0.435204,2.11206 0.342187,0.43025 0.843544,0.66297 1.504074,0.69814 0.478481,0.0255 0.894495,-0.0737 1.248042,-0.29735 0.35353,-0.22372 0.595432,-0.5303 0.725706,-0.91975 0.08117,-0.25125 0.140036,-0.72014 0.176596,-1.40666 l 0.155754,-2.92555 z"
+ id="path5083"
+ style="font-size:16px" /><path
+ d="m 62.494207,453.68612 8.288312,0.37685 -0.05748,1.26431 -1.256515,-0.0571 c 0.57326,0.34932 0.947337,0.66481 1.122232,0.94648 0.174879,0.28167 0.254871,0.5864 0.239976,0.91419 -0.02154,0.47347 -0.194303,0.94788 -0.518304,1.42324 l -1.28134,-0.54313 c 0.218521,-0.33418 0.335592,-0.67296 0.351212,-1.01635 0.01395,-0.30698 -0.06587,-0.58693 -0.239444,-0.83987 -0.173593,-0.25294 -0.421914,-0.43889 -0.744963,-0.55785 -0.492393,-0.1788 -1.035154,-0.28168 -1.628287,-0.30865 l -4.339267,-0.19729 z"
+ id="path5085"
+ style="font-size:16px" /><path
+ d="m 72.064046,459.64751 1.614176,0.0987 -0.08579,1.40363 -1.614175,-0.0987 z m -9.817616,-0.60005 8.281421,0.50616 -0.08579,1.40363 -8.281421,-0.50616 z"
+ id="path5087"
+ style="font-size:16px" /><path
+ d="m 62.072234,462.59865 8.273028,0.62861 -0.0953,1.25419 -1.160717,-0.0882 c 0.385345,0.29044 0.684987,0.66056 0.898927,1.11036 0.213925,0.44979 0.299977,0.94993 0.258157,1.50043 -0.04657,0.61282 -0.211986,1.1056 -0.496246,1.47837 -0.284275,0.37276 -0.661032,0.62228 -1.130274,0.74855 0.916238,0.72776 1.334505,1.61616 1.254803,2.66523 -0.06235,0.82054 -0.337508,1.43427 -0.825462,1.84119 -0.487967,0.4069 -1.204542,0.57444 -2.149729,0.50264 l -5.678943,-0.4315 0.105951,-1.39442 5.211541,0.39598 c 0.560878,0.0426 0.968114,0.0279 1.22171,-0.0443 0.253584,-0.0721 0.464759,-0.22195 0.633524,-0.44939 0.168753,-0.22746 0.265366,-0.50218 0.289837,-0.82416 0.04419,-0.58166 -0.112565,-1.07934 -0.470263,-1.49304 -0.357711,-0.41372 -0.962419,-0.65293 -1.814125,-0.71763 l -4.806458,-0.36521 0.106543,-1.40221 5.375131,0.40842 c 0.623198,0.0473 1.099282,-0.0314 1.428252,-0.23622 0.328958,-0.20484 0.51317,-0.56692 0.552637,-1.08625 0.02998,-0.3947 -0.04616,-0.76743 -0.228439,-1.11818 -0.182289,-0.35076 -0.467653,-0.61664 -0.856092,-0.79762 -0.388451,-0.181 -0.959192,-0.3001 -1.712225,-0.35732 l -4.292315,-0.32614 z"
+ id="path5089"
+ style="font-size:16px" /><path
+ d="m 63.112413,481.79967 -0.313505,1.43024 c -0.824084,-0.30683 -1.44079,-0.7905 -1.850119,-1.45104 -0.409329,-0.66055 -0.569371,-1.47052 -0.480128,-2.42991 0.1124,-1.20833 0.573615,-2.13182 1.383645,-2.77048 0.81003,-0.63866 1.886624,-0.89551 3.229786,-0.77057 1.389828,0.12928 2.435218,0.58745 3.136173,1.37451 0.700941,0.78705 0.998351,1.75103 0.89223,2.89194 -0.102759,1.1046 -0.562677,1.97198 -1.379756,2.60215 -0.817092,0.63014 -1.907586,0.88178 -3.271484,0.75492 -0.08298,-0.008 -0.2072,-0.0219 -0.372665,-0.0425 l 0.573093,-6.1609 c -0.912368,-0.0326 -1.631162,0.15949 -2.156387,0.57618 -0.525227,0.41669 -0.81992,0.96989 -0.884079,1.65963 -0.04776,0.5134 0.04631,0.96416 0.282215,1.35226 0.2359,0.3881 0.63956,0.71596 1.210981,0.98358 z m 2.691313,-4.38677 -0.429095,4.6129 c 0.7007,0.002 1.238289,-0.12544 1.612767,-0.38353 0.580818,-0.39582 0.904275,-0.94897 0.97037,-1.65944 0.05981,-0.64306 -0.105115,-1.20372 -0.494779,-1.68196 -0.389676,-0.47826 -0.942763,-0.77425 -1.659263,-0.88797 z"
+ id="path5091"
+ style="font-size:16px" /><path
+ d="m 59.792635,489.32216 11.383842,1.25786 -0.250542,2.26745 -8.358053,1.80391 c -0.778099,0.16554 -1.359804,0.28467 -1.745119,0.35738 0.399845,0.17517 0.985813,0.44428 1.757906,0.80732 l 7.61938,3.60078 -0.223944,2.02673 -11.383842,-1.25786 0.16045,-1.4521 9.52795,1.0528 -9.162433,-4.36079 0.150154,-1.35892 10.05482,-2.22165 -9.691019,-1.07081 z"
+ id="path5093"
+ style="font-size:16px" /><path
+ d="m 60.144362,508.42535 -0.370341,1.41658 c -0.811182,-0.33947 -1.40809,-0.84738 -1.790728,-1.52372 -0.382638,-0.67637 -0.510223,-1.49208 -0.382757,-2.44715 0.16054,-1.20288 0.658247,-2.10722 1.493124,-2.71304 0.834875,-0.60581 1.920864,-0.81949 3.257969,-0.64104 1.38356,0.18465 2.409829,0.68418 3.078811,1.49859 0.668967,0.8144 0.927664,1.78949 0.77609,2.92526 -0.146767,1.09961 -0.64094,1.94794 -1.48252,2.54499 -0.841592,0.59703 -1.941261,0.80495 -3.29901,0.62374 -0.0826,-0.011 -0.20616,-0.0301 -0.37067,-0.0573 l 0.818543,-6.13312 c -0.91034,-0.0689 -1.636228,0.0943 -2.177666,0.48966 -0.54144,0.39539 -0.857979,0.93639 -0.949617,1.62302 -0.06821,0.51108 0.0078,0.96523 0.228016,1.36245 0.220221,0.3972 0.610473,0.74091 1.170756,1.03113 z m 2.864264,-4.27586 -0.612874,4.5921 c 0.700046,0.0304 1.242309,-0.0759 1.62679,-0.31885 0.596155,-0.37233 0.941432,-0.91212 1.035833,-1.61939 0.08543,-0.64016 -0.05699,-1.20695 -0.427251,-1.70037 -0.370277,-0.49343 -0.911109,-0.81126 -1.622498,-0.95349 z"
+ id="path5095"
+ style="font-size:16px" /><path
+ d="m 57.017756,511.24663 8.203227,1.24307 -0.18962,1.25134 -1.243615,-0.18845 c 0.533511,0.40744 0.872478,0.76039 1.016902,1.05883 0.144409,0.29844 0.192036,0.60987 0.142884,0.9343 -0.07102,0.4686 -0.292535,0.92231 -0.664552,1.36111 l -1.217391,-0.67438 c 0.252328,-0.30944 0.404246,-0.63409 0.455754,-0.97396 0.04603,-0.30383 -0.004,-0.5906 -0.150142,-0.86033 -0.146139,-0.26973 -0.373613,-0.48067 -0.682422,-0.63282 -0.470952,-0.2294 -0.999949,-0.38858 -1.586992,-0.47754 l -4.294722,-0.65079 z"
+ id="path5097"
+ style="font-size:16px" /><path
+ d="m 65.979482,517.99715 1.599793,0.23656 -0.2057,1.39112 -1.599793,-0.23655 z m -9.730141,-1.43875 8.207633,1.21362 -0.2057,1.39113 -8.207633,-1.21363 z"
+ id="path5099"
+ style="font-size:16px" /><path
+ d="m 54.756351,525.36962 1.030675,0.18346 c -0.717999,-0.66212 -0.987553,-1.49569 -0.808664,-2.50072 0.115914,-0.65123 0.401943,-1.21795 0.858087,-1.70016 0.456144,-0.48221 1.032678,-0.81604 1.729604,-1.00146 0.696922,-0.18543 1.463294,-0.20376 2.299118,-0.055 0.815306,0.14512 1.530795,0.41266 2.14647,0.80263 0.615662,0.38996 1.052029,0.8882 1.309104,1.49472 0.25706,0.60651 0.325811,1.24564 0.206255,1.91738 -0.08763,0.49225 -0.2695,0.91219 -0.545619,1.25982 -0.276133,0.34761 -0.602296,0.61225 -0.97849,0.79394 l 4.045786,0.72012 -0.245061,1.3768 -11.275898,-2.00704 z m 4.855545,-3.65092 c -1.046061,-0.1862 -1.867287,-0.10489 -2.463679,0.24391 -0.596395,0.3488 -0.947985,0.82318 -1.054771,1.42313 -0.107699,0.60506 0.04821,1.16316 0.467744,1.67428 0.419528,0.51111 1.136938,0.85702 2.152232,1.03774 1.117843,0.19896 1.976614,0.12963 2.576315,-0.20799 0.599691,-0.33765 0.95567,-0.82182 1.067939,-1.45252 0.109518,-0.61534 -0.05024,-1.17412 -0.479282,-1.67634 -0.429051,-0.50223 -1.18455,-0.84963 -2.266498,-1.04221 z"
+ id="path5101"
+ style="font-size:16px" /><path
+ d="m 63.779537,530.73494 1.587034,0.31084 -0.270294,1.38003 -1.587034,-0.31084 z m -9.652536,-1.89055 8.142171,1.59473 -0.270294,1.38003 -8.142171,-1.59474 z"
+ id="path5103"
+ style="font-size:16px" /><path
+ d="m 53.252402,537.8338 c -0.320697,-0.60367 -0.518405,-1.16033 -0.593125,-1.66998 -0.07472,-0.50966 -0.05287,-1.03411 0.06554,-1.57334 0.19549,-0.89025 0.563212,-1.52671 1.103167,-1.90939 0.539954,-0.38268 1.148225,-0.49974 1.824814,-0.35116 0.396794,0.0871 0.739423,0.25702 1.027889,0.50966 0.28846,0.25265 0.499774,0.54701 0.633944,0.88308 0.134161,0.33608 0.211901,0.69842 0.233217,1.08704 0.01201,0.28525 -0.0087,0.7073 -0.06207,1.26615 -0.111262,1.13803 -0.132853,1.98915 -0.06477,2.55334 0.187103,0.0464 0.306091,0.0752 0.356967,0.0864 0.559579,0.12287 0.982317,0.0797 1.268214,-0.12945 0.387387,-0.28287 0.657045,-0.77023 0.808974,-1.46207 0.141864,-0.64607 0.133401,-1.14785 -0.02539,-1.50532 -0.1588,-0.35749 -0.509421,-0.67311 -1.051865,-0.94686 l 0.478046,-1.30279 c 0.548029,0.24832 0.968104,0.5512 1.260227,0.90863 0.292108,0.35742 0.475461,0.82161 0.550059,1.39257 0.07458,0.57095 0.03536,1.20489 -0.117674,1.90183 -0.15193,0.69184 -0.356761,1.2361 -0.614495,1.63276 -0.257746,0.39666 -0.53232,0.66964 -0.823723,0.81895 -0.291415,0.1493 -0.634279,0.22332 -1.028595,0.22206 -0.244066,-0.006 -0.671324,-0.0754 -1.281775,-0.20948 l -1.831366,-0.40215 c -1.276869,-0.28039 -2.090873,-0.42848 -2.442014,-0.44426 -0.351139,-0.0158 -0.700857,0.0287 -1.049154,0.13356 l 0.315017,-1.43457 c 0.316159,-0.0799 0.669473,-0.0983 1.059943,-0.0552 z m 3.092672,0.55914 c -0.09401,-0.54323 -0.102764,-1.32902 -0.02625,-2.35737 0.0426,-0.58254 0.03872,-1.00199 -0.01163,-1.25834 -0.05036,-0.25635 -0.159502,-0.46962 -0.327427,-0.6398 -0.167929,-0.17019 -0.37144,-0.28153 -0.610533,-0.33403 -0.366275,-0.0804 -0.701942,-0.009 -1.007004,0.2148 -0.305064,0.22362 -0.516242,0.60251 -0.633535,1.13666 -0.116177,0.52906 -0.103775,1.02503 0.03721,1.48792 0.14098,0.46288 0.391187,0.8351 0.750622,1.11667 0.277918,0.21566 0.719561,0.38996 1.324931,0.5229 z"
+ id="path5105"
+ style="font-size:16px" /><path
+ d="m 51.49594,541.02374 8.010721,2.16021 -0.329523,1.22197 -1.139001,-0.30714 c 0.721357,0.82566 0.932194,1.79416 0.632512,2.90551 -0.130189,0.48275 -0.336606,0.90314 -0.619253,1.26118 -0.282659,0.35801 -0.59191,0.59963 -0.927754,0.72485 -0.335855,0.1252 -0.708232,0.17582 -1.117135,0.15187 -0.264999,-0.0175 -0.711791,-0.11103 -1.340375,-0.28053 l -4.925613,-1.32826 0.366137,-1.35775 4.872811,1.31402 c 0.553154,0.14916 0.981002,0.20789 1.283548,0.17621 0.302537,-0.0317 0.571798,-0.16004 0.807785,-0.385 0.235977,-0.22497 0.402786,-0.51848 0.500428,-0.88054 0.155941,-0.57831 0.106983,-1.1269 -0.146876,-1.64579 -0.253869,-0.51889 -0.893728,-0.91665 -1.919578,-1.19328 l -4.37497,-1.17978 z"
+ id="path5107"
+ style="font-size:16px" /></g>
+<text
+ x="315.86932"
+ y="-413.14511"
+ transform="scale(1,-1)"
+ id="text3721-8-2-5-1"
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="315.86932"
+ y="-413.14511"
+ id="tspan3727-8-4-5-7">φ</tspan></text>
+
+<text
+ x="292.20465"
+ y="-379.30618"
+ transform="scale(1,-1)"
+ id="text3721-8-2-5-1-1"
+ xml:space="preserve"
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:sans-serif"><tspan
+ x="292.20465"
+ y="-379.30618"
+ id="tspan3727-8-4-5-7-1">λ</tspan></text>
+
+</g></svg> \ No newline at end of file
diff --git a/docs/source/operations/conversions/index.rst b/docs/source/operations/conversions/index.rst
index b0bd0d37..b335c2ac 100644
--- a/docs/source/operations/conversions/index.rst
+++ b/docs/source/operations/conversions/index.rst
@@ -19,4 +19,5 @@ conversions.
pop
push
set
+ topocentric
unitconvert
diff --git a/docs/source/operations/conversions/topocentric.rst b/docs/source/operations/conversions/topocentric.rst
new file mode 100644
index 00000000..828ef4e0
--- /dev/null
+++ b/docs/source/operations/conversions/topocentric.rst
@@ -0,0 +1,115 @@
+.. _topocentric:
+
+================================================================================
+Geocentric to topocentric conversion
+================================================================================
+
+.. versionadded:: 8.0.0
+
+Convert geocentric coordinates to topocentric coordinates (in the forward path).
+
++---------------------+--------------------------------------------------------+
+| **Alias** | topocentric |
++---------------------+--------------------------------------------------------+
+| **Domain** | 3D |
++---------------------+--------------------------------------------------------+
+| **Input type** | Geocentric cartesian coordinates |
++---------------------+--------------------------------------------------------+
+| **Output type** | Topocentric cartesian coordinates |
++---------------------+--------------------------------------------------------+
+
+This operation converts geocentric coordinate values (X, Y, Z) to topocentric
+(E/East, N/North, U/Up) values. This is also sometimes known as the ECEF (Earth
+Centered Earth Fixed) to ENU conversion.
+
+Topocentric coordinates are expressed in a frame whose East and North axis form
+a local tangent plane to the Earth's ellipsoidal surface fixed to a specific
+location (the topocentric origin), and the Up axis points upwards along the
+normal to that plane.
+
+.. image:: ./images/ECEF_ENU_Longitude_Latitude_relationships.png
+ :align: center
+ :scale: 100%
+ :alt: ENU coordinate frame
+
+..
+ Source : https://en.wikipedia.org/wiki/Local_tangent_plane_coordinates#/media/File:ECEF_ENU_Longitude_Latitude_relationships.svg
+ Public domain
+..
+
+The topocentric origin is a required parameter of the conversion, and can be
+expressed either as geocentric coordinates (``X_0``, ``Y_0`` and ``Z_0``) or
+as geographic coordinates (``lat_0``, ``lon_0``, ``h_0``).
+
+When conversion between geographic and topocentric coordinates is desired, the
+topocentric conversion must be preceded by the :ref:`cart` conversion to
+perform the initial geographic to geocentric coordinates conversion.
+
+The formulas used come from the "Geocentric/topocentric conversions" paragraph
+of :cite:`IOGP2018`
+
+Usage
+################################################################################
+
+Convert geocentric coordinates to topocentric coordinates, with the topocentric
+origin specified in geocentric coordinates::
+
+ echo 3771793.968 140253.342 5124304.349 2020 | \
+ cct -d 3 +proj=topocentric +ellps=WGS84 +X_0=3652755.3058 +Y_0=319574.6799 +Z_0=5201547.3536
+
+ -189013.869 -128642.040 -4220.171 2020.0000
+
+Convert geographic coordinates to topocentric coordinates, with the topocentric
+origin specified in geographic coordinates::
+
+ echo 2.12955 53.80939444 73 2020 | cct -d 3 +proj=pipeline \
+ +step +proj=cart +ellps=WGS84 \
+ +step +proj=topocentric +ellps=WGS84 +lon_0=5 +lat_0=55 +h_0=200
+
+ -189013.869 -128642.040 -4220.171 2020.0000
+
+
+Parameters
+################################################################################
+
+.. include:: ../options/ellps.rst
+
+Topocentric origin described as geocentric coordinates
+------------------------------------------------------
+
+.. note::
+
+ The below options are mutually exclusive with the ones to express the origin as geographic coordinates.
+
+.. option:: +X_0=<value>
+
+ Geocentric X value of the topocentric origin (in metre)
+
+.. option:: +Y_0=<value>
+
+ Geocentric Y value of the topocentric origin (in metre)
+
+.. option:: +Z_0=<value>
+
+ Geocentric Z value of the topocentric origin (in metre)
+
+Topocentric origin described as geographic coordinates
+------------------------------------------------------
+
+.. note::
+
+ The below options are mutually exclusive with the ones to express the origin as geocentric coordinates.
+
+.. option:: +lat_0=<value>
+
+ Latitude of topocentric origin (in degree)
+
+.. option:: +lon_0=<value>
+
+ Longitude of topocentric origin (in degree)
+
+.. option:: +h_0=<value>
+
+ Ellipsoidal height of topocentric origin (in metre)
+
+ *Defaults to 0.0.*
diff --git a/docs/source/operations/projections/isea.rst b/docs/source/operations/projections/isea.rst
index adb703a1..73f0af7a 100644
--- a/docs/source/operations/projections/isea.rst
+++ b/docs/source/operations/projections/isea.rst
@@ -43,7 +43,9 @@ Parameters
.. option:: +orient=<string>
- Can be set to either ``isea`` or ``pole``.
+ Can be set to either ``isea`` or ``pole``. See Snyder's Figure 12 for pole orientation :cite:`Snyder1992`.
+
+ *Defaults to isea*
.. option:: +azi=<value>
@@ -62,6 +64,8 @@ Parameters
.. option:: +mode=<string>
Can be either ``plane``, ``di``, ``dd`` or ``hex``.
+
+ *Defaults to plane*
.. include:: ../options/lon_0.rst
diff --git a/docs/source/operations/projections/merc.rst b/docs/source/operations/projections/merc.rst
index 7b6e13da..2107b7b2 100644
--- a/docs/source/operations/projections/merc.rst
+++ b/docs/source/operations/projections/merc.rst
@@ -158,7 +158,35 @@ Inverse projection
\lambda = \frac{x}{k_0 a}; \quad \psi = \frac{y}{k_0 a}
The latitude :math:`\phi` is found by inverting the equation for
-:math:`\psi` iteratively.
+:math:`\psi`. This follows the method given by :cite:`Karney2011tm`.
+Start by introducing the conformal latitude
+
+.. math::
+ \chi = \tan^{-1}\sinh\psi
+
+The tangents of the latitudes :math:`\tau = \tan\phi` and :math:`\tau' =
+\tan\chi = \sinh\psi` are related by
+
+.. math::
+ \tau' = \tau \sqrt{1 + \sigma^2} - \sigma \sqrt{1 + \tau^2}
+
+where
+
+.. math::
+ \sigma = \sinh\bigl(e \tanh^{-1}(e \tau/\sqrt{1 + \tau^2}) \bigr)
+
+This is obtained by taking the :math:`\sinh` of the equation for
+:math:`\psi` and using the multiple argument formula. The equation for
+:math:`\tau'` can be solved to give :math:`\tau` using Newton's method
+using :math:`\tau = \tau'/(1 - e^2)` as an initial guess and with the
+needed derivative given by
+
+..math::
+ \frac{d\tau'}{d\tau} = \frac{1 - e^2}{1 + (1 - e^2)\tau^2}
+ \sqrt{1 + \tau'^2} \sqrt{1 + \tau^2}
+
+This converges after no more than 2 iterations. Finally set
+:math:`\phi=\tan^{-1}\tau`.
Further reading
###############
diff --git a/docs/source/operations/projections/utm.rst b/docs/source/operations/projections/utm.rst
index 82715a02..cbbda09d 100644
--- a/docs/source/operations/projections/utm.rst
+++ b/docs/source/operations/projections/utm.rst
@@ -6,7 +6,7 @@ Universal Transverse Mercator (UTM)
The Universal Transverse Mercator is a system of map projections divided into
sixty zones across the globe, with each zone corresponding to 6 degrees of
-longigude.
+longitude.
+---------------------+----------------------------------------------------------+
| **Classification** | Transverse cylindrical, conformal |
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp
index b607ff9d..8c1f9f6f 100644
--- a/include/proj/crs.hpp
+++ b/include/proj/crs.hpp
@@ -155,6 +155,11 @@ class PROJ_GCC_DLL CRS : public common::ObjectUsage,
const;
PROJ_INTERNAL bool hasImplicitCS() const;
+
+ PROJ_INTERNAL static CRSNNPtr
+ getResolvedCRS(const CRSNNPtr &crs,
+ const io::AuthorityFactoryPtr &authFactory,
+ metadata::ExtentPtr &extentOut);
//! @endcond
protected:
@@ -335,6 +340,11 @@ class PROJ_GCC_DLL GeodeticCRS : virtual public SingleCRS,
PROJ_INTERNAL std::list<std::pair<CRSNNPtr, int>>
_identify(const io::AuthorityFactoryPtr &authorityFactory) const override;
+ PROJ_INTERNAL bool
+ _isEquivalentToNoTypeCheck(const util::IComparable *other,
+ util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const;
+
INLINED_MAKE_SHARED
private:
@@ -1400,6 +1410,7 @@ class PROJ_GCC_DLL DerivedCRSTemplate final : public DerivedCRSTraits::BaseType,
DerivedCRSTemplate(const BaseNNPtr &baseCRSIn,
const operation::ConversionNNPtr &derivingConversionIn,
const CSNNPtr &csIn);
+ // cppcheck-suppress noExplicitConstructor
PROJ_INTERNAL DerivedCRSTemplate(const DerivedCRSTemplate &other);
PROJ_INTERNAL CRSNNPtr _shallowClone() const override;
diff --git a/include/proj/internal/coordinateoperation_constants.hpp b/include/proj/internal/coordinateoperation_constants.hpp
index 592f6263..0ed3a027 100644
--- a/include/proj/internal/coordinateoperation_constants.hpp
+++ b/include/proj/internal/coordinateoperation_constants.hpp
@@ -532,6 +532,34 @@ static const ParamMapping *const paramsColombiaUrban[] = {
&paramProjectionPlaneOriginHeight,
nullptr};
+static const ParamMapping paramGeocentricXTopocentricOrigin = {
+ EPSG_NAME_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN,
+ EPSG_CODE_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN, nullptr,
+ common::UnitOfMeasure::Type::LINEAR, "X_0"};
+
+static const ParamMapping paramGeocentricYTopocentricOrigin = {
+ EPSG_NAME_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN,
+ EPSG_CODE_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN, nullptr,
+ common::UnitOfMeasure::Type::LINEAR, "Y_0"};
+
+static const ParamMapping paramGeocentricZTopocentricOrigin = {
+ EPSG_NAME_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN,
+ EPSG_CODE_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN, nullptr,
+ common::UnitOfMeasure::Type::LINEAR, "Z_0"};
+
+static const ParamMapping *const paramsGeocentricTopocentric[] = {
+ &paramGeocentricXTopocentricOrigin, &paramGeocentricYTopocentricOrigin,
+ &paramGeocentricZTopocentricOrigin, nullptr};
+
+static const ParamMapping paramHeightTopoOriginWithH0 = {
+ EPSG_NAME_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN,
+ EPSG_CODE_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN, nullptr,
+ common::UnitOfMeasure::Type::LINEAR, "h_0"};
+
+static const ParamMapping *const paramsGeographicTopocentric[] = {
+ &paramLatTopoOrigin, &paramLonTopoOrigin, &paramHeightTopoOriginWithH0,
+ nullptr};
+
static const MethodMapping projectionMethodMappings[] = {
{EPSG_NAME_METHOD_TRANSVERSE_MERCATOR, EPSG_CODE_METHOD_TRANSVERSE_MERCATOR,
"Transverse_Mercator", "tmerc", nullptr, paramsNatOriginScaleK},
@@ -836,6 +864,14 @@ static const MethodMapping projectionMethodMappings[] = {
{EPSG_NAME_METHOD_COLOMBIA_URBAN, EPSG_CODE_METHOD_COLOMBIA_URBAN, nullptr,
"col_urban", nullptr, paramsColombiaUrban},
+
+ {EPSG_NAME_METHOD_GEOCENTRIC_TOPOCENTRIC,
+ EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC, nullptr, "topocentric", nullptr,
+ paramsGeocentricTopocentric},
+
+ {EPSG_NAME_METHOD_GEOGRAPHIC_TOPOCENTRIC,
+ EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC, nullptr, nullptr, nullptr,
+ paramsGeographicTopocentric},
};
#define METHOD_NAME_CODE(method) \
@@ -878,6 +914,8 @@ static const struct MethodNameCode {
METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_2D),
METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_3D),
METHOD_NAME_CODE(GEOGRAPHIC_GEOCENTRIC),
+ METHOD_NAME_CODE(GEOCENTRIC_TOPOCENTRIC),
+ METHOD_NAME_CODE(GEOGRAPHIC_TOPOCENTRIC),
// Transformations
METHOD_NAME_CODE(LONGITUDE_ROTATION),
METHOD_NAME_CODE(AFFINE_PARAMETRIC_TRANSFORMATION),
@@ -943,6 +981,9 @@ static const struct ParamNameCode {
PARAM_NAME_CODE(LONGITUDE_OF_ORIGIN),
PARAM_NAME_CODE(ELLIPSOID_SCALE_FACTOR),
PARAM_NAME_CODE(PROJECTION_PLANE_ORIGIN_HEIGHT),
+ PARAM_NAME_CODE(GEOCENTRIC_X_TOPOCENTRIC_ORIGIN),
+ PARAM_NAME_CODE(GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN),
+ PARAM_NAME_CODE(GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN),
// Parameters of transformations
PARAM_NAME_CODE(SEMI_MAJOR_AXIS_DIFFERENCE),
PARAM_NAME_CODE(FLATTENING_DIFFERENCE),
diff --git a/include/proj/io.hpp b/include/proj/io.hpp
index 20dcedfe..bc11c220 100644
--- a/include/proj/io.hpp
+++ b/include/proj/io.hpp
@@ -243,6 +243,10 @@ class PROJ_GCC_DLL WKTFormatter {
PROJ_DLL WKTFormatter &setStrict(bool strict) noexcept;
PROJ_DLL bool isStrict() const noexcept;
+ PROJ_DLL WKTFormatter &
+ setAllowEllipsoidalHeightAsVerticalCRS(bool allow) noexcept;
+ PROJ_DLL bool isAllowedEllipsoidalHeightAsVerticalCRS() const noexcept;
+
PROJ_DLL const std::string &toString() const;
PROJ_PRIVATE :
@@ -1032,6 +1036,8 @@ class PROJ_GCC_DLL AuthorityFactory {
DYNAMIC_GEODETIC_REFERENCE_FRAME,
/** Object of type datum::DynamicVerticalReferenceFrame */
DYNAMIC_VERTICAL_REFERENCE_FRAME,
+ /** Object of type datum::DatumEnsemble */
+ DATUM_ENSEMBLE,
};
PROJ_DLL std::set<std::string>
@@ -1225,6 +1231,18 @@ class PROJ_GCC_DLL AuthorityFactory {
private:
PROJ_OPAQUE_PRIVATE_DATA
+
+ PROJ_INTERNAL void
+ createGeodeticDatumOrEnsemble(const std::string &code,
+ datum::GeodeticReferenceFramePtr &outDatum,
+ datum::DatumEnsemblePtr &outDatumEnsemble,
+ bool turnEnsembleAsDatum) const;
+
+ PROJ_INTERNAL void
+ createVerticalDatumOrEnsemble(const std::string &code,
+ datum::VerticalReferenceFramePtr &outDatum,
+ datum::DatumEnsemblePtr &outDatumEnsemble,
+ bool turnEnsembleAsDatum) const;
};
// ---------------------------------------------------------------------------
diff --git a/include/proj/util.hpp b/include/proj/util.hpp
index 3d85e579..2ada4f79 100644
--- a/include/proj/util.hpp
+++ b/include/proj/util.hpp
@@ -213,6 +213,14 @@ template <typename T> using nn_shared_ptr = nn<std::shared_ptr<T>>;
// To avoid formatting differences between clang-format 3.8 and 7
#define PROJ_NOEXCEPT noexcept
+//! @cond Doxygen_Suppress
+// isOfExactType<MyType>(*p) checks that the type of *p is exactly MyType
+template <typename TemplateT, typename ObjectT>
+inline bool isOfExactType(const ObjectT &o) {
+ return typeid(TemplateT).hash_code() == typeid(o).hash_code();
+}
+//! @endcond
+
/** \brief Loose transposition of [std::optional]
* (https://en.cppreference.com/w/cpp/utility/optional) available from C++17. */
template <class T> class optional {
diff --git a/scripts/build_db.py b/scripts/build_db.py
index 63636a71..af304424 100755
--- a/scripts/build_db.py
+++ b/scripts/build_db.py
@@ -401,6 +401,9 @@ def fill_helmert_transformation(proj_db_cursor):
assert param_code[6] == 8611
assert param_uom_code[3] == param_uom_code[4]
assert param_uom_code[3] == param_uom_code[5]
+ for i in range(7):
+ assert param_uom_code[i] is not None
+
if n_params == 8: # Time-specific transformation
assert param_code[7] == 1049, (code, name, param_code[7])
param_value[14] = param_value[7]
@@ -438,6 +441,8 @@ def fill_helmert_transformation(proj_db_cursor):
assert param_uom_code[7] == param_uom_code[9]
assert param_uom_code[10] == param_uom_code[11]
assert param_uom_code[10] == param_uom_code[12]
+ for i in range(15):
+ assert param_uom_code[i] is not None, (code, name, i, param_name[i])
arg = (EPSG_AUTHORITY, code, name,
remarks,
diff --git a/scripts/build_db_create_ignf.py b/scripts/build_db_create_ignf.py
deleted file mode 100755
index 97157ec5..00000000
--- a/scripts/build_db_create_ignf.py
+++ /dev/null
@@ -1,527 +0,0 @@
-#!/usr/bin/env python
-###############################################################################
-# $Id$
-#
-# Project: PROJ
-# Purpose: Build SRS and coordinate transform database
-# Author: Even Rouault <even.rouault at spatialys.com>
-#
-###############################################################################
-# Copyright (c) 2018, Even Rouault <even.rouault at spatialys.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.
-###############################################################################
-
-import copy
-import json
-import os
-import sqlite3
-import sys
-
-if len(sys.argv) != 3:
- print('Usage: build_db_create_ignf.py path_to_IGNF_file proj.db')
- sys.exit(1)
-
-def escape_literal(x):
- return x.replace("'", "''")
-
-def find_ellipsoid(cursor, line, d):
- for prec in (10,9,8,7,6):
- cursor.execute('SELECT code, name FROM ellipsoid WHERE code != 1024 AND semi_major_axis = ? AND (inv_flattening = ? OR (abs(semi_major_axis / (semi_major_axis - semi_minor_axis)) - ?) < 1e-%d)' % prec, (float(d['a']), float(d['rf']), float(d['rf'])))
- row = cursor.fetchone()
- if prec > 6 and row is None:
- continue
- assert row, line
- ellps_code, ellps_name = row
- return ellps_code, ellps_name
-
-def find_geogcrs_code(line,d):
- pm = None
- if 'pm' in d:
- pm = d['pm']
- assert pm == '2.337229167', pm
-
- key = { 'a' : d['a'], 'rf' : d['rf'], 'towgs84' : d['towgs84'], 'pm': pm }
- key_geog_crs = json.dumps(key)
- if 'W84' in code:
- geogcrs_code = "WGS84G"
- elif 'RGFG95' in code:
- geogcrs_code = "RGFG95GEO"
- elif 'ETRS89' in code:
- geogcrs_code = "ETRS89GEO"
- elif 'RGF93' in code:
- geogcrs_code = "RGF93G"
- elif 'LAMB93' in code:
- geogcrs_code = "RGF93G"
- elif 'MILLER' in code:
- geogcrs_code = "WGS84G"
- elif code.startswith('GEOPORTAL'):
- geogcrs_code = 'RGF93G'
- elif key_geog_crs not in map_geog_crs:
- max_count_common = 0
- max_common_code = None
- for k in map_geog_crs:
- temp = copy.copy(key)
- temp['code'] = map_geog_crs[k]['code']
- if temp == json.loads(k):
- count_common = 0
- while True:
- if len(code) <= count_common:
- break
- if len(map_geog_crs[k]['code']) <= count_common:
- break
- if code[count_common] == map_geog_crs[k]['code'][count_common]:
- count_common += 1
- else:
- break
- if count_common > max_count_common:
- max_count_common = count_common
- max_common_code = map_geog_crs[k]['code']
- assert max_count_common >= 4, (max_common_code, max_count_common, line)
- geogcrs_code = max_common_code
- else:
- geogcrs_code = map_geog_crs[key_geog_crs]['code']
- return geogcrs_code
-
-
-IGNF_file = sys.argv[1]
-proj_db = sys.argv[2]
-
-conn = sqlite3.connect(proj_db)
-cursor = conn.cursor()
-
-all_sql = []
-
-geocentric_crs_name_to_datum_code = {}
-map_geog_crs = {}
-
-for line in open(IGNF_file, 'rt').readlines():
- line = line.strip('\n')
- if line[0] == '#' or line.startswith('<metadata>'):
- continue
- assert line[0] == '<'
- code = line[1:line.find('>')]
- proj4_string = line[line.find('>')+1:]
- #print(code, proj4_string)
- tokens = proj4_string.split(' +')
- assert tokens[0] == ''
- tokens = tokens[1:]
- d = {}
- for token in tokens:
- if token == 'no_defs <>' or token == 'wktext':
- continue
- pos_equal = token.find('=')
- assert pos_equal > 0, line
- key = token[0:pos_equal]
- value = token[pos_equal+1:]
- d[key] = value
- assert 'proj' in d, line
- assert 'title' in d, line
- proj = d['proj']
-
- assert 'a' in d
- assert 'rf' in d
- assert (not 'nadgrids' in d) or d['nadgrids'] in ('null', '@null', 'ntf_r93.gsb,null'), line
- assert 'towgs84' in d
-
- if proj == 'geocent':
-
- ellps_code, ellps_name = find_ellipsoid(cursor, line, d)
-
- datum_code = 'DATUM_' + code
-
- geocentric_crs_name_to_datum_code[d['title']] = datum_code
-
- sql = """INSERT INTO "geodetic_datum" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','%s','EPSG','8901','EPSG','1262',0);""" % (datum_code, escape_literal(d['title']), ellps_code)
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','geocentric');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "geodetic_crs" VALUES('IGNF','%s','%s',NULL,NULL,'geocentric','EPSG','6500','IGNF','%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), datum_code)
- all_sql.append(sql)
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978','helmert_transformation');""" % (code)
- #all_sql.append(sql)
-
- towgs84 = d['towgs84'].split(',')
- assert len(towgs84) in (3, 7), towgs84
- x = towgs84[0]
- y = towgs84[1]
- z = towgs84[2]
- if len(towgs84) == 3:
- rx = 'NULL'
- ry = 'NULL'
- rz = 'NULL'
- s = 'NULL'
- r_uom_auth_name = 'NULL'
- r_uom_code = 'NULL'
- s_uom_auth_name = 'NULL'
- s_uom_code = 'NULL'
- method_code = "'1031'"
- method_name = "'Geocentric translations (geocentric domain)'"
- else:
- rx = towgs84[3]
- ry = towgs84[4]
- rz = towgs84[5]
- s = towgs84[6]
- r_uom_auth_name = "'EPSG'"
- r_uom_code = "'9104'"
- s_uom_auth_name = "'EPSG'"
- s_uom_code = "'9202'"
- method_code = "'1033'"
- method_name = "'Position Vector transformation (geocentric domain)'"
-
- sql = """INSERT INTO "helmert_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978','%s to WGS 84',NULL,NULL,'EPSG',%s,%s,'IGNF','%s','EPSG','4978','EPSG','1262',NULL,%s,%s,%s,'EPSG','9001',%s,%s,%s,%s,%s,%s,%s, %s,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), method_code, method_name, code, x, y, z, rx, ry, rz, r_uom_auth_name, r_uom_code, s, s_uom_auth_name, s_uom_code)
- all_sql.append(sql)
-
- if 'nadgrids' in d and d['nadgrids'] == 'ntf_r93.gsb,null':
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978_GRID','grid_transformation');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "grid_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4978_GRID','%s to WGS 84 (2)',NULL,NULL,'EPSG','9615','NTv2','IGNF','%s','EPSG','4978','EPSG','1262',NULL,'EPSG','8656','Latitude and longitude difference file','ntf_r93.gsb',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'longlat':
-
- pm = None
- pm_code = "'8901'" # Greenwich
- if 'pm' in d:
- pm = d['pm']
- assert pm == '2.337229167', pm
- pm_code = "'8903'" # Paris
-
- ellps_code, ellps_name = find_ellipsoid(cursor, line, d)
-
- if d['title'] in geocentric_crs_name_to_datum_code:
- datum_code = geocentric_crs_name_to_datum_code[d['title']]
- else:
- datum_code = 'DATUM_' + code
- sql = """INSERT INTO "geodetic_datum" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','%s','EPSG',%s,'EPSG','1262',0);""" % (datum_code, escape_literal(d['title']), ellps_code, pm_code)
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','geographic 2D');""" % (code)
- #all_sql.append(sql)
-
- cs_code = "'6424'" # Long Lat deg
- if 'grades' in d['title']:
- cs_code = "'6425'" # Long Lat grad
-
- sql = """INSERT INTO "geodetic_crs" VALUES('IGNF','%s','%s',NULL,NULL,'geographic 2D','EPSG',%s,'IGNF','%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), cs_code, datum_code)
- all_sql.append(sql)
-
- key = { 'a' : d['a'], 'rf' : d['rf'], 'towgs84' : d['towgs84'], 'pm': pm }
- if "+towgs84=0.0000,0.0000,0.0000 +a=6378137.0000 +rf=298.2572221010000" in line or code == 'WGS84G':
- key['code'] = code
- key_geog_crs = json.dumps(key)
- assert key_geog_crs not in map_geog_crs, (line, map_geog_crs[key_geog_crs])
- map_geog_crs[ key_geog_crs ] = { 'code': code, 'title': d['title'] }
-
- if code == 'NTFP': # Grades
- assert cs_code == "'6425'" # Long Lat grad
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_NTFP_TO_IGNF_NTFG','other_transformation');"""
- #all_sql.append(sql)
-
- sql = """INSERT INTO "other_transformation" VALUES('IGNF','IGNF_NTFP_TO_IGNF_NTFG','Nouvelle Triangulation Francaise Paris grades to Nouvelle Triangulation Francaise Greenwich degres sexagesimaux',NULL,NULL,'EPSG','9601','Longitude rotation','IGNF','NTFP','IGNF','NTFG','EPSG','1262',0.0,'EPSG','8602','Longitude offset',2.5969213,'EPSG','9105',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);"""
- all_sql.append(sql)
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','concatenated_operation');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "concatenated_operation" VALUES('IGNF','IGNF_NTFP_TO_EPSG_4326','Nouvelle Triangulation Francaise Paris grades to WGS 84',NULL,NULL,'IGNF','NTFP','EPSG','4326','EPSG','1262',NULL,'IGNF','IGNF_NTFP_TO_IGNF_NTFG','IGNF','IGNF_NTFG_TO_EPSG_4326',NULL,NULL,0);"""
- all_sql.append(sql)
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','concatenated_operation');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "concatenated_operation" VALUES('IGNF','IGNF_NTFP_TO_EPSG_4326_GRID','Nouvelle Triangulation Francaise Paris grades to WGS 84 (2)',NULL,NULL,'IGNF','NTFP','EPSG','4326','EPSG','1262',NULL,'IGNF','IGNF_NTFP_TO_IGNF_NTFG','IGNF','IGNF_NTFG_TO_EPSG_4326_GRID',NULL,NULL,0);"""
- all_sql.append(sql)
-
- continue
-
- assert cs_code == "'6424'" # Long Lat deg
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','helmert_transformation');""" % (code)
- #all_sql.append(sql)
-
- towgs84 = d['towgs84'].split(',')
- assert len(towgs84) in (3, 7), towgs84
- x = towgs84[0]
- y = towgs84[1]
- z = towgs84[2]
- if len(towgs84) == 3:
- rx = 'NULL'
- ry = 'NULL'
- rz = 'NULL'
- s = 'NULL'
- r_uom_auth_name = 'NULL'
- r_uom_code = 'NULL'
- s_uom_auth_name = 'NULL'
- s_uom_code = 'NULL'
- method_code = "'9603'"
- method_name = "'Geocentric translations (geog2D domain)'"
-
- else:
- rx = towgs84[3]
- ry = towgs84[4]
- rz = towgs84[5]
- s = towgs84[6]
- r_uom_auth_name = "'EPSG'"
- r_uom_code = "'9104'"
- s_uom_auth_name = "'EPSG'"
- s_uom_code = "'9202'"
- method_code = "'9606'"
- method_name = "'Position Vector transformation (geog2D domain)'"
-
- sql = """INSERT INTO "helmert_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326','%s to WGS 84',NULL,NULL,'EPSG',%s,%s,'IGNF','%s','EPSG','4326','EPSG','1262',NULL,%s,%s,%s,'EPSG','9001',%s,%s,%s,%s,%s,%s,%s, %s,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), method_code, method_name, code, x, y, z, rx, ry, rz, r_uom_auth_name, r_uom_code, s, s_uom_auth_name, s_uom_code)
- all_sql.append(sql)
-
- if 'nadgrids' in d and d['nadgrids'] == 'ntf_r93.gsb,null':
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','grid_transformation');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "grid_transformation" VALUES('IGNF','IGNF_%s_TO_EPSG_4326_GRID','%s to WGS 84 (2)',NULL,NULL,'EPSG','9615','NTv2','IGNF','%s','EPSG','4326','EPSG','1262',NULL,'EPSG','8656','Latitude and longitude difference file','ntf_r93.gsb',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'tmerc':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- assert 'k_0' in d
- assert 'lat_0' in d
- assert 'lon_0' in d
- assert 'units' in d and d['units'] == 'm'
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9807','Transverse Mercator','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0'])
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'laea':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- assert 'lat_0' in d
- assert 'lon_0' in d
- assert 'units' in d and d['units'] == 'm'
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9820','Lambert Azimuthal Equal Area','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['x_0'], d['y_0'])
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'lcc':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- assert 'lat_0' in d
- assert 'lat_1' in d
- assert 'k_0' in d or 'lat_2' in d, line
- assert 'lon_0' in d
- assert 'units' in d and d['units'] == 'm'
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- if 'lat_2' in d:
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9802','Lambert Conic Conformal (2SP)','EPSG','8821','Latitude of false origin',%s,'EPSG','9102','EPSG','8822','Longitude of false origin',%s,'EPSG','9102','EPSG','8823','Latitude of 1st standard parallel',%s,'EPSG','9102','EPSG','8824','Latitude of 2nd standard parallel',%s,'EPSG','9102','EPSG','8826','Easting at false origin',%s,'EPSG','9001','EPSG','8827','Northing at false origin',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['lat_1'], d['lat_2'], d['x_0'], d['y_0'])
- else:
- assert d['lat_0'] == d['lat_1'], line
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9801','Lambert Conic Conformal (1SP)','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0'])
-
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'eqc':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d, line
- assert 'y_0' in d, line
- assert 'lat_0' in d, line
- assert 'lat_ts' in d, line
- assert 'lon_0' in d, line
- assert 'units' in d and d['units'] == 'm', line
- assert float(d['lat_0']) == 0, line
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','1028','Equidistant Cylindrical','EPSG','8823','Latitude of 1st standard parallel',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_ts'], d['lon_0'], d['x_0'], d['y_0'])
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'gstmerc':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- assert 'k_0' in d
- assert 'lat_0' in d
- assert 'lon_0' in d
- assert 'units' in d and d['units'] == 'm'
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262',NULL,NULL,'Gauss Schreiber Transverse Mercator','EPSG','8801','Latitude of natural origin',%s,'EPSG','9102','EPSG','8802','Longitude of natural origin',%s,'EPSG','9102','EPSG','8805','Scale factor at natural origin',%s,'EPSG','9201','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_0'], d['lon_0'], d['k_0'], d['x_0'], d['y_0'])
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'stere':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- if 'k' in d or 'k_0' in d:
- print('k/k_0 ignored for ' + line)
- assert 'lat_0' in d
- assert float(d['lat_0']) == -90, line
- assert 'lat_ts' in d
- assert 'lon_0' in d
- assert float(d['lon_0']) == 140, line
- assert 'units' in d and d['units'] == 'm'
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262','EPSG','9829','Polar Stereographic (variant B)','EPSG','8832','Latitude of standard parallel',%s,'EPSG','9102','EPSG','8833','Longitude of origin',%s,'EPSG','9102','EPSG','8806','False easting',%s,'EPSG','9001','EPSG','8807','False northing',%s,'EPSG','9001',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']), d['lat_ts'], d['lon_0'], d['x_0'], d['y_0'])
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- # Hardcoding 1025 for coordinate system since the only instance uses it
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','1025','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- elif proj == 'mill':
-
- geogcrs_code = find_geogcrs_code(line,d)
-
- assert 'x_0' in d
- assert 'y_0' in d
- assert 'lon_0' in d
- assert 'units' in d and d['units'] == 'm'
- assert float(d['x_0']) == 0, d
- assert float(d['y_0']) == 0, d
- assert float(d['lon_0']) == 0, d
-
- #sql = """INSERT INTO "coordinate_operation" VALUES('IGNF','CONV_%s','conversion');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "conversion" VALUES('IGNF','CONV_%s','Conversion for %s',NULL,NULL,'EPSG','1262',NULL,NULL,'PROJ mill',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0);""" % (code, escape_literal(d['title']))
- all_sql.append(sql)
-
- #sql = """INSERT INTO "crs" VALUES('IGNF','%s','projected');""" % (code)
- #all_sql.append(sql)
-
- sql = """INSERT INTO "projected_crs" VALUES('IGNF','%s','%s',NULL,NULL,'EPSG','4499','IGNF','%s','IGNF','CONV_%s','EPSG','1262',NULL,0);""" % (code, escape_literal(d['title']), geogcrs_code, code)
- all_sql.append(sql)
-
- all_sql.append('')
-
- else:
- assert False, line
-
-
-all_sql.append("""INSERT INTO grid_alternatives(original_grid_name,
- proj_grid_name,
- proj_grid_format,
- proj_method,
- inverse_direction,
- package_name,
- url, direct_download, open_license, directory)
- VALUES ('ntf_r93.gsb', -- as referenced by the IGNF registry
- 'ntf_r93.gsb',
- 'NTv2',
- 'hgridshift',
- 0,
- 'proj-datumgrid',
- NULL, NULL, NULL, NULL);
-""")
-
-#for k in map_geog_crs:
-# print k, map_geog_crs[k]
-
-script_dir_name = os.path.dirname(os.path.realpath(__file__))
-sql_dir_name = os.path.join(os.path.dirname(script_dir_name), 'data', 'sql')
-
-f = open(os.path.join(sql_dir_name, 'ignf') + '.sql', 'wb')
-f.write("--- This file has been generated by scripts/build_db_create_ignf.py from the PROJ4 IGNF definition file. DO NOT EDIT !\n\n".encode('UTF-8'))
-for sql in all_sql:
- f.write((sql + '\n').encode('UTF-8'))
-f.close()
-
diff --git a/scripts/build_db_from_esri.py b/scripts/build_db_from_esri.py
index 2e6f55ec..b55a1411 100755
--- a/scripts/build_db_from_esri.py
+++ b/scripts/build_db_from_esri.py
@@ -80,8 +80,9 @@ VALUES
('c1hpgn', 'us_noaa_c1hpgn.tif', 'c1hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c1hpgn.tif', 1, 1, NULL),
('c2hpgn', 'us_noaa_c2hpgn.tif', 'c2hpgn.gsb', 'GTiff', 'hgridshift', 0, NULL, 'https://cdn.proj.org/us_noaa_c2hpgn.tif', 1, 1, NULL),
('spain/100800401','es_cat_icgc_100800401.tif','100800401.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_cat_icgc_100800401.tif',1,1,NULL),
-('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL) -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage."
-;
+('australia/QLD_0900','au_icsm_National_84_02_07_01.tif','National_84_02_07_01.gsb','GTiff','hgridshift',0,NULL,'https://cdn.proj.org/au_icsm_National_84_02_07_01.tif',1,1,NULL), -- From https://www.dnrme.qld.gov.au/__data/assets/pdf_file/0006/105765/gday-21-user-guide.pdf: "Note that the Queensland grid QLD_0900.gsb produces identical results to the National AGD84 grid for the equivalent coverage."
+('spain/PENR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL),
+('spain/BALR2009','es_ign_SPED2ETV2.tif',NULL,'GTiff','hgridshift',0,NULL,'https://cdn.proj.org/es_ign_SPED2ETV2.tif',1,1,NULL);
-- 'france/RGNC1991_IGN72GrandeTerre' : we have a 3D geocentric corresponding one: no need for mapping
-- 'france/RGNC1991_NEA74Noumea' : we have a 3D geocentric corresponding one: no need for mapping
"""
diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh
index 1cfd61b5..4e76db94 100755
--- a/scripts/cppcheck.sh
+++ b/scripts/cppcheck.sh
@@ -22,7 +22,7 @@ for dirname in ${TOPDIR}/src; do
echo "Running cppcheck on $dirname... (can be long)"
if ! cppcheck --inline-suppr --template='{file}:{line},{severity},{id},{message}' \
--enable=all --inconclusive --std=posix \
- -DCPPCHECK -D__cplusplus=201103L -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H -DNAN \
+ -DCPPCHECK -D__cplusplus=201103L -DNAN \
-I${TOPDIR}/src -I${TOPDIR}/include \
"$dirname" \
-j 8 >>${LOG_FILE} 2>&1 ; then
diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt
index 8db49a95..167b8a27 100644
--- a/scripts/reference_exported_symbols.txt
+++ b/scripts/reference_exported_symbols.txt
@@ -284,8 +284,8 @@ osgeo::proj::datum::VerticalReferenceFrame::create(osgeo::proj::util::PropertyMa
osgeo::proj::datum::VerticalReferenceFrame::realizationMethod() const
osgeo::proj::datum::VerticalReferenceFrame::~VerticalReferenceFrame()
osgeo::proj::File::~File()
-osgeo::proj::FileManager::exists(projCtx_t*, char const*)
-osgeo::proj::FileManager::open(projCtx_t*, char const*, osgeo::proj::FileAccess)
+osgeo::proj::FileManager::exists(pj_ctx*, char const*)
+osgeo::proj::FileManager::open(pj_ctx*, char const*, osgeo::proj::FileAccess)
osgeo::proj::File::read_line(unsigned long, bool&, bool&)
osgeo::proj::GenericShiftGrid::~GenericShiftGrid()
osgeo::proj::GenericShiftGrid::GenericShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
@@ -293,9 +293,9 @@ osgeo::proj::GenericShiftGrid::gridAt(double, double) const
osgeo::proj::GenericShiftGridSet::~GenericShiftGridSet()
osgeo::proj::GenericShiftGridSet::GenericShiftGridSet()
osgeo::proj::GenericShiftGridSet::gridAt(double, double) const
-osgeo::proj::GenericShiftGridSet::open(projCtx_t*, std::string const&)
-osgeo::proj::GenericShiftGridSet::reassign_context(projCtx_t*)
-osgeo::proj::GenericShiftGridSet::reopen(projCtx_t*)
+osgeo::proj::GenericShiftGridSet::open(pj_ctx*, std::string const&)
+osgeo::proj::GenericShiftGridSet::reassign_context(pj_ctx*)
+osgeo::proj::GenericShiftGridSet::reopen(pj_ctx*)
osgeo::proj::Grid::~Grid()
osgeo::proj::Grid::Grid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
osgeo::proj::HorizontalShiftGrid::gridAt(double, double) const
@@ -304,9 +304,9 @@ osgeo::proj::HorizontalShiftGrid::HorizontalShiftGrid(std::string const&, int, i
osgeo::proj::HorizontalShiftGridSet::gridAt(double, double) const
osgeo::proj::HorizontalShiftGridSet::~HorizontalShiftGridSet()
osgeo::proj::HorizontalShiftGridSet::HorizontalShiftGridSet()
-osgeo::proj::HorizontalShiftGridSet::open(projCtx_t*, std::string const&)
-osgeo::proj::HorizontalShiftGridSet::reassign_context(projCtx_t*)
-osgeo::proj::HorizontalShiftGridSet::reopen(projCtx_t*)
+osgeo::proj::HorizontalShiftGridSet::open(pj_ctx*, std::string const&)
+osgeo::proj::HorizontalShiftGridSet::reassign_context(pj_ctx*)
+osgeo::proj::HorizontalShiftGridSet::reopen(pj_ctx*)
osgeo::proj::internal::ci_equal(std::string const&, char const*)
osgeo::proj::internal::ci_equal(std::string const&, std::string const&)
osgeo::proj::internal::ci_find(std::string const&, char const*)
@@ -351,9 +351,9 @@ osgeo::proj::io::AuthorityFactory::getUnitList() const
osgeo::proj::io::AuthorityFactory::identifyBodyFromSemiMajorAxis(double, double) const
osgeo::proj::io::AuthorityFactory::listAreaOfUseFromName(std::string const&, bool) const
osgeo::proj::io::AuthorityFactory::UnitInfo::UnitInfo()
-osgeo::proj::io::createFromUserInput(std::string const&, projCtx_t*)
+osgeo::proj::io::createFromUserInput(std::string const&, pj_ctx*)
osgeo::proj::io::createFromUserInput(std::string const&, std::shared_ptr<osgeo::proj::io::DatabaseContext> const&, bool)
-osgeo::proj::io::DatabaseContext::create(std::string const&, std::vector<std::string, std::allocator<std::string> > const&, projCtx_t*)
+osgeo::proj::io::DatabaseContext::create(std::string const&, std::vector<std::string, std::allocator<std::string> > const&, pj_ctx*)
osgeo::proj::io::DatabaseContext::create(void*)
osgeo::proj::io::DatabaseContext::~DatabaseContext()
osgeo::proj::io::DatabaseContext::getAuthorities() const
@@ -413,7 +413,7 @@ osgeo::proj::io::PROJStringFormatter::setUseApproxTMerc(bool)
osgeo::proj::io::PROJStringFormatter::startInversion()
osgeo::proj::io::PROJStringFormatter::stopInversion()
osgeo::proj::io::PROJStringFormatter::toString() const
-osgeo::proj::io::PROJStringParser::attachContext(projCtx_t*)
+osgeo::proj::io::PROJStringParser::attachContext(pj_ctx*)
osgeo::proj::io::PROJStringParser::attachDatabaseContext(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&)
osgeo::proj::io::PROJStringParser::createFromPROJString(std::string const&)
osgeo::proj::io::PROJStringParser::~PROJStringParser()
@@ -422,7 +422,9 @@ osgeo::proj::io::PROJStringParser::setUsePROJ4InitRules(bool)
osgeo::proj::io::PROJStringParser::warningList() const
osgeo::proj::io::WKTFormatter::create(dropbox::oxygen::nn<std::unique_ptr<osgeo::proj::io::WKTFormatter, std::default_delete<osgeo::proj::io::WKTFormatter> > > const&)
osgeo::proj::io::WKTFormatter::create(osgeo::proj::io::WKTFormatter::Convention, std::shared_ptr<osgeo::proj::io::DatabaseContext>)
+osgeo::proj::io::WKTFormatter::isAllowedEllipsoidalHeightAsVerticalCRS() const
osgeo::proj::io::WKTFormatter::isStrict() const
+osgeo::proj::io::WKTFormatter::setAllowEllipsoidalHeightAsVerticalCRS(bool)
osgeo::proj::io::WKTFormatter::setIndentationWidth(int)
osgeo::proj::io::WKTFormatter::setMultiLine(bool)
osgeo::proj::io::WKTFormatter::setOutputAxis(osgeo::proj::io::WKTFormatter::OutputAxisRule)
@@ -734,90 +736,34 @@ osgeo::proj::util::UnsupportedOperationException::~UnsupportedOperationException
osgeo::proj::util::UnsupportedOperationException::UnsupportedOperationException(osgeo::proj::util::UnsupportedOperationException const&)
osgeo::proj::VerticalShiftGrid::gridAt(double, double) const
osgeo::proj::VerticalShiftGridSet::gridAt(double, double) const
-osgeo::proj::VerticalShiftGridSet::open(projCtx_t*, std::string const&)
-osgeo::proj::VerticalShiftGridSet::reassign_context(projCtx_t*)
-osgeo::proj::VerticalShiftGridSet::reopen(projCtx_t*)
+osgeo::proj::VerticalShiftGridSet::open(pj_ctx*, std::string const&)
+osgeo::proj::VerticalShiftGridSet::reassign_context(pj_ctx*)
+osgeo::proj::VerticalShiftGridSet::reopen(pj_ctx*)
osgeo::proj::VerticalShiftGridSet::~VerticalShiftGridSet()
osgeo::proj::VerticalShiftGridSet::VerticalShiftGridSet()
osgeo::proj::VerticalShiftGrid::~VerticalShiftGrid()
osgeo::proj::VerticalShiftGrid::VerticalShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
-pj_acquire_lock
pj_add_type_crs_if_needed(std::string const&)
-pj_apply_gridshift
pj_approx_2D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD)
pj_approx_3D_trans(PJconsts*, PJ_DIRECTION, PJ_COORD)
pj_atof(char const*)
-pj_calloc
pj_chomp(char*)
-pj_cleanup_lock
-pj_clear_initcache
-pj_compare_datums
-pj_context_get_grid_cache_filename(projCtx_t*)
-pj_context_set_user_writable_directory(projCtx_t*, std::string const&)
-pj_ctx_alloc
-pj_ctx_fclose
-pj_ctx_fgets
-pj_ctx_fopen
-pj_ctx_fread
-pj_ctx_free
-pj_ctx_fseek
-pj_ctx_ftell
-pj_ctx_get_app_data
-pj_ctx_get_errno
-pj_ctx_get_fileapi
-pj_ctx_set_app_data
-pj_ctx_set_debug
-pj_ctx_set_errno
-pj_ctx_set_fileapi
-pj_ctx_set_logger
-pj_dalloc
-pj_datum_transform
-pj_dealloc
-pj_deallocate_grids
-pj_ell_set(projCtx_t*, ARG_list*, double*, double*)
-pj_find_file
-pj_free
-pj_fwd
-pj_fwd3d
-pj_geocentric_to_geodetic
-pj_geodetic_to_geocentric
-pj_get_ctx
+pj_context_get_grid_cache_filename(pj_ctx*)
+pj_context_set_user_writable_directory(pj_ctx*, std::string const&)
+pj_ell_set(pj_ctx*, ARG_list*, double*, double*)
+pj_fwd(PJ_LP, PJconsts*)
pj_get_datums_ref()
-pj_get_def
-pj_get_default_ctx
-pj_get_default_fileapi
-pj_get_default_searchpaths(projCtx_t*)
-pj_get_errno_ref
-pj_get_relative_share_proj(projCtx_t*)
-pj_get_release
-pj_get_spheroid_defn
-pj_has_inverse
-pj_init
-pj_init_ctx
-pj_init_plus
-pj_init_plus_ctx
-pj_inv
-pj_inv3d
-pj_is_geocent
-pj_is_latlong
-pj_latlong_from_proj
-pj_log
-pj_malloc
+pj_get_default_ctx()
+pj_get_default_searchpaths(pj_ctx*)
+pj_get_relative_share_proj(pj_ctx*)
+pj_get_release()
+pj_inv(PJ_XY, PJconsts*)
pj_mkparam(char const*)
-pj_open_lib
pj_param_exists(ARG_list*, char const*)
-pj_param(projCtx_t*, ARG_list*, char const*)
-pj_phi2(projCtx_t*, double, double)
-pj_pr_list
-pj_release_lock
-pj_set_ctx
-pj_set_finder
-pj_set_searchpath
+pj_param(pj_ctx*, ARG_list*, char const*)
+pj_phi2(pj_ctx*, double, double)
+pj_pr_list(PJconsts*)
pj_shrink(char*)
-pj_stderr_logger
-pj_strdup
-pj_strerrno
-pj_transform
proj_alter_id
proj_alter_name
proj_angular_input
@@ -852,7 +798,7 @@ proj_context_set_enable_network
proj_context_set_fileapi
proj_context_set_file_finder
proj_context_set_network_callbacks
-proj_context_set(PJconsts*, projCtx_t*)
+proj_context_set(PJconsts*, pj_ctx*)
proj_context_set_search_paths
proj_context_set_sqlite3_vfs_name
proj_context_set_url_endpoint
diff --git a/src/4D_api.cpp b/src/4D_api.cpp
index 86c0e071..d6eb901d 100644
--- a/src/4D_api.cpp
+++ b/src/4D_api.cpp
@@ -778,14 +778,14 @@ PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition) {
argc = pj_trim_argc (args);
if (argc==0) {
- pj_dealloc (args);
+ free (args);
proj_context_errno_set(ctx, PJD_ERR_NO_ARGS);
return nullptr;
}
argv = pj_trim_argv (argc, args);
if (!argv) {
- pj_dealloc(args);
+ free(args);
proj_context_errno_set(ctx, ENOMEM);
return nullptr;
}
@@ -795,8 +795,8 @@ PJ *pj_create_internal (PJ_CONTEXT *ctx, const char *definition) {
allow_init_epsg = proj_context_get_use_proj4_init_rules(ctx, FALSE);
P = pj_init_ctx_with_allow_init_epsg (ctx, (int) argc, argv, allow_init_epsg);
- pj_dealloc (argv);
- pj_dealloc (args);
+ free (argv);
+ free (args);
/* Support cs2cs-style modifiers */
ret = cs2cs_emulation_setup (P);
@@ -834,7 +834,7 @@ indicator, as in {"+proj=utm", "+zone=32"}, or leave it out, as in {"proj=utm",
P = proj_create (ctx, c);
- pj_dealloc ((char *) c);
+ free ((char *) c);
return P;
}
@@ -862,13 +862,13 @@ Same as proj_create_argv() but calls pj_create_internal() instead of proj_create
P = pj_create_internal (ctx, c);
- pj_dealloc ((char *) c);
+ free ((char *) c);
return P;
}
/** Create an area of use */
PJ_AREA * proj_area_create(void) {
- return static_cast<PJ_AREA*>(pj_calloc(1, sizeof(PJ_AREA)));
+ return static_cast<PJ_AREA*>(calloc(1, sizeof(PJ_AREA)));
}
/** Assign a bounding box to an area of use. */
@@ -886,7 +886,7 @@ void proj_area_set_bbox(PJ_AREA *area,
/** Free an area of use */
void proj_area_destroy(PJ_AREA* area) {
- pj_dealloc(area);
+ free(area);
}
/************************************************************************/
@@ -1260,8 +1260,20 @@ std::vector<CoordOperation> pj_create_prepared_operations(PJ_CONTEXT *ctx,
}
}
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+static const char *getOptionValue(const char *option,
+ const char *keyWithEqual) noexcept {
+ if (ci_starts_with(option, keyWithEqual)) {
+ return option + strlen(keyWithEqual);
+ }
+ return nullptr;
+}
+//! @endcond
+
/*****************************************************************************/
-PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, const PJ *target_crs, PJ_AREA *area, const char* const *) {
+PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, const PJ *target_crs, PJ_AREA *area, const char* const * options) {
/******************************************************************************
Create a transformation pipeline between two known coordinate reference
systems.
@@ -1273,7 +1285,20 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons
ctx = pj_get_default_ctx();
}
- auto operation_ctx = proj_create_operation_factory_context(ctx, nullptr);
+ const char* authority = nullptr;
+ for (auto iter = options; iter && iter[0]; ++iter) {
+ const char *value;
+ if ((value = getOptionValue(*iter, "AUTHORITY="))) {
+ authority = value;
+ } else {
+ std::string msg("Unknown option :");
+ msg += *iter;
+ ctx->logger(ctx->logger_app_data, PJ_LOG_ERROR, msg.c_str());
+ return nullptr;
+ }
+ }
+
+ auto operation_ctx = proj_create_operation_factory_context(ctx, authority);
if( !operation_ctx ) {
return nullptr;
}
@@ -1287,9 +1312,11 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons
area->east_lon_degree,
area->north_lat_degree);
}
+ else {
+ proj_operation_factory_context_set_spatial_criterion(
+ ctx, operation_ctx, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);
+ }
- proj_operation_factory_context_set_spatial_criterion(
- ctx, operation_ctx, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);
proj_operation_factory_context_set_grid_availability_use(
ctx, operation_ctx,
proj_context_is_network_enabled(ctx) ?
@@ -1353,17 +1380,13 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons
return P;
}
-PJ *proj_destroy (PJ *P) {
- pj_free (P);
- return nullptr;
-}
/*****************************************************************************/
int proj_errno (const PJ *P) {
/******************************************************************************
Read an error level from the context of a PJ.
******************************************************************************/
- return pj_ctx_get_errno (pj_get_ctx ((PJ *) P));
+ return proj_context_errno (pj_get_ctx ((PJ *) P));
}
/*****************************************************************************/
@@ -1374,7 +1397,7 @@ int proj_context_errno (PJ_CONTEXT *ctx) {
******************************************************************************/
if (nullptr==ctx)
ctx = pj_get_default_ctx();
- return pj_ctx_get_errno (ctx);
+ return ctx->last_errno;
}
/*****************************************************************************/
@@ -1389,6 +1412,7 @@ int proj_errno_set (const PJ *P, int err) {
/* For P==0 err goes to the default context */
proj_context_errno_set (pj_get_ctx ((PJ *) P), err);
errno = err;
+
return err;
}
@@ -1439,16 +1463,15 @@ int proj_errno_reset (const PJ *P) {
int last_errno;
last_errno = proj_errno (P);
- pj_ctx_set_errno (pj_get_ctx ((PJ *) P), 0);
+ proj_context_errno_set (pj_get_ctx ((PJ *) P), 0);
errno = 0;
- pj_errno = 0;
return last_errno;
}
/* Create a new context based on the default context */
PJ_CONTEXT *proj_context_create (void) {
- return pj_ctx_alloc ();
+ return new (std::nothrow) pj_ctx(*pj_get_default_ctx());
}
@@ -1460,7 +1483,7 @@ PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx) {
if (pj_get_default_ctx ()==ctx)
return nullptr;
- pj_ctx_free (ctx);
+ delete ctx;
return nullptr;
}
@@ -1499,15 +1522,15 @@ static char *path_append (char *buf, const char *app, size_t *buf_size) {
/* "pj_realloc", so to speak */
if (*buf_size < len) {
- p = static_cast<char*>(pj_calloc (2 * len, sizeof (char)));
+ p = static_cast<char*>(calloc (2 * len, sizeof (char)));
if (nullptr==p) {
- pj_dealloc (buf);
+ free (buf);
return nullptr;
}
*buf_size = 2 * len;
if (buf != nullptr)
strcpy (p, buf);
- pj_dealloc (buf);
+ free (buf);
buf = p;
}
assert(buf);
@@ -1560,7 +1583,7 @@ PJ_INFO proj_info (void) {
}
}
- pj_dalloc(const_cast<char*>(info.searchpath));
+ free(const_cast<char*>(info.searchpath));
info.searchpath = buf ? buf : empty;
info.paths = ctx ? ctx->c_compat_paths : nullptr;
@@ -1635,7 +1658,7 @@ PJ_PROJ_INFO proj_pj_info(PJ *P) {
pjinfo.definition = empty;
else
pjinfo.definition = pj_shrink (def);
- /* Make pj_free clean this up eventually */
+ /* Make proj_destroy clean this up eventually */
P->def_full = def;
pjinfo.has_inverse = pj_has_inverse(P);
@@ -1746,7 +1769,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){
if( strcmp(initname, "epsg") == 0 || strcmp(initname, "EPSG") == 0 ) {
const char* val;
- pj_ctx_set_errno( ctx, 0 );
+ proj_context_errno_set( ctx, 0 );
strncpy (ininfo.name, initname, sizeof(ininfo.name) - 1);
strcpy(ininfo.origin, "EPSG");
@@ -1764,7 +1787,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){
if( strcmp(initname, "IGNF") == 0 ) {
const char* val;
- pj_ctx_set_errno( ctx, 0 );
+ proj_context_errno_set( ctx, 0 );
strncpy (ininfo.name, initname, sizeof(ininfo.name) - 1);
strcpy(ininfo.origin, "IGNF");
@@ -1809,7 +1832,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){
for ( ; start; start = next) {
next = start->next;
- pj_dalloc(start);
+ free(start);
}
return ininfo;
diff --git a/src/Makefile.am b/src/Makefile.am
index 5b36c8bd..83ee4adc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
AM_CFLAGS = @C_WFLAGS@
-EXTRA_PROGRAMS = multistresstest test228
+EXTRA_PROGRAMS = multistresstest
TESTS = geodtest
check_PROGRAMS = geodtest
@@ -9,7 +9,7 @@ AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \
-DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@ @TIFF_CFLAGS@ @TIFF_ENABLED_FLAGS@ @CURL_CFLAGS@ @CURL_ENABLED_FLAGS@
AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@
-include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesic.h \
+include_HEADERS = proj.h proj_experimental.h proj_constants.h geodesic.h \
proj_symbol_rename.h
EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \
@@ -36,7 +36,6 @@ bin_PROGRAMS = proj geod cs2cs gie cct projinfo $(PROJSYNC_BIN)
gie_SOURCES = apps/gie.cpp apps/proj_strtod.cpp apps/proj_strtod.h apps/optargpm.h
multistresstest_SOURCES = tests/multistresstest.cpp
-test228_SOURCES = tests/test228.cpp
geodtest_SOURCES = tests/geodtest.cpp
cct_LDADD = libproj.la
@@ -47,7 +46,6 @@ projinfo_LDADD = libproj.la
gie_LDADD = libproj.la
multistresstest_LDADD = libproj.la @THREAD_LIB@
-test228_LDADD = libproj.la @THREAD_LIB@
geodtest_LDADD = libproj.la
lib_LTLIBRARIES = libproj.la
@@ -187,6 +185,7 @@ libproj_la_SOURCES = \
conversions/geoc.cpp \
conversions/geocent.cpp \
conversions/noop.cpp \
+ conversions/topocentric.cpp \
conversions/set.cpp \
conversions/unitconvert.cpp \
\
@@ -209,19 +208,17 @@ libproj_la_SOURCES = \
\
aasincos.cpp adjlon.cpp \
dmstor.cpp auth.cpp \
- deriv.cpp ell_set.cpp ellps.cpp errno.cpp \
+ deriv.cpp ell_set.cpp ellps.cpp \
factors.cpp fwd.cpp init.cpp inv.cpp \
list.cpp malloc.cpp mlfn.cpp mlfn.hpp msfn.cpp proj_mdist.cpp \
param.cpp phi2.cpp pr_list.cpp \
qsfn.cpp strerrno.cpp \
tsfn.cpp units.cpp ctx.cpp log.cpp zpoly1.cpp rtodms.cpp \
release.cpp gauss.cpp \
- fileapi.cpp \
generic_inverse.cpp \
quadtree.hpp \
\
- datums.cpp datum_set.cpp transform.cpp \
- utils.cpp \
+ datums.cpp datum_set.cpp \
mutex.cpp initcache.cpp geodesic.c \
strtod.cpp \
\
diff --git a/src/aasincos.cpp b/src/aasincos.cpp
index 398a8cfc..c4314c67 100644
--- a/src/aasincos.cpp
+++ b/src/aasincos.cpp
@@ -9,24 +9,24 @@
#define ATOL 1e-50
double
-aasin(projCtx ctx,double v) {
+aasin(PJ_CONTEXT *ctx,double v) {
double av;
if ((av = fabs(v)) >= 1.) {
if (av > ONE_TOL)
- pj_ctx_set_errno( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE );
+ proj_context_errno_set( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE );
return (v < 0. ? -M_HALFPI : M_HALFPI);
}
return asin(v);
}
double
-aacos(projCtx ctx, double v) {
+aacos(PJ_CONTEXT *ctx, double v) {
double av;
if ((av = fabs(v)) >= 1.) {
if (av > ONE_TOL)
- pj_ctx_set_errno( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE );
+ proj_context_errno_set( ctx, PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE );
return (v < 0. ? M_PI : 0.);
}
return acos(v);
diff --git a/src/apps/cct.cpp b/src/apps/cct.cpp
index f7413872..4f21f10a 100644
--- a/src/apps/cct.cpp
+++ b/src/apps/cct.cpp
@@ -78,6 +78,9 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-10-26
#include <string.h>
#include <stdarg.h>
+#include <fstream> // std::ifstream
+#include <iostream>
+
#include "proj.h"
#include "proj_internal.h"
#include "proj_strtod.h"
@@ -193,9 +196,8 @@ static void print(PJ_LOG_LEVEL log_level, const char *fmt, ...) {
free( msg_buf );
}
-
int main(int argc, char **argv) {
- PJ *P;
+ PJ *P = nullptr;
PJ_COORD point;
PJ_PROJ_INFO info;
OPTARGS *o;
@@ -292,10 +294,73 @@ int main(int argc, char **argv) {
}
/* Setup transformation */
- P = proj_create_argv (nullptr, o->pargc, o->pargv);
- if ((nullptr==P) || (0==o->pargc)) {
+ if (o-> pargc == 0 && o->fargc > 0) {
+ std::string input(o->fargv[0]);
+
+ if (!input.empty() && input[0] == '@') {
+ std::ifstream fs;
+ auto filename = input.substr(1);
+ fs.open(filename, std::fstream::in | std::fstream::binary);
+ if (!fs.is_open()) {
+ std::cerr << "cannot open " << filename << std::endl;
+ std::exit(1);
+ }
+ input.clear();
+ while (!fs.eof()) {
+ char buffer[256];
+ fs.read(buffer, sizeof(buffer));
+ input.append(buffer, static_cast<size_t>(fs.gcount()));
+ if (input.size() > 100 * 1000) {
+ fs.close();
+ std::cerr << "too big file " << filename << std::endl;
+ std::exit(1);
+ }
+ }
+ fs.close();
+ }
+
+ /* Assume we got a auth:code combination */
+ auto n = input.find(":");
+ if (n > 0) {
+ std::string auth = input.substr(0,n);
+ std::string code = input.substr(n+1, input.length());
+ // Check that the authority matches one of the known ones
+ auto authorityList = proj_get_authorities_from_database(nullptr);
+ if( authorityList )
+ {
+ for( auto iter = authorityList; *iter; iter++ )
+ {
+ if( *iter == auth ) {
+ P = proj_create_from_database(
+ nullptr, auth.c_str(), code.c_str(),
+ PJ_CATEGORY_COORDINATE_OPERATION, 0, nullptr);
+ break;
+ }
+ }
+ proj_string_list_destroy(authorityList);
+ }
+ }
+ if( P == nullptr ) {
+ /* if we didn't get a auth:code combo we try to see if the input matches */
+ /* anything else */
+ P = proj_create(nullptr, input.c_str());
+ }
+
+ /* If instantiating operation without +-options optargpm thinks the input is */
+ /* a file, hence we move all o->fargv entries one place closer to the start */
+ /* of the array. This effectively overwrites the input and only leaves a list */
+ /* of files in o->fargv. */
+ o->fargc = o->fargc-1;
+ for (int j=0; j < o->fargc; j++) {
+ o->fargv[j] = o->fargv[j+1];
+ }
+ } else {
+ P = proj_create_argv (nullptr, o->pargc, o->pargv);
+ }
+
+ if (nullptr==P) {
print (PJ_LOG_ERROR, "%s: Bad transformation arguments - (%s)\n '%s -h' for help",
- o->progname, pj_strerrno (proj_errno(P)), o->progname);
+ o->progname, proj_errno_string (proj_errno(P)), o->progname);
free (o);
if (stdout != fout)
fclose (fout);
@@ -322,7 +387,7 @@ int main(int argc, char **argv) {
buf = static_cast<char*>(calloc (1, 10000));
if (nullptr==buf) {
print (PJ_LOG_ERROR, "%s: Out of memory", o->progname);
- pj_free (P);
+ proj_destroy (P);
free (o);
if (stdout != fout)
fclose (fout);
@@ -370,7 +435,7 @@ int main(int argc, char **argv) {
if (HUGE_VAL==point.xyzt.x) {
/* transformation error */
print (PJ_LOG_NONE, "# Record %d TRANSFORMATION ERROR: %s (%s)",
- (int) o->record_index, buf, pj_strerrno (proj_errno(P)));
+ (int) o->record_index, buf, proj_errno_string (proj_errno(P)));
proj_errno_restore (P, err);
continue;
}
@@ -385,12 +450,22 @@ int main(int argc, char **argv) {
colmax = MAX(colmax, columns_xyzt[i]);
comment = column(buf, colmax+1);
}
+ /* remove the line feed from comment, as logger() above, invoked
+ by print() below (output), will add one */
+ size_t len = strlen(comment);
+ if (len >= 1)
+ comment[len - 1] = '\0';
comment_delimiter = (comment && *comment) ? whitespace : blank_comment;
/* Time to print the result */
- if (proj_angular_output (P, direction)) {
- point.lpzt.lam = proj_todeg (point.lpzt.lam);
- point.lpzt.phi = proj_todeg (point.lpzt.phi);
+ /* use same arguments to printf format string for both radians and
+ degrees; convert radians to degrees before printing */
+ if (proj_angular_output (P, direction) ||
+ proj_degree_output (P, direction)) {
+ if (proj_angular_output (P, direction)) {
+ point.lpzt.lam = proj_todeg (point.lpzt.lam);
+ point.lpzt.phi = proj_todeg (point.lpzt.phi);
+ }
print (PJ_LOG_NONE, "%14.*f %14.*f %12.*f %12.4f%s%s",
decimals_angles, point.xyzt.x,
decimals_angles, point.xyzt.y,
@@ -405,6 +480,8 @@ int main(int argc, char **argv) {
decimals_distances, point.xyzt.z,
point.xyzt.t, comment_delimiter, comment
);
+ if( fout == stdout )
+ fflush(stdout);
}
proj_destroy(P);
diff --git a/src/apps/cs2cs.cpp b/src/apps/cs2cs.cpp
index 58c164c9..409a5ef3 100644
--- a/src/apps/cs2cs.cpp
+++ b/src/apps/cs2cs.cpp
@@ -36,8 +36,13 @@
#include <string.h>
#include <cassert>
+#include <iostream>
#include <string>
+#include <proj/io.hpp>
+#include <proj/metadata.hpp>
+#include <proj/util.hpp>
+
#include <proj/internal/internal.hpp>
// PROJ include order is sensitive
@@ -70,12 +75,19 @@ static const char *oform =
static char oform_buffer[16]; /* buffer for oform when using -d */
static const char *oterr = "*\t*"; /* output line for unprojectable input */
static const char *usage =
- "%s\nusage: %s [-dDeEfIlrstvwW [args]] [+opt[=arg] ...]\n"
- " [+to +opt[=arg] ...] [file ...]\n";
+ "%s\nusage: %s [-dDeEfIlrstvwW [args]]\n"
+ " [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]\n"
+ " [--authority {name}]\n"
+ " [+opt[=arg] ...] [+to +opt[=arg] ...] [file ...]\n";
static double (*informat)(const char *,
char **); /* input data deformatter function */
+using namespace NS_PROJ::io;
+using namespace NS_PROJ::metadata;
+using namespace NS_PROJ::util;
+using namespace NS_PROJ::internal;
+
/************************************************************************/
/* process() */
/* */
@@ -217,6 +229,7 @@ static void process(FILE *fid)
printf("%s", s);
else
printf("\n");
+ fflush(stdout);
}
}
@@ -358,9 +371,57 @@ int main(int argc, char **argv) {
}
}
+ ExtentPtr bboxFilter;
+ std::string area;
+ const char* authority = nullptr;
+
/* process run line arguments */
while (--argc > 0) { /* collect run line arguments */
- if (**++argv == '-') {
+ ++argv;
+ if (strcmp(*argv, "--area") == 0 ) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --area");
+ std::exit(1);
+ }
+ area = *argv;
+ }
+ else if (strcmp(*argv, "--bbox") == 0) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --bbox");
+ std::exit(1);
+ }
+ auto bboxStr(*argv);
+ auto bbox(split(bboxStr, ','));
+ if (bbox.size() != 4) {
+ std::cerr << "Incorrect number of values for option --bbox: "
+ << bboxStr << std::endl;
+ std::exit(1);
+ }
+ try {
+ bboxFilter = Extent::createFromBBOX(
+ c_locale_stod(bbox[0]), c_locale_stod(bbox[1]),
+ c_locale_stod(bbox[2]), c_locale_stod(bbox[3]))
+ .as_nullable();
+ } catch (const std::exception &e) {
+ std::cerr << "Invalid value for option --bbox: " << bboxStr
+ << ", " << e.what() << std::endl;
+ std::exit(1);
+ }
+ }
+ else if (strcmp(*argv, "--authority") == 0 ) {
+ ++argv;
+ --argc;
+ if( argc == 0 ) {
+ emess(1, "missing argument for --authority");
+ std::exit(1);
+ }
+ authority = *argv;
+ }
+ else if (**argv == '-') {
for (arg = *argv;;) {
switch (*++arg) {
case '\0': /* position of "stdin" */
@@ -467,10 +528,23 @@ int main(int argc, char **argv) {
reverseout = 1;
continue;
case 'D': /* set debug level */
+ {
if (--argc <= 0)
goto noargument;
- pj_ctx_set_debug(pj_get_default_ctx(), atoi(*++argv));
+ int log_level = atoi(*++argv);
+ if (log_level <= 0) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_NONE);
+ } else if (log_level == 1) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_ERROR);
+ } else if (log_level == 2) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_DEBUG);
+ } else if (log_level == 3) {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_TRACE);
+ } else {
+ proj_log_level(pj_get_default_ctx(), PJ_LOG_TELL);
+ }
continue;
+ }
case 'd':
if (--argc <= 0)
goto noargument;
@@ -522,6 +596,102 @@ int main(int argc, char **argv) {
}
}
+ if (bboxFilter && !area.empty()) {
+ std::cerr << "ERROR: --bbox and --area are exclusive" << std::endl;
+ std::exit(1);
+ }
+
+ PJ_AREA* pj_area = nullptr;
+ if (!area.empty()) {
+
+ DatabaseContextPtr dbContext;
+ try {
+ dbContext =
+ DatabaseContext::create().as_nullable();
+ } catch (const std::exception &e) {
+ std::cerr << "ERROR: Cannot create database connection: "
+ << e.what() << std::endl;
+ std::exit(1);
+ }
+
+ // Process area of use
+ try {
+ if (area.find(' ') == std::string::npos &&
+ area.find(':') != std::string::npos) {
+ auto tokens = split(area, ':');
+ if (tokens.size() == 2) {
+ const std::string &areaAuth = tokens[0];
+ const std::string &areaCode = tokens[1];
+ bboxFilter = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), areaAuth)
+ ->createExtent(areaCode)
+ .as_nullable();
+ }
+ }
+ if (!bboxFilter) {
+ auto authFactory = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), std::string());
+ auto res = authFactory->listAreaOfUseFromName(area, false);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else {
+ res = authFactory->listAreaOfUseFromName(area, true);
+ if (res.size() == 1) {
+ bboxFilter =
+ AuthorityFactory::create(NN_NO_CHECK(dbContext),
+ res.front().first)
+ ->createExtent(res.front().second)
+ .as_nullable();
+ } else if (res.empty()) {
+ std::cerr << "No area of use matching provided name"
+ << std::endl;
+ std::exit(1);
+ } else {
+ std::cerr << "Several candidates area of use "
+ "matching provided name :"
+ << std::endl;
+ for (const auto &candidate : res) {
+ auto obj =
+ AuthorityFactory::create(
+ NN_NO_CHECK(dbContext), candidate.first)
+ ->createExtent(candidate.second);
+ std::cerr << " " << candidate.first << ":"
+ << candidate.second << " : "
+ << *obj->description() << std::endl;
+ }
+ std::exit(1);
+ }
+ }
+ }
+ } catch (const std::exception &e) {
+ std::cerr << "Area of use retrieval failed: " << e.what()
+ << std::endl;
+ std::exit(1);
+ }
+ }
+
+ if (bboxFilter) {
+ auto geogElts = bboxFilter->geographicElements();
+ if (geogElts.size() == 1)
+ {
+ auto bbox = std::dynamic_pointer_cast<GeographicBoundingBox>(
+ geogElts[0].as_nullable());
+ if (bbox)
+ {
+ pj_area = proj_area_create();
+ proj_area_set_bbox(pj_area,
+ bbox->westBoundLongitude(),
+ bbox->southBoundLatitude(),
+ bbox->eastBoundLongitude(),
+ bbox->northBoundLatitude());
+ }
+ }
+ }
+
/*
* If the user has requested inverse, then just reverse the
* coordinate systems.
@@ -602,15 +772,23 @@ int main(int argc, char **argv) {
}
}
+ std::string authorityOption; /* keep this variable in this outer scope ! */
+ const char* options[2] = { nullptr, nullptr };
+ if( authority ) {
+ authorityOption = "AUTHORITY=";
+ authorityOption += authority;
+ options[0] = authorityOption.data();
+ }
transformation = proj_create_crs_to_crs_from_pj(nullptr, src, dst,
- nullptr, nullptr);
+ pj_area, options);
proj_destroy(src);
proj_destroy(dst);
+ proj_area_destroy(pj_area);
if (!transformation) {
emess(3, "cannot initialize transformation\ncause: %s",
- pj_strerrno(pj_errno));
+ proj_errno_string(proj_context_errno(nullptr)));
}
if (use_env_locale) {
diff --git a/src/apps/emess.cpp b/src/apps/emess.cpp
index 53018ba8..5a50cd25 100644
--- a/src/apps/emess.cpp
+++ b/src/apps/emess.cpp
@@ -9,17 +9,13 @@
# endif
#endif
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "proj_api.h"
+#include "proj_internal.h"
#include "proj_config.h"
#define EMESS_ROUTINE
#include "emess.h"
diff --git a/src/apps/geod.cpp b/src/apps/geod.cpp
index 919430ca..35a8e826 100644
--- a/src/apps/geod.cpp
+++ b/src/apps/geod.cpp
@@ -124,6 +124,7 @@ process(FILE *fid) {
(void)fputs(rtodms(pline, al21, 0, 0), stdout);
}
(void)fputs(s, stdout);
+ fflush(stdout);
}
}
diff --git a/src/apps/geod_set.cpp b/src/apps/geod_set.cpp
index 603f0d95..d6516f22 100644
--- a/src/apps/geod_set.cpp
+++ b/src/apps/geod_set.cpp
@@ -75,6 +75,6 @@ geod_set(int argc, char **argv) {
/* free up linked list */
for ( ; start; start = curr) {
curr = start->next;
- pj_dalloc(start);
+ free(start);
}
}
diff --git a/src/apps/gie.cpp b/src/apps/gie.cpp
index 8940afde..b504b922 100644
--- a/src/apps/gie.cpp
+++ b/src/apps/gie.cpp
@@ -880,8 +880,8 @@ static int expect_failure_with_errno_message (int expected, int got) {
banner (T.operation);
fprintf (T.fout, "%s", T.op_ko? " -----\n": delim);
fprintf (T.fout, " FAILURE in %s(%d):\n", opt_strip_path (T.curr_file), (int) F->lineno);
- fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, pj_strerrno (got));
- fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, pj_strerrno (expected));
+ fprintf (T.fout, " got errno %s (%d): %s\n", err_const_from_errno(got), got, proj_errno_string (got));
+ fprintf (T.fout, " expected %s (%d): %s", err_const_from_errno(expected), expected, proj_errno_string (expected));
fprintf (T.fout, "\n");
return 1;
}
@@ -934,7 +934,7 @@ Tell GIE what to expect, when transforming the ACCEPTed input
/* Otherwise, it's a true failure */
banner (T.operation);
errmsg (3, "%sInvalid operation definition in line no. %d:\n %s (errno=%s/%d)\n",
- delim, (int) T.operation_lineno, pj_strerrno(proj_errno(T.P)),
+ delim, (int) T.operation_lineno, proj_errno_string (proj_errno(T.P)),
err_const_from_errno (proj_errno(T.P)), proj_errno(T.P)
);
return another_failing_failure ();
@@ -1124,7 +1124,7 @@ static const struct errno_vs_err_const lookup[] = {
{"pjd_err_invalid_x_or_y" , -15},
{"pjd_err_wrong_format_dms_value" , -16},
{"pjd_err_non_conv_inv_meri_dist" , -17},
- {"pjd_err_non_con_inv_phi2" , -18},
+ {"pjd_err_non_conv_sinhpsi2tanphi" , -18},
{"pjd_err_acos_asin_arg_too_large" , -19},
{"pjd_err_tolerance_condition" , -20},
{"pjd_err_conic_lat_equal" , -21},
@@ -1186,7 +1186,7 @@ static int list_err_codes (void) {
if (9999==lookup[i].the_errno)
break;
fprintf (T.fout, "%25s (%2.2d): %s\n", lookup[i].the_err_const + 8,
- lookup[i].the_errno, pj_strerrno(lookup[i].the_errno));
+ lookup[i].the_errno, proj_errno_string (lookup[i].the_errno));
}
return 0;
}
diff --git a/src/apps/proj.cpp b/src/apps/proj.cpp
index 0bf98b3a..0108cb74 100644
--- a/src/apps/proj.cpp
+++ b/src/apps/proj.cpp
@@ -9,6 +9,8 @@
#include "emess.h"
#include "utils.h"
+#include <vector>
+
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__WIN32__)
# include <fcntl.h>
# include <io.h>
@@ -171,6 +173,7 @@ static void process(FILE *fid) {
(void)fputs("\t<* * * * * *>", stdout);
}
(void)fputs(bin_in ? "\n" : s, stdout);
+ fflush(stdout);
}
}
@@ -249,10 +252,8 @@ static void vprocess(FILE *fid) {
if (postscale) { dat_xy.x *= fscale; dat_xy.y *= fscale; }
}
- /* For some reason pj_errno does not work as expected in some */
- /* versions of Visual Studio, so using pj_get_errno_ref instead */
- if (*pj_get_errno_ref()) {
- emess(-1, pj_strerrno(*pj_get_errno_ref()));
+ if (proj_context_errno(nullptr)) {
+ emess(-1, proj_errno_string(proj_context_errno(nullptr)));
continue;
}
@@ -286,15 +287,17 @@ static void vprocess(FILE *fid) {
(void)fputs(proj_rtodms(pline, facs.meridian_convergence, 0, 0), stdout);
(void)printf(" [ %.8f ]\n", facs.meridian_convergence * RAD_TO_DEG);
(void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n", facs.tissot_semimajor, facs.tissot_semiminor);
+
+ fflush(stdout);
}
}
int main(int argc, char **argv) {
char *arg;
- char *pargv[MAX_PARGS] = {};
+ std::vector<char*> argvVector;
char **eargv = argv;
FILE *fid;
- int pargc = 0, eargc = 0, mon = 0;
+ int eargc = 0, mon = 0;
if ( (emess_dat.Prog_name = strrchr(*argv,DIR_CHAR)) != nullptr)
++emess_dat.Prog_name;
@@ -449,10 +452,7 @@ int main(int argc, char **argv) {
}
break;
} else if (**argv == '+') { /* + argument */
- if (pargc < MAX_PARGS)
- pargv[pargc++] = *argv + 1;
- else
- emess(1,"overflowed + argument table");
+ argvVector.push_back(*argv + 1);
} else /* assumed to be input file name(s) */
eargv[eargc++] = *argv;
}
@@ -472,9 +472,14 @@ int main(int argc, char **argv) {
postscale = 0;
fscale = 1./fscale;
}
- if (!(Proj = pj_init(pargc, pargv)))
+ proj_context_use_proj4_init_rules(nullptr, true);
+
+ // proj historically ignores any datum shift specifier, like nadgrids, towgs84, etc
+ argvVector.push_back(const_cast<char*>("break_cs2cs_recursion"));
+
+ if (!(Proj = proj_create_argv(nullptr, static_cast<int>(argvVector.size()), argvVector.data())))
emess(3,"projection initialization failure\ncause: %s",
- pj_strerrno(pj_errno));
+ proj_errno_string(proj_context_errno(nullptr)));
if (!proj_angular_input(Proj, PJ_FWD)) {
emess(3, "can't initialize operations that take non-angular input coordinates");
@@ -559,7 +564,7 @@ int main(int argc, char **argv) {
}
if( Proj )
- pj_free(Proj);
+ proj_destroy(Proj);
exit(0); /* normal completion */
}
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 37b76346..da885fbb 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -72,6 +72,7 @@ struct OutputOptions {
bool singleLine = false;
bool strict = true;
bool ballparkAllowed = true;
+ bool allowEllipsoidalHeightAsVerticalCRS = false;
};
} // anonymous namespace
@@ -79,7 +80,8 @@ struct OutputOptions {
static void usage() {
std::cerr
- << "usage: projinfo [-o formats] [-k crs|operation|datum|ellipsoid] "
+ << "usage: projinfo [-o formats] "
+ "[-k crs|operation|datum|ensemble|ellipsoid] "
"[--summary] [-q]"
<< std::endl
<< " ([--area name_or_code] | "
@@ -94,6 +96,8 @@ static void usage() {
<< " [--pivot-crs always|if_no_direct_transformation|"
<< "never|{auth:code[,auth:code]*}]" << std::endl
<< " [--show-superseded] [--hide-ballpark]" << std::endl
+ << " [--allow-ellipsoidal-height-as-vertical-crs]"
+ << std::endl
<< " [--boundcrs-to-wgs84]" << std::endl
<< " [--main-db-path path] [--aux-db-path path]*"
<< std::endl
@@ -184,11 +188,11 @@ static BaseObjectNNPtr buildObject(
auto urn = "urn:ogc:def:coordinateOperation:" + tokens[0] + "::" +
tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
- } else if (kind == "ellipsoid" && tokens.size() == 2) {
- auto urn = "urn:ogc:def:ellipsoid:" + tokens[0] + "::" + tokens[1];
- obj = createFromUserInput(urn, dbContext).as_nullable();
- } else if (kind == "datum" && tokens.size() == 2) {
- auto urn = "urn:ogc:def:datum:" + tokens[0] + "::" + tokens[1];
+ } else if ((kind == "ellipsoid" || kind == "datum" ||
+ kind == "ensemble") &&
+ tokens.size() == 2) {
+ auto urn =
+ "urn:ogc:def:" + kind + ":" + tokens[0] + "::" + tokens[1];
obj = createFromUserInput(urn, dbContext).as_nullable();
} else {
// Convenience to be able to use C escaped strings...
@@ -222,6 +226,9 @@ static BaseObjectNNPtr buildObject(
AuthorityFactory::ObjectType::ELLIPSOID);
else if (kind == "datum")
allowedTypes.push_back(AuthorityFactory::ObjectType::DATUM);
+ else if (kind == "ensemble")
+ allowedTypes.push_back(
+ AuthorityFactory::ObjectType::DATUM_ENSEMBLE);
constexpr size_t limitResultCount = 10;
auto factory = AuthorityFactory::create(NN_NO_CHECK(dbContext),
std::string());
@@ -483,6 +490,8 @@ static void outputObject(
formatter->setMultiLine(false);
}
formatter->setStrict(outputOpt.strict);
+ formatter->setAllowEllipsoidalHeightAsVerticalCRS(
+ outputOpt.allowEllipsoidalHeightAsVerticalCRS);
auto wkt = wktExportable->exportToWKT(formatter.get());
if (outputOpt.c_ify) {
wkt = c_ify_string(wkt);
@@ -689,6 +698,7 @@ static void outputOperations(
std::vector<CoordinateOperationNNPtr> list;
size_t spatialCriterionPartialIntersectionResultCount = 0;
+ bool spatialCriterionPartialIntersectionMoreRelevant = false;
try {
auto authFactory =
dbContext
@@ -714,10 +724,15 @@ static void outputOperations(
ctxt->setSpatialCriterion(
CoordinateOperationContext::SpatialCriterion::
PARTIAL_INTERSECTION);
- spatialCriterionPartialIntersectionResultCount =
- CoordinateOperationFactory::create()
- ->createOperations(nnSourceCRS, nnTargetCRS, ctxt)
- .size();
+ auto list2 =
+ CoordinateOperationFactory::create()->createOperations(
+ nnSourceCRS, nnTargetCRS, ctxt);
+ spatialCriterionPartialIntersectionResultCount = list2.size();
+ if (spatialCriterionPartialIntersectionResultCount == 1 &&
+ list.size() == 1 &&
+ list2[0]->nameStr() != list[0]->nameStr()) {
+ spatialCriterionPartialIntersectionMoreRelevant = true;
+ }
} catch (const std::exception &) {
}
}
@@ -736,6 +751,10 @@ static void outputOperations(
"more results ("
<< spatialCriterionPartialIntersectionResultCount << ")"
<< std::endl;
+ } else if (spatialCriterionPartialIntersectionMoreRelevant) {
+ std::cout << "Note: using '--spatial-test intersects' would bring "
+ "more relevant results."
+ << std::endl;
}
if (summary) {
for (const auto &op : list) {
@@ -929,6 +948,8 @@ int main(int argc, char **argv) {
objectKind = "ellipsoid";
} else if (ci_equal(kind, "datum")) {
objectKind = "datum";
+ } else if (ci_equal(kind, "ensemble")) {
+ objectKind = "ensemble";
} else {
std::cerr << "Unrecognized value for option -k: " << kind
<< std::endl;
@@ -1054,6 +1075,8 @@ int main(int argc, char **argv) {
showSuperseded = true;
} else if (arg == "--lax") {
outputOpt.strict = false;
+ } else if (arg == "--allow-ellipsoidal-height-as-vertical-crs") {
+ outputOpt.allowEllipsoidalHeightAsVerticalCRS = true;
} else if (arg == "--hide-ballpark") {
outputOpt.ballparkAllowed = false;
} else if (ci_equal(arg, "--3d")) {
diff --git a/src/auth.cpp b/src/auth.cpp
index a8ee262a..ced02fb4 100644
--- a/src/auth.cpp
+++ b/src/auth.cpp
@@ -18,7 +18,7 @@
pj_authset(double es) {
double t, *APA;
- if ((APA = (double *)pj_malloc(APA_SIZE * sizeof(double))) != nullptr) {
+ if ((APA = (double *)malloc(APA_SIZE * sizeof(double))) != nullptr) {
APA[0] = es * P00;
t = es * es;
APA[0] += t * P01;
diff --git a/src/bin_projinfo.cmake b/src/bin_projinfo.cmake
index 16c9e9d0..8610a3a7 100644
--- a/src/bin_projinfo.cmake
+++ b/src/bin_projinfo.cmake
@@ -15,3 +15,7 @@ install(TARGETS binprojinfo
if(MSVC AND BUILD_SHARED_LIBS)
target_compile_definitions(binprojinfo PRIVATE PROJ_MSVC_DLL_IMPORT=1)
endif()
+
+if(CURL_ENABLED)
+ target_compile_definitions(binprojinfo PRIVATE -DCURL_ENABLED)
+endif()
diff --git a/src/conversions/axisswap.cpp b/src/conversions/axisswap.cpp
index 4ae2b4e4..1aa339c3 100644
--- a/src/conversions/axisswap.cpp
+++ b/src/conversions/axisswap.cpp
@@ -169,7 +169,7 @@ static PJ_COORD reverse_4d(PJ_COORD coo, PJ *P) {
/***********************************************************************/
PJ *CONVERSION(axisswap,0) {
/***********************************************************************/
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
char *s;
unsigned int i, j, n = 0;
diff --git a/src/conversions/set.cpp b/src/conversions/set.cpp
index 7628bf4f..2f30bda8 100644
--- a/src/conversions/set.cpp
+++ b/src/conversions/set.cpp
@@ -39,7 +39,7 @@ PJ *OPERATION(set, 0) {
P->inv4d = set_fwd_inv;
P->fwd4d = set_fwd_inv;
- auto set = static_cast<struct Set*>(pj_calloc (1, sizeof(struct Set)));
+ auto set = static_cast<struct Set*>(calloc (1, sizeof(struct Set)));
P->opaque = set;
if (nullptr==P->opaque)
return pj_default_destructor(P, ENOMEM);
diff --git a/src/conversions/topocentric.cpp b/src/conversions/topocentric.cpp
new file mode 100644
index 00000000..f6f328ad
--- /dev/null
+++ b/src/conversions/topocentric.cpp
@@ -0,0 +1,165 @@
+/******************************************************************************
+ * Project: PROJ
+ * Purpose: Convert between geocentric coordinates and topocentric (ENU) coordinates
+ *
+ ******************************************************************************
+ * Copyright (c) 2020, Even Rouault <even.rouault at spatialys.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 PJ_LIB__
+
+#include "proj_internal.h"
+#include <errno.h>
+#include <math.h>
+
+PROJ_HEAD(topocentric, "Geocentric/Topocentric conversion");
+
+// Notations and formulas taken from IOGP Publication 373-7-2 -
+// Geomatics Guidance Note number 7, part 2 - October 2020
+
+namespace { // anonymous namespace
+struct pj_opaque {
+ double X0;
+ double Y0;
+ double Z0;
+ double sinphi0;
+ double cosphi0;
+ double sinlam0;
+ double coslam0;
+};
+} // anonymous namespace
+
+// Convert from geocentric to topocentric
+static PJ_COORD topocentric_fwd(PJ_COORD in, PJ * P)
+{
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
+ PJ_COORD out;
+ const double dX = in.xyz.x - Q->X0;
+ const double dY = in.xyz.y - Q->Y0;
+ const double dZ = in.xyz.z - Q->Z0;
+ out.xyz.x = -dX * Q->sinlam0 + dY * Q->coslam0;
+ out.xyz.y = -dX * Q->sinphi0 * Q->coslam0 - dY * Q->sinphi0 * Q->sinlam0 + dZ * Q->cosphi0;
+ out.xyz.z = dX * Q->cosphi0 * Q->coslam0 + dY * Q->cosphi0 * Q->sinlam0 + dZ * Q->sinphi0;
+ return out;
+}
+
+// Convert from topocentric to geocentric
+static PJ_COORD topocentric_inv(PJ_COORD in, PJ * P)
+{
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(P->opaque);
+ PJ_COORD out;
+ out.xyz.x = Q->X0 - in.xyz.x * Q->sinlam0 - in.xyz.y * Q->sinphi0 * Q->coslam0 + in.xyz.z * Q->cosphi0 * Q->coslam0;
+ out.xyz.y = Q->Y0 + in.xyz.x * Q->coslam0 - in.xyz.y * Q->sinphi0 * Q->sinlam0 + in.xyz.z * Q->cosphi0 * Q->sinlam0;
+ out.xyz.z = Q->Z0 + in.xyz.y * Q->cosphi0 + in.xyz.z * Q->sinphi0;
+ return out;
+}
+
+
+/*********************************************************************/
+PJ *CONVERSION(topocentric,1) {
+/*********************************************************************/
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
+ if (nullptr==Q)
+ return pj_default_destructor (P, ENOMEM);
+ P->opaque = static_cast<void *>(Q);
+
+ // The topocentric origin can be specified either in geocentric coordinates
+ // (X_0,Y_0,Z_0) or as geographic coordinates (lon_0,lat_0,h_0)
+ // Checks:
+ // - X_0 or lon_0 must be specified
+ // - If X_0 is specified, the Y_0 and Z_0 must also be
+ // - If lon_0 is specified, then lat_0 must also be
+ // - If any of X_0, Y_0, Z_0 is specified, then any of lon_0,lat_0,h_0 must
+ // not be, and vice versa.
+ const auto hasX0 = pj_param_exists(P->params, "X_0");
+ const auto hasY0 = pj_param_exists(P->params, "Y_0");
+ const auto hasZ0 = pj_param_exists(P->params, "Z_0");
+ const auto hasLon0 = pj_param_exists(P->params, "lon_0");
+ const auto hasLat0 = pj_param_exists(P->params, "lat_0");
+ const auto hash0 = pj_param_exists(P->params, "h_0");
+ if( !hasX0 && !hasLon0 )
+ {
+ return pj_default_destructor(P, PJD_ERR_MISSING_ARGS);
+ }
+ if ( (hasX0 || hasY0 || hasZ0) &&
+ (hasLon0 || hasLat0 || hash0) )
+ {
+ return pj_default_destructor(P, PJD_ERR_MUTUALLY_EXCLUSIVE_ARGS);
+ }
+ if( hasX0 && (!hasY0 || !hasZ0) )
+ {
+ return pj_default_destructor(P, PJD_ERR_MISSING_ARGS);
+ }
+ if( hasLon0 && !hasLat0 ) // allow missing h_0
+ {
+ return pj_default_destructor(P, PJD_ERR_MISSING_ARGS);
+ }
+
+ // Pass a dummy ellipsoid definition that will be overridden just afterwards
+ PJ* cart = proj_create(P->ctx, "+proj=cart +a=1");
+ if (cart == nullptr)
+ return pj_default_destructor(P, ENOMEM);
+ /* inherit ellipsoid definition from P to cart */
+ pj_inherit_ellipsoid_def (P, cart);
+
+ if( hasX0 )
+ {
+ Q->X0 = pj_param(P->ctx, P->params, "dX_0").f;
+ Q->Y0 = pj_param(P->ctx, P->params, "dY_0").f;
+ Q->Z0 = pj_param(P->ctx, P->params, "dZ_0").f;
+
+ // Compute lam0, phi0 from X0,Y0,Z0
+ PJ_XYZ xyz;
+ xyz.x = Q->X0;
+ xyz.y = Q->Y0;
+ xyz.z = Q->Z0;
+ const auto lpz = pj_inv3d(xyz, cart);
+ Q->sinphi0 = sin(lpz.phi);
+ Q->cosphi0 = cos(lpz.phi);
+ Q->sinlam0 = sin(lpz.lam);
+ Q->coslam0 = cos(lpz.lam);
+ }
+ else
+ {
+ // Compute X0,Y0,Z0 from lam0, phi0, h0
+ PJ_LPZ lpz;
+ lpz.lam = P->lam0;
+ lpz.phi = P->phi0;
+ lpz.z = pj_param(P->ctx, P->params, "dh_0").f;
+ const auto xyz = pj_fwd3d(lpz, cart);
+ Q->X0 = xyz.x;
+ Q->Y0 = xyz.y;
+ Q->Z0 = xyz.z;
+
+ Q->sinphi0 = sin(P->phi0);
+ Q->cosphi0 = cos(P->phi0);
+ Q->sinlam0 = sin(P->lam0);
+ Q->coslam0 = cos(P->lam0);
+ }
+
+ proj_destroy(cart);
+
+ P->fwd4d = topocentric_fwd;
+ P->inv4d = topocentric_inv;
+ P->left = PJ_IO_UNITS_CARTESIAN;
+ P->right = PJ_IO_UNITS_CARTESIAN;
+ return P;
+}
diff --git a/src/conversions/unitconvert.cpp b/src/conversions/unitconvert.cpp
index 172e2c48..61bccbf1 100644
--- a/src/conversions/unitconvert.cpp
+++ b/src/conversions/unitconvert.cpp
@@ -433,7 +433,7 @@ static double get_unit_conversion_factor(const char* name,
/***********************************************************************/
PJ *CONVERSION(unitconvert,0) {
/***********************************************************************/
- struct pj_opaque_unitconvert *Q = static_cast<struct pj_opaque_unitconvert*>(pj_calloc (1, sizeof (struct pj_opaque_unitconvert)));
+ struct pj_opaque_unitconvert *Q = static_cast<struct pj_opaque_unitconvert*>(calloc (1, sizeof (struct pj_opaque_unitconvert)));
const char *s, *name;
int i;
double f;
diff --git a/src/ctx.cpp b/src/ctx.cpp
index 6dbe0de5..2093950b 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -1,6 +1,6 @@
/******************************************************************************
* Project: PROJ.4
- * Purpose: Implementation of the projCtx thread context object.
+ * Purpose: Implementation of the PJ_CONTEXT thread context object.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
@@ -43,7 +43,7 @@
/* pj_get_ctx() */
/************************************************************************/
-projCtx pj_get_ctx( projPJ pj )
+PJ_CONTEXT* pj_get_ctx( PJ *pj )
{
if (nullptr==pj)
@@ -54,13 +54,17 @@ projCtx pj_get_ctx( projPJ pj )
}
/************************************************************************/
-/* pj_set_ctx() */
-/* */
-/* Note we do not deallocate the old context! */
+/* proj_assign_context() */
/************************************************************************/
-void pj_set_ctx( projPJ pj, projCtx ctx )
-
+/** \brief Re-assign a context to a PJ* object.
+ *
+ * This may be useful if the PJ* has been created with a context that is
+ * thread-specific, and is later used in another thread. In that case,
+ * the user may want to assign another thread-specific context to the
+ * object.
+ */
+void proj_assign_context( PJ* pj, PJ_CONTEXT *ctx )
{
if (pj==nullptr)
return;
@@ -71,36 +75,20 @@ void pj_set_ctx( projPJ pj, projCtx ctx )
}
for( const auto &alt: pj->alternativeCoordinateOperations )
{
- pj_set_ctx(alt.pj, ctx);
+ proj_assign_context(alt.pj, ctx);
}
-}
-
-/************************************************************************/
-/* proj_assign_context() */
-/************************************************************************/
-/** \brief Re-assign a context to a PJ* object.
- *
- * This may be useful if the PJ* has been created with a context that is
- * thread-specific, and is later used in another thread. In that case,
- * the user may want to assign another thread-specific context to the
- * object.
- */
-void proj_assign_context( PJ* pj, PJ_CONTEXT* ctx )
-{
- pj_set_ctx( pj, ctx );
}
/************************************************************************/
/* createDefault() */
/************************************************************************/
-projCtx_t projCtx_t::createDefault()
+pj_ctx pj_ctx::createDefault()
{
- projCtx_t ctx;
+ pj_ctx ctx;
ctx.debug_level = PJ_LOG_NONE;
ctx.logger = pj_stderr_logger;
- ctx.fileapi_legacy = pj_get_default_fileapi();
NS_PROJ::FileManager::fillDefaultNetworkInterface(&ctx);
if( getenv("PROJ_DEBUG") != nullptr )
@@ -117,7 +105,7 @@ projCtx_t projCtx_t::createDefault()
/* get_cpp_context() */
/**************************************************************************/
-projCppContext* projCtx_t::get_cpp_context()
+projCppContext* pj_ctx::get_cpp_context()
{
if (cpp_context == nullptr) {
cpp_context = new projCppContext(this);
@@ -125,12 +113,11 @@ projCppContext* projCtx_t::get_cpp_context()
return cpp_context;
}
-
/**************************************************************************/
/* safeAutoCloseDbIfNeeded() */
/**************************************************************************/
-void projCtx_t::safeAutoCloseDbIfNeeded()
+void pj_ctx::safeAutoCloseDbIfNeeded()
{
if (cpp_context) {
cpp_context->autoCloseDbIfNeeded();
@@ -141,7 +128,7 @@ void projCtx_t::safeAutoCloseDbIfNeeded()
/* set_search_paths() */
/************************************************************************/
-void projCtx_t::set_search_paths(const std::vector<std::string>& search_paths_in )
+void pj_ctx::set_search_paths(const std::vector<std::string>& search_paths_in )
{
search_paths = search_paths_in;
delete[] c_compat_paths;
@@ -158,26 +145,24 @@ void projCtx_t::set_search_paths(const std::vector<std::string>& search_paths_in
/* set_ca_bundle_path() */
/**************************************************************************/
-void projCtx_t::set_ca_bundle_path(const std::string& ca_bundle_path_in)
+void pj_ctx::set_ca_bundle_path(const std::string& ca_bundle_path_in)
{
ca_bundle_path = ca_bundle_path_in;
}
/************************************************************************/
-/* projCtx_t(const projCtx_t& other) */
+/* pj_ctx(const pj_ctx& other) */
/************************************************************************/
-projCtx_t::projCtx_t(const projCtx_t& other) :
+pj_ctx::pj_ctx(const pj_ctx& other) :
debug_level(other.debug_level),
logger(other.logger),
logger_app_data(other.logger_app_data),
- fileapi_legacy(other.fileapi_legacy),
cpp_context(other.cpp_context ? other.cpp_context->clone(this) : nullptr),
use_proj4_init_rules(other.use_proj4_init_rules),
epsg_file_exists(other.epsg_file_exists),
ca_bundle_path(other.ca_bundle_path),
env_var_proj_lib(other.env_var_proj_lib),
- file_finder_legacy(other.file_finder_legacy),
file_finder(other.file_finder),
file_finder_user_data(other.file_finder_user_data),
custom_sqlite3_vfs_name(other.custom_sqlite3_vfs_name),
@@ -197,129 +182,35 @@ projCtx_t::projCtx_t(const projCtx_t& other) :
/* pj_get_default_ctx() */
/************************************************************************/
-projCtx pj_get_default_ctx()
+PJ_CONTEXT* pj_get_default_ctx()
{
// C++11 rules guarantee a thread-safe instantiation.
- static projCtx_t default_context(projCtx_t::createDefault());
+ static pj_ctx default_context(pj_ctx::createDefault());
return &default_context;
}
/************************************************************************/
-/* ~projCtx_t() */
+/* ~pj_ctx() */
/************************************************************************/
-projCtx_t::~projCtx_t()
+pj_ctx::~pj_ctx()
{
delete[] c_compat_paths;
proj_context_delete_cpp_context(cpp_context);
}
/************************************************************************/
-/* pj_ctx_alloc() */
-/************************************************************************/
-
-projCtx pj_ctx_alloc()
-
-{
- return new (std::nothrow) projCtx_t(*pj_get_default_ctx());
-}
-
-/************************************************************************/
/* proj_context_clone() */
/* Create a new context based on a custom context */
/************************************************************************/
-PJ_CONTEXT *proj_context_clone (PJ_CONTEXT *ctx)
-{
- if (nullptr==ctx)
- return pj_ctx_alloc ();
-
- return new (std::nothrow) projCtx_t(*ctx);
-}
-
-/************************************************************************/
-/* pj_ctx_free() */
-/************************************************************************/
-
-void pj_ctx_free( projCtx ctx )
-
-{
- delete ctx;
-}
-
-/************************************************************************/
-/* pj_ctx_get_errno() */
-/************************************************************************/
-
-int pj_ctx_get_errno( projCtx ctx )
-
+PJ_CONTEXT* proj_context_clone (PJ_CONTEXT *ctx)
{
if (nullptr==ctx)
- return pj_get_default_ctx ()->last_errno;
- return ctx->last_errno;
-}
-
-/************************************************************************/
-/* pj_ctx_set_errno() */
-/* */
-/* Also sets the global errno */
-/************************************************************************/
-
-void pj_ctx_set_errno( projCtx ctx, int new_errno )
-
-{
- ctx->last_errno = new_errno;
- if( new_errno == 0 )
- return;
- errno = new_errno;
- pj_errno = new_errno;
-}
-
-/************************************************************************/
-/* pj_ctx_set_debug() */
-/************************************************************************/
-
-void pj_ctx_set_debug( projCtx ctx, int new_debug )
+ return proj_context_create();
-{
- if (nullptr==ctx)
- return;
- ctx->debug_level = new_debug;
+ return new (std::nothrow) pj_ctx(*ctx);
}
-/************************************************************************/
-/* pj_ctx_set_logger() */
-/************************************************************************/
-
-void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) )
-{
- if (nullptr==ctx)
- return;
- ctx->logger = new_logger;
-}
-
-/************************************************************************/
-/* pj_ctx_set_app_data() */
-/************************************************************************/
-
-void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
-
-{
- if (nullptr==ctx)
- return;
- ctx->logger_app_data = new_app_data;
-}
-
-/************************************************************************/
-/* pj_ctx_get_app_data() */
-/************************************************************************/
-
-void *pj_ctx_get_app_data( projCtx ctx )
-
-{
- if (nullptr==ctx)
- return nullptr;
- return ctx->logger_app_data;
-}
diff --git a/src/datum_set.cpp b/src/datum_set.cpp
index 15d51613..3f612633 100644
--- a/src/datum_set.cpp
+++ b/src/datum_set.cpp
@@ -38,7 +38,7 @@
/* pj_datum_set() */
/************************************************************************/
-int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
+int pj_datum_set(PJ_CONTEXT *ctx, paralist *pl, PJ *projdef)
{
const char *name, *towgs84, *nadgrids;
@@ -71,7 +71,7 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
for (i = 0; (s = pj_datums[i].id) && strcmp(name, s) ; ++i) {}
if (!s) {
- pj_ctx_set_errno(ctx, PJD_ERR_UNKNOWN_ELLP_PARAM);
+ proj_context_errno_set(ctx, PJD_ERR_UNKNOWN_ELLP_PARAM);
return 1;
}
@@ -84,25 +84,27 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
sizeof(entry) - 1 - strlen(entry) );
entry[ sizeof(entry) - 1 ] = '\0';
- curr = curr->next = pj_mkparam(entry);
- if (nullptr == curr)
+ auto param = pj_mkparam(entry);
+ if (nullptr == param)
{
- pj_ctx_set_errno(ctx, ENOMEM);
+ proj_context_errno_set(ctx, ENOMEM);
return 1;
}
+ curr->next = param;
+ curr = param;
}
if( pj_datums[i].defn && strlen(pj_datums[i].defn) > 0 )
{
- curr = curr->next = pj_mkparam(pj_datums[i].defn);
- if (nullptr == curr)
+ auto param = pj_mkparam(pj_datums[i].defn);
+ if (nullptr == param)
{
- pj_ctx_set_errno(ctx, ENOMEM);
+ proj_context_errno_set(ctx, ENOMEM);
return 1;
}
+ curr->next = param;
+ /* curr = param; */
}
-
- (void)curr; /* make clang static analyzer happy */
}
/* -------------------------------------------------------------------- */
diff --git a/src/dmstor.cpp b/src/dmstor.cpp
index 3ba66030..24887a11 100644
--- a/src/dmstor.cpp
+++ b/src/dmstor.cpp
@@ -26,7 +26,7 @@ dmstor(const char *is, char **rs) {
}
double
-dmstor_ctx(projCtx ctx, const char *is, char **rs) {
+dmstor_ctx(PJ_CONTEXT *ctx, const char *is, char **rs) {
int sign, n, nl;
char *s, work[MAX_WORK];
const char* p;
@@ -61,7 +61,7 @@ dmstor_ctx(projCtx ctx, const char *is, char **rs) {
n = 2; break;
case 'r': case 'R':
if (nl) {
- pj_ctx_set_errno( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE );
+ proj_context_errno_set( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE );
return HUGE_VAL;
}
++s;
@@ -73,7 +73,7 @@ dmstor_ctx(projCtx ctx, const char *is, char **rs) {
continue;
}
if (n < nl) {
- pj_ctx_set_errno( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE );
+ proj_context_errno_set( ctx, PJD_ERR_WRONG_FORMAT_DMS_VALUE );
return HUGE_VAL;
}
v += tv * vm[n];
diff --git a/src/ell_set.cpp b/src/ell_set.cpp
index ddd507ac..176fc553 100644
--- a/src/ell_set.cpp
+++ b/src/ell_set.cpp
@@ -77,13 +77,13 @@ int pj_ellipsoid (PJ *P) {
int err = proj_errno_reset (P);
const char *empty = {""};
- pj_dealloc(P->def_size);
+ free(P->def_size);
P->def_size = nullptr;
- pj_dealloc(P->def_shape);
+ free(P->def_shape);
P->def_shape = nullptr;
- pj_dealloc(P->def_spherification);
+ free(P->def_spherification);
P->def_spherification = nullptr;
- pj_dealloc(P->def_ellps);
+ free(P->def_ellps);
P->def_ellps = nullptr;
/* Specifying R overrules everything */
@@ -162,7 +162,7 @@ static int ellps_ellps (PJ *P) {
new_params->next = pj_mkparam (ellps->ell);
if (nullptr == new_params->next)
{
- pj_dealloc(new_params);
+ free(new_params);
return proj_errno_set (P, ENOMEM);
}
paralist* old_params = P->params;
@@ -176,8 +176,8 @@ static int ellps_ellps (PJ *P) {
ellps_shape (P);
P->params = old_params;
- pj_dealloc (new_params->next);
- pj_dealloc (new_params);
+ free (new_params->next);
+ free (new_params);
if (proj_errno (P))
return proj_errno (P);
@@ -195,7 +195,7 @@ static int ellps_size (PJ *P) {
paralist *par = nullptr;
int a_was_set = 0;
- pj_dealloc(P->def_size);
+ free(P->def_size);
P->def_size = nullptr;
/* A size parameter *must* be given, but may have been given as ellps prior */
@@ -235,7 +235,7 @@ static int ellps_shape (PJ *P) {
par = nullptr;
len = sizeof (keys) / sizeof (char *);
- pj_dealloc(P->def_shape);
+ free(P->def_shape);
P->def_shape = nullptr;
/* Check which shape key is specified */
@@ -552,7 +552,7 @@ int pj_calc_ellipsoid_params (PJ *P, double a, double es) {
if (0==P->f)
P->f = 1 - cos (P->alpha); /* = 1 - sqrt (1 - PIN->es); */
if (P->f == 1.0) {
- pj_ctx_set_errno( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ proj_context_errno_set( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
return PJD_ERR_INVALID_ECCENTRICITY;
}
P->rf = P->f != 0.0 ? 1.0/P->f: HUGE_VAL;
@@ -573,7 +573,7 @@ int pj_calc_ellipsoid_params (PJ *P, double a, double es) {
P->one_es = 1. - P->es;
if (P->one_es == 0.) {
- pj_ctx_set_errno( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ proj_context_errno_set( P->ctx, PJD_ERR_INVALID_ECCENTRICITY);
return PJD_ERR_INVALID_ECCENTRICITY;
}
@@ -609,7 +609,7 @@ int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) {
/**************************************************************************************/
-int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
+int pj_ell_set (PJ_CONTEXT *ctx, paralist *pl, double *a, double *es) {
/***************************************************************************************
Initialize ellipsoidal parameters: This is the original ellipsoid setup
function by Gerald Evenden - significantly more compact than pj_ellipsoid and
@@ -630,7 +630,7 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
paralist *start = 0;
/* clear any previous error */
- pj_ctx_set_errno(ctx,0);
+ proj_context_errno_set(ctx,0);
/* check for varying forms of ellipsoid input */
*a = *es = 0.;
@@ -648,7 +648,7 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
for (start = pl; start && start->next ; start = start->next) ;
for (i = 0; (s = pj_ellps[i].id) && strcmp(name, s) ; ++i) ;
if (!s) {
- pj_ctx_set_errno( ctx, PJD_ERR_UNKNOWN_ELLP_PARAM);
+ proj_context_errno_set( ctx, PJD_ERR_UNKNOWN_ELLP_PARAM);
return 1;
}
start->next = pj_mkparam(pj_ellps[i].major);
@@ -662,14 +662,14 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
else if (pj_param(ctx,pl, "te").i) { /* eccentricity */
e = pj_param(ctx,pl, "de").f;
if (e < 0) {
- pj_ctx_set_errno(ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ proj_context_errno_set(ctx, PJD_ERR_INVALID_ECCENTRICITY);
return 1;
}
*es = e * e;
} else if (pj_param(ctx,pl, "trf").i) { /* recip flattening */
*es = pj_param(ctx,pl, "drf").f;
if (*es == 0.0) {
- pj_ctx_set_errno(ctx, PJD_ERR_REV_FLATTENING_IS_ZERO);
+ proj_context_errno_set(ctx, PJD_ERR_REV_FLATTENING_IS_ZERO);
goto bomb;
}
*es = 1./ *es;
@@ -700,7 +700,7 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
*es = 0.;
} else if (pj_param(ctx,pl, "bR_h").i) { /* sphere--harmonic mean */
if ( (*a + b) == 0.0) {
- pj_ctx_set_errno(ctx, PJD_ERR_TOLERANCE_CONDITION);
+ proj_context_errno_set(ctx, PJD_ERR_TOLERANCE_CONDITION);
goto bomb;
}
*a = 2. * *a * b / (*a + b);
@@ -711,7 +711,7 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
tmp = sin(pj_param(ctx,pl, i ? "rR_lat_a" : "rR_lat_g").f);
if (fabs(tmp) > M_HALFPI) {
- pj_ctx_set_errno(ctx, PJD_ERR_REF_RAD_LARGER_THAN_90);
+ proj_context_errno_set(ctx, PJD_ERR_REF_RAD_LARGER_THAN_90);
goto bomb;
}
tmp = 1. - *es * tmp * tmp;
@@ -721,8 +721,8 @@ int pj_ell_set (projCtx ctx, paralist *pl, double *a, double *es) {
}
bomb:
if (start) { /* clean up temporary extension of list */
- pj_dalloc(start->next->next);
- pj_dalloc(start->next);
+ free(start->next->next);
+ free(start->next);
start->next = 0;
}
if (ctx->last_errno)
@@ -730,15 +730,15 @@ bomb:
}
/* some remaining checks */
if (*es < 0.) {
- pj_ctx_set_errno(ctx, PJD_ERR_ES_LESS_THAN_ZERO);
+ proj_context_errno_set(ctx, PJD_ERR_ES_LESS_THAN_ZERO);
return 1;
}
if (*es >= 1.) {
- pj_ctx_set_errno(ctx, PJD_ERR_INVALID_ECCENTRICITY);
+ proj_context_errno_set(ctx, PJD_ERR_INVALID_ECCENTRICITY);
return 1;
}
if (*a <= 0.) {
- pj_ctx_set_errno(ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN);
+ proj_context_errno_set(ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN);
return 1;
}
return 0;
diff --git a/src/errno.cpp b/src/errno.cpp
deleted file mode 100644
index 4f3119b3..00000000
--- a/src/errno.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/* For full ANSI compliance of global variable */
-
-#include "proj.h"
-#include "proj_internal.h"
-
-int pj_errno = 0;
-
-/************************************************************************/
-/* pj_get_errno_ref() */
-/************************************************************************/
-
-int *pj_get_errno_ref()
-
-{
- return &pj_errno;
-}
-
-/* end */
diff --git a/src/fileapi.cpp b/src/fileapi.cpp
deleted file mode 100644
index 70be2502..00000000
--- a/src/fileapi.cpp
+++ /dev/null
@@ -1,240 +0,0 @@
-/******************************************************************************
- * Project: PROJ.4
- * Purpose: Implementation of the pj_ctx_* file api, and the default stdio
- * based implementation.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2013, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "proj.h"
-#include "proj_internal.h"
-#include "filemanager.hpp"
-
-static PAFile stdio_fopen(projCtx ctx, const char *filename,
- const char *access);
-static size_t stdio_fread(void *buffer, size_t size, size_t nmemb,
- PAFile file);
-static int stdio_fseek(PAFile file, long offset, int whence);
-static long stdio_ftell(PAFile file);
-static void stdio_fclose(PAFile file);
-
-static projFileAPI default_fileapi = {
- stdio_fopen,
- stdio_fread,
- stdio_fseek,
- stdio_ftell,
- stdio_fclose
-};
-
-typedef struct {
- projCtx ctx;
- FILE *fp;
-} stdio_pafile;
-
-/************************************************************************/
-/* pj_get_default_fileapi() */
-/************************************************************************/
-
-projFileAPI *pj_get_default_fileapi(void)
-{
- return &default_fileapi;
-}
-
-/************************************************************************/
-/* stdio_fopen() */
-/************************************************************************/
-
-static PAFile stdio_fopen(projCtx ctx, const char *filename,
- const char *access)
-{
- stdio_pafile *pafile;
- FILE *fp;
-
- fp = fopen(filename, access);
- if (fp == nullptr)
- {
- return nullptr;
- }
-
- pafile = (stdio_pafile *) malloc(sizeof(stdio_pafile));
- if (!pafile)
- {
- pj_ctx_set_errno(ctx, ENOMEM);
- fclose(fp);
- return nullptr;
- }
-
- pafile->fp = fp;
- pafile->ctx = ctx;
- return (PAFile) pafile;
-}
-
-/************************************************************************/
-/* stdio_fread() */
-/************************************************************************/
-
-static size_t stdio_fread(void *buffer, size_t size, size_t nmemb,
- PAFile file)
-{
- stdio_pafile *pafile = (stdio_pafile *) file;
- return fread(buffer, size, nmemb, pafile->fp);
-}
-
-/************************************************************************/
-/* stdio_fseek() */
-/************************************************************************/
-static int stdio_fseek(PAFile file, long offset, int whence)
-{
- stdio_pafile *pafile = (stdio_pafile *) file;
- return fseek(pafile->fp, offset, whence);
-}
-
-/************************************************************************/
-/* stdio_ftell() */
-/************************************************************************/
-static long stdio_ftell(PAFile file)
-{
- stdio_pafile *pafile = (stdio_pafile *) file;
- return ftell(pafile->fp);
-}
-
-/************************************************************************/
-/* stdio_fclose() */
-/************************************************************************/
-static void stdio_fclose(PAFile file)
-{
- stdio_pafile *pafile = (stdio_pafile *) file;
- fclose(pafile->fp);
- free(pafile);
-}
-
-/************************************************************************/
-/* pj_ctx_fopen() */
-/* */
-/* Open a file using the provided file io hooks. */
-/************************************************************************/
-
-PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access)
-{
- return ctx->fileapi_legacy->FOpen(ctx, filename, access);
-}
-
-/************************************************************************/
-/* pj_ctx_fread() */
-/************************************************************************/
-size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file)
-{
- return ctx->fileapi_legacy->FRead(buffer, size, nmemb, file);
-}
-
-/************************************************************************/
-/* pj_ctx_fseek() */
-/************************************************************************/
-int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence)
-{
- return ctx->fileapi_legacy->FSeek(file, offset, whence);
-}
-
-/************************************************************************/
-/* pj_ctx_ftell() */
-/************************************************************************/
-long pj_ctx_ftell(projCtx ctx, PAFile file)
-{
- return ctx->fileapi_legacy->FTell(file);
-}
-
-/************************************************************************/
-/* pj_ctx_fclose() */
-/************************************************************************/
-void pj_ctx_fclose(projCtx ctx, PAFile file)
-{
- ctx->fileapi_legacy->FClose(file);
-}
-
-/************************************************************************/
-/* pj_ctx_fgets() */
-/* */
-/* A not very optimal implementation of fgets on top of */
-/* fread(). If we end up using this a lot more care should be */
-/* taken. */
-/************************************************************************/
-
-char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file)
-{
- long start = pj_ctx_ftell(ctx, file);
- size_t bytes_read;
- int i;
- int max_size;
-
- line[size-1] = '\0';
- bytes_read = pj_ctx_fread(ctx, line, 1, size-1, file);
- if(bytes_read == 0)
- return nullptr;
- if(bytes_read < (size_t)size)
- {
- line[bytes_read] = '\0';
- }
-
- max_size = (int)MIN(bytes_read, (size_t)(size > 2 ? size - 2 : 0));
- for( i = 0; i < max_size; i++)
- {
- if (line[i] == '\n')
- {
- line[i+1] = '\0';
- pj_ctx_fseek(ctx, file, start + i + 1, SEEK_SET);
- break;
- }
- }
- return line;
-}
-
-/************************************************************************/
-/* pj_ctx_set_fileapi() */
-/************************************************************************/
-
-void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
-
-{
- if (nullptr==ctx)
- return;
- ctx->fileapi_legacy = fileapi;
-}
-
-/************************************************************************/
-/* pj_ctx_get_fileapi() */
-/************************************************************************/
-
-projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
-
-{
- if (nullptr==ctx)
- return nullptr;
- return ctx->fileapi_legacy;
-}
-
diff --git a/src/filemanager.cpp b/src/filemanager.cpp
index e6a9ed95..b51205eb 100644
--- a/src/filemanager.cpp
+++ b/src/filemanager.cpp
@@ -786,75 +786,6 @@ std::unique_ptr<File> FileStdio::open(PJ_CONTEXT *ctx, const char *filename,
// ---------------------------------------------------------------------------
-#ifndef REMOVE_LEGACY_SUPPORT
-
-class FileLegacyAdapter : public File {
- PJ_CONTEXT *m_ctx;
- PAFile m_fp;
-
- FileLegacyAdapter(const FileLegacyAdapter &) = delete;
- FileLegacyAdapter &operator=(const FileLegacyAdapter &) = delete;
-
- protected:
- FileLegacyAdapter(const std::string &filename, PJ_CONTEXT *ctx, PAFile fp)
- : File(filename), m_ctx(ctx), m_fp(fp) {}
-
- public:
- ~FileLegacyAdapter() override;
-
- size_t read(void *buffer, size_t sizeBytes) override;
- size_t write(const void *, size_t) override { return 0; }
- bool seek(unsigned long long offset, int whence = SEEK_SET) override;
- unsigned long long tell() override;
- void reassign_context(PJ_CONTEXT *ctx) override { m_ctx = ctx; }
-
- // We may lie, but the real use case is only for network files
- bool hasChanged() const override { return false; }
-
- static std::unique_ptr<File> open(PJ_CONTEXT *ctx, const char *filename,
- FileAccess access);
-};
-
-// ---------------------------------------------------------------------------
-
-FileLegacyAdapter::~FileLegacyAdapter() { pj_ctx_fclose(m_ctx, m_fp); }
-
-// ---------------------------------------------------------------------------
-
-size_t FileLegacyAdapter::read(void *buffer, size_t sizeBytes) {
- return pj_ctx_fread(m_ctx, buffer, 1, sizeBytes, m_fp);
-}
-
-// ---------------------------------------------------------------------------
-
-bool FileLegacyAdapter::seek(unsigned long long offset, int whence) {
- if (offset != static_cast<unsigned long long>(static_cast<long>(offset))) {
- pj_log(m_ctx, PJ_LOG_ERROR,
- "Attempt at seeking to a 64 bit offset. Not supported yet");
- return false;
- }
- return pj_ctx_fseek(m_ctx, m_fp, static_cast<long>(offset), whence) == 0;
-}
-
-// ---------------------------------------------------------------------------
-
-unsigned long long FileLegacyAdapter::tell() {
- return pj_ctx_ftell(m_ctx, m_fp);
-}
-
-// ---------------------------------------------------------------------------
-
-std::unique_ptr<File>
-FileLegacyAdapter::open(PJ_CONTEXT *ctx, const char *filename, FileAccess) {
- auto fid = pj_ctx_fopen(ctx, filename, "rb");
- return std::unique_ptr<File>(fid ? new FileLegacyAdapter(filename, ctx, fid)
- : nullptr);
-}
-
-#endif // REMOVE_LEGACY_SUPPORT
-
-// ---------------------------------------------------------------------------
-
class FileApiAdapter : public File {
PJ_CONTEXT *m_ctx;
PROJ_FILE_HANDLE *m_fp;
@@ -954,12 +885,6 @@ std::unique_ptr<File> FileManager::open(PJ_CONTEXT *ctx, const char *filename,
}
return pj_network_file_open(ctx, filename);
}
-#ifndef REMOVE_LEGACY_SUPPORT
- // If the user has specified a legacy fileapi, use it
- if (ctx->fileapi_legacy != pj_get_default_fileapi()) {
- return FileLegacyAdapter::open(ctx, filename, access);
- }
-#endif
if (ctx->fileApi.open_cbk != nullptr) {
return FileApiAdapter::open(ctx, filename, access);
}
@@ -1444,10 +1369,10 @@ static bool dontReadUserWritableDirectory() {
return envVar != nullptr && envVar[0] != '\0';
}
-static void *
-pj_open_lib_internal(projCtx ctx, const char *name, const char *mode,
- void *(*open_file)(projCtx, const char *, const char *),
- char *out_full_filename, size_t out_full_filename_size) {
+static void *pj_open_lib_internal(
+ PJ_CONTEXT *ctx, const char *name, const char *mode,
+ void *(*open_file)(PJ_CONTEXT *, const char *, const char *),
+ char *out_full_filename, size_t out_full_filename_size) {
try {
std::string fname;
const char *sysname = nullptr;
@@ -1493,10 +1418,6 @@ pj_open_lib_internal(projCtx ctx, const char *name, const char *mode,
ctx, name, ctx->file_finder_user_data)) != nullptr)
;
- else if (ctx->file_finder_legacy != nullptr &&
- (sysname = ctx->file_finder_legacy(name)) != nullptr)
- ;
-
/* The user has search paths set */
else if (!ctx->search_paths.empty()) {
for (const auto &path : ctx->search_paths) {
@@ -1566,7 +1487,7 @@ pj_open_lib_internal(projCtx ctx, const char *name, const char *mode,
}
if (ctx->last_errno == 0 && errno != 0)
- pj_ctx_set_errno(ctx, errno);
+ proj_context_errno_set(ctx, errno);
pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "pj_open_lib(%s): call fopen(%s) - %s",
name, sysname, fid == nullptr ? "failed" : "succeeded");
@@ -1617,7 +1538,7 @@ std::vector<std::string> pj_get_default_searchpaths(PJ_CONTEXT *ctx) {
/* pj_open_file_with_manager() */
/************************************************************************/
-static void *pj_open_file_with_manager(projCtx ctx, const char *name,
+static void *pj_open_file_with_manager(PJ_CONTEXT *ctx, const char *name,
const char * /* mode */) {
return NS_PROJ::FileManager::open(ctx, name, NS_PROJ::FileAccess::READ_ONLY)
.release();
@@ -1639,7 +1560,7 @@ static NS_PROJ::io::DatabaseContextPtr getDBcontext(PJ_CONTEXT *ctx) {
/************************************************************************/
std::unique_ptr<NS_PROJ::File>
-NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
+NS_PROJ::FileManager::open_resource_file(PJ_CONTEXT *ctx, const char *name) {
if (ctx == nullptr) {
ctx = pj_get_default_ctx();
@@ -1666,7 +1587,7 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
pj_open_file_with_manager, nullptr,
0)));
if (file) {
- pj_ctx_set_errno(ctx, 0);
+ proj_context_errno_set(ctx, 0);
} else {
// For final network access attempt, use the new
// name.
@@ -1696,7 +1617,7 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
pj_open_file_with_manager, nullptr,
0)));
if (file) {
- pj_ctx_set_errno(ctx, 0);
+ proj_context_errno_set(ctx, 0);
}
}
} catch (const std::exception &e) {
@@ -1721,7 +1642,7 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
if (file) {
pj_log(ctx, PJ_LOG_DEBUG_MAJOR, "Using %s",
remote_file.c_str());
- pj_ctx_set_errno(ctx, 0);
+ proj_context_errno_set(ctx, 0);
}
}
}
@@ -1729,26 +1650,6 @@ NS_PROJ::FileManager::open_resource_file(projCtx ctx, const char *name) {
}
/************************************************************************/
-/* pj_open_lib() */
-/************************************************************************/
-
-#ifndef REMOVE_LEGACY_SUPPORT
-
-// Used by following legacy function
-static void *pj_ctx_fopen_adapter(projCtx ctx, const char *name,
- const char *mode) {
- return pj_ctx_fopen(ctx, name, mode);
-}
-
-// Legacy function
-PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) {
- return (PAFile)pj_open_lib_internal(ctx, name, mode, pj_ctx_fopen_adapter,
- nullptr, 0);
-}
-
-#endif // REMOVE_LEGACY_SUPPORT
-
-/************************************************************************/
/* pj_find_file() */
/************************************************************************/
@@ -1764,7 +1665,7 @@ PAFile pj_open_lib(projCtx ctx, const char *name, const char *mode) {
* @param out_full_filename_size size of out_full_filename.
* @return 1 if the file was found, 0 otherwise.
*/
-int pj_find_file(projCtx ctx, const char *short_filename,
+int pj_find_file(PJ_CONTEXT *ctx, const char *short_filename,
char *out_full_filename, size_t out_full_filename_size) {
auto file = std::unique_ptr<NS_PROJ::File>(
reinterpret_cast<NS_PROJ::File *>(pj_open_lib_internal(
@@ -1812,7 +1713,7 @@ static std::string trim(const std::string &s) {
/* pj_load_ini() */
/************************************************************************/
-void pj_load_ini(projCtx ctx) {
+void pj_load_ini(PJ_CONTEXT *ctx) {
if (ctx->iniFileLoaded)
return;
@@ -1891,19 +1792,6 @@ void pj_load_ini(projCtx ctx) {
//! @endcond
/************************************************************************/
-/* pj_set_finder() */
-/************************************************************************/
-
-void pj_set_finder(const char *(*new_finder)(const char *))
-
-{
- auto ctx = pj_get_default_ctx();
- if (ctx) {
- ctx->file_finder_legacy = new_finder;
- }
-}
-
-/************************************************************************/
/* proj_context_set_file_finder() */
/************************************************************************/
@@ -1974,19 +1862,6 @@ void proj_context_set_search_paths(PJ_CONTEXT *ctx, int count_paths,
}
/************************************************************************/
-/* pj_set_searchpath() */
-/* */
-/* Path control for callers that can't practically provide */
-/* pj_set_finder() style callbacks. Call with (0,NULL) as args */
-/* to clear the searchpath set. */
-/************************************************************************/
-
-void pj_set_searchpath(int count, const char **path) {
- proj_context_set_search_paths(nullptr, count,
- const_cast<const char *const *>(path));
-}
-
-/************************************************************************/
/* proj_context_set_ca_bundle_path() */
/************************************************************************/
diff --git a/src/gauss.cpp b/src/gauss.cpp
index a34a8f5b..96bd5166 100644
--- a/src/gauss.cpp
+++ b/src/gauss.cpp
@@ -81,7 +81,7 @@ void *pj_gauss_ini(double e, double phi0, double *chi, double *rc) {
return ((void *)en);
}
-PJ_LP pj_gauss(projCtx ctx, PJ_LP elp, const void *data) {
+PJ_LP pj_gauss(PJ_CONTEXT *ctx, PJ_LP elp, const void *data) {
const struct GAUSS *en = (const struct GAUSS *)data;
PJ_LP slp;
(void) ctx;
@@ -93,7 +93,7 @@ PJ_LP pj_gauss(projCtx ctx, PJ_LP elp, const void *data) {
return(slp);
}
-PJ_LP pj_inv_gauss(projCtx ctx, PJ_LP slp, const void *data) {
+PJ_LP pj_inv_gauss(PJ_CONTEXT *ctx, PJ_LP slp, const void *data) {
const struct GAUSS *en = (const struct GAUSS *)data;
PJ_LP elp;
double num;
@@ -109,6 +109,6 @@ PJ_LP pj_inv_gauss(projCtx ctx, PJ_LP slp, const void *data) {
}
/* convergence failed */
if (!i)
- pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST);
+ proj_context_errno_set(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST);
return (elp);
}
diff --git a/src/generic_inverse.cpp b/src/generic_inverse.cpp
index a15cfae1..ddd5060b 100644
--- a/src/generic_inverse.cpp
+++ b/src/generic_inverse.cpp
@@ -109,6 +109,6 @@ PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial) {
lp.phi = M_HALFPI;
}
}
- pj_ctx_set_errno(P->ctx, PJD_ERR_NON_CONVERGENT);
+ proj_context_errno_set(P->ctx, PJD_ERR_NON_CONVERGENT);
return lp;
}
diff --git a/src/geodesic.c b/src/geodesic.c
index 7d612d3f..53ec9ed6 100644
--- a/src/geodesic.c
+++ b/src/geodesic.c
@@ -18,7 +18,7 @@
*
* See the comments in geodesic.h for documentation.
*
- * Copyright (c) Charles Karney (2012-2019) <charles@karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
*/
@@ -28,15 +28,6 @@
#include <limits.h>
#include <float.h>
-#if !defined(HAVE_C99_MATH)
-#if defined(PROJ_LIB)
-/* PROJ requires C99 so HAVE_C99_MATH is implicit */
-#define HAVE_C99_MATH 1
-#else
-#define HAVE_C99_MATH 0
-#endif
-#endif
-
#if !defined(__cplusplus)
#define nullptr 0
#endif
@@ -88,19 +79,7 @@ static void Init() {
tolb = tol0 * tol2;
xthresh = 1000 * tol2;
degree = pi/180;
-#if defined(NAN)
- NaN = NAN; /* NAN is defined in C99 */
-#else
-#if HAVE_C99_MATH
NaN = nan("0");
-#else
- {
- real minus1 = -1;
- /* cppcheck-suppress wrongmathcall */
- NaN = sqrt(minus1);
- }
-#endif
-#endif
init = 1;
}
}
@@ -116,95 +95,6 @@ enum captype {
OUT_ALL = 0x7F80U
};
-#if HAVE_C99_MATH
-#define hypotx hypot
-/* no need to redirect log1px, since it's only used by atanhx */
-#define atanhx atanh
-#define copysignx copysign
-#define cbrtx cbrt
-#define remainderx remainder
-#define remquox remquo
-#else
-/* Replacements for C99 math functions */
-
-static real hypotx(real x, real y) {
- x = fabs(x); y = fabs(y);
- if (x < y) {
- x /= y; /* y is nonzero */
- return y * sqrt(1 + x * x);
- } else {
- y /= (x != 0 ? x : 1);
- return x * sqrt(1 + y * y);
- }
-}
-
-static real log1px(real x) {
- volatile real
- y = 1 + x,
- z = y - 1;
- /* Here's the explanation for this magic: y = 1 + z, exactly, and z
- * approx x, thus log(y)/z (which is nearly constant near z = 0) returns
- * a good approximation to the true log(1 + x)/x. The multiplication x *
- * (log(y)/z) introduces little additional error. */
- return z == 0 ? x : x * log(y) / z;
-}
-
-static real atanhx(real x) {
- real y = fabs(x); /* Enforce odd parity */
- y = log1px(2 * y/(1 - y))/2;
- return x > 0 ? y : (x < 0 ? -y : x); /* atanh(-0.0) = -0.0 */
-}
-
-static real copysignx(real x, real y) {
- /* 1/y trick to get the sign of -0.0 */
- return fabs(x) * (y < 0 || (y == 0 && 1/y < 0) ? -1 : 1);
-}
-
-static real cbrtx(real x) {
- real y = pow(fabs(x), 1/(real)(3)); /* Return the real cube root */
- return x > 0 ? y : (x < 0 ? -y : x); /* cbrt(-0.0) = -0.0 */
-}
-
-static real remainderx(real x, real y) {
- real z;
- y = fabs(y); /* The result doesn't depend on the sign of y */
- z = fmod(x, y);
- if (z == 0)
- /* This shouldn't be necessary. However, before version 14 (2015),
- * Visual Studio had problems dealing with -0.0. Specifically
- * VC 10,11,12 and 32-bit compile: fmod(-0.0, 360.0) -> +0.0
- * python 2.7 on Windows 32-bit machines has the same problem. */
- z = copysignx(z, x);
- else if (2 * fabs(z) == y)
- z -= fmod(x, 2 * y) - z; /* Implement ties to even */
- else if (2 * fabs(z) > y)
- z += (z < 0 ? y : -y); /* Fold remaining cases to (-y/2, y/2) */
- return z;
-}
-
-static real remquox(real x, real y, int* n) {
- real z = remainderx(x, y);
- if (n) {
- real
- a = remainderx(x, 2 * y),
- b = remainderx(x, 4 * y),
- c = remainderx(x, 8 * y);
- *n = (a > z ? 1 : (a < z ? -1 : 0));
- *n += (b > a ? 2 : (b < a ? -2 : 0));
- *n += (c > b ? 4 : (c < b ? -4 : 0));
- if (y < 0) *n *= -1;
- if (y != 0) {
- if (x/y > 0 && *n <= 0)
- *n += 8;
- else if (x/y < 0 && *n >= 0)
- *n -= 8;
- }
- }
- return z;
-}
-
-#endif
-
static real sq(real x) { return x * x; }
static real sumx(real u, real v, real* t) {
@@ -237,13 +127,13 @@ static void swapx(real* x, real* y)
{ real t = *x; *x = *y; *y = t; }
static void norm2(real* sinx, real* cosx) {
- real r = hypotx(*sinx, *cosx);
+ real r = hypot(*sinx, *cosx);
*sinx /= r;
*cosx /= r;
}
static real AngNormalize(real x) {
- x = remainderx(x, (real)(360));
+ x = remainder(x, (real)(360));
return x != -180 ? x : 180;
}
@@ -275,7 +165,7 @@ static void sincosdx(real x, real* sinx, real* cosx) {
/* In order to minimize round-off errors, this function exactly reduces
* the argument to the range [-45, 45] before converting it to radians. */
real r, s, c; int q;
- r = remquox(x, (real)(90), &q);
+ r = remquo(x, (real)(90), &q);
/* now abs(r) <= 45 */
r *= degree;
/* Possibly could call the gnu extension sincos */
@@ -396,7 +286,7 @@ void geod_init(struct geod_geodesic* g, real a, real f) {
g->b = g->a * g->f1;
g->c2 = (sq(g->a) + sq(g->b) *
(g->e2 == 0 ? 1 :
- (g->e2 > 0 ? atanhx(sqrt(g->e2)) : atan(sqrt(-g->e2))) /
+ (g->e2 > 0 ? atanh(sqrt(g->e2)) : atan(sqrt(-g->e2))) /
sqrt(fabs(g->e2))))/2; /* authalic radius squared */
/* The sig12 threshold for "really short". Using the auxiliary sphere
* solution with dnm computed at (bet1 + bet2) / 2, the relative error in the
@@ -446,7 +336,7 @@ static void geod_lineinit_int(struct geod_geodesicline* l,
l->salp0 = l->salp1 * cbet1; /* alp0 in [0, pi/2 - |bet1|] */
/* Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following
* is slightly better (consider the case salp1 = 0). */
- l->calp0 = hypotx(l->calp1, l->salp1 * sbet1);
+ l->calp0 = hypot(l->calp1, l->salp1 * sbet1);
/* Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
* sig = 0 is nearest northward crossing of equator.
* With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
@@ -550,9 +440,8 @@ real geod_genposition(const struct geod_geodesicline* l,
(pS12 ? GEOD_AREA : GEOD_NONE);
outmask &= l->caps & OUT_ALL;
- if (!( /*Init() &&*/
- (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) ))
- /* Uninitialized or impossible distance calculation requested */
+ if (!( (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) ))
+ /* Impossible distance calculation requested */
return NaN;
if (flags & GEOD_ARCMODE) {
@@ -617,7 +506,7 @@ real geod_genposition(const struct geod_geodesicline* l,
/* sin(bet2) = cos(alp0) * sin(sig2) */
sbet2 = l->calp0 * ssig2;
/* Alt: cbet2 = hypot(csig2, salp0 * ssig2); */
- cbet2 = hypotx(l->salp0, l->calp0 * csig2);
+ cbet2 = hypot(l->salp0, l->calp0 * csig2);
if (cbet2 == 0)
/* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case */
cbet2 = csig2 = tiny;
@@ -630,7 +519,7 @@ real geod_genposition(const struct geod_geodesicline* l,
s12_a12;
if (outmask & GEOD_LONGITUDE) {
- real E = copysignx(1, l->salp0); /* east or west going? */
+ real E = copysign(1, l->salp0); /* east or west going? */
/* tan(omg2) = sin(alp0) * tan(sig2) */
somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */
/* omg12 = omg2 - omg1 */
@@ -1045,7 +934,7 @@ static real geod_geninverse_int(const struct geod_geodesic* g,
real
/* From Lambda12: sin(alp1) * cos(bet1) = sin(alp0) */
salp0 = salp1 * cbet1,
- calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */
+ calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */
real alp12;
if (calp0 != 0 && salp0 != 0) {
real
@@ -1279,8 +1168,8 @@ real Astroid(real x, real y) {
* of precision due to cancellation. The result is unchanged because
* of the way the T is used in definition of u. */
T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc); /* T3 = (r * t)^3 */
- /* N.B. cbrtx always returns the real root. cbrtx(-8) = -2. */
- T = cbrtx(T3); /* T = r * t */
+ /* N.B. cbrt always returns the real root. cbrt(-8) = -2. */
+ T = cbrt(T3); /* T = r * t */
/* T can be zero; but then r2 / T -> 0. */
u += T + (T != 0 ? r2 / T : 0);
} else {
@@ -1348,7 +1237,7 @@ real InverseStart(const struct geod_geodesic* g,
sbet12 + cbet2 * sbet1 * sq(somg12) / (1 + comg12) :
sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
- ssig12 = hypotx(salp1, calp1);
+ ssig12 = hypot(salp1, calp1);
csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
if (shortline && ssig12 < g->etol2) {
@@ -1500,7 +1389,7 @@ real Lambda12(const struct geod_geodesic* g,
/* sin(alp1) * cos(bet1) = sin(alp0) */
salp0 = salp1 * cbet1;
- calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */
+ calp0 = hypot(calp1, salp1 * sbet1); /* calp0 > 0 */
/* tan(bet1) = tan(sig1) * cos(alp1)
* tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1) */
@@ -1850,8 +1739,8 @@ int transit(real lon1, real lon2) {
int transitdirect(real lon1, real lon2) {
/* Compute exactly the parity of
int(ceil(lon2 / 360)) - int(ceil(lon1 / 360)) */
- lon1 = remainderx(lon1, (real)(720));
- lon2 = remainderx(lon2, (real)(720));
+ lon1 = remainder(lon1, (real)(720));
+ lon2 = remainder(lon2, (real)(720));
return ( (lon2 <= 0 && lon2 > -360 ? 1 : 0) -
(lon1 <= 0 && lon1 > -360 ? 1 : 0) );
}
@@ -1891,7 +1780,7 @@ void accneg(real s[]) {
void accrem(real s[], real y) {
/* Reduce to [-y/2, y/2]. */
- s[0] = remainderx(s[0], y);
+ s[0] = remainder(s[0], y);
accadd(s, (real)(0));
}
@@ -2093,7 +1982,7 @@ real areareduceA(real area[], real area0,
real areareduceB(real area, real area0,
int crossings, boolx reverse, boolx sign) {
- area = remainderx(area, area0);
+ area = remainder(area, area0);
if (crossings & 1)
area += (area < 0 ? 1 : -1) * area0/2;
/* area is with the clockwise sense. If !reverse convert to
diff --git a/src/geodesic.h b/src/geodesic.h
index b21e6c8c..548fbf47 100644
--- a/src/geodesic.h
+++ b/src/geodesic.h
@@ -107,12 +107,12 @@
* twice about restructuring the internals of the C code since this may make
* porting fixes from the C++ code more difficult.
*
- * Copyright (c) Charles Karney (2012-2019) <charles@karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
*
* This library was distributed with
- * <a href="../index.html">GeographicLib</a> 1.50.
+ * <a href="../index.html">GeographicLib</a> 1.51.
**********************************************************************/
#if !defined(GEODESIC_H)
@@ -127,7 +127,7 @@
* The minor version of the geodesic library. (This tracks the version of
* GeographicLib.)
**********************************************************************/
-#define GEODESIC_VERSION_MINOR 50
+#define GEODESIC_VERSION_MINOR 51
/**
* The patch level of the geodesic library. (This tracks the version of
* GeographicLib.)
diff --git a/src/grids.cpp b/src/grids.cpp
index 8065813a..871e21ed 100644
--- a/src/grids.cpp
+++ b/src/grids.cpp
@@ -197,7 +197,7 @@ GTXVerticalShiftGrid *GTXVerticalShiftGrid::open(PJ_CONTEXT *ctx,
/* Read the header. */
/* -------------------------------------------------------------------- */
if (fp->read(header, sizeof(header)) != sizeof(header)) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -223,7 +223,7 @@ GTXVerticalShiftGrid *GTXVerticalShiftGrid::open(PJ_CONTEXT *ctx,
if (xorigin < -360 || xorigin > 360 || yorigin < -90 || yorigin > 90) {
pj_log(ctx, PJ_LOG_ERROR,
"gtx file header has invalid extents, corrupt?");
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -258,7 +258,7 @@ bool GTXVerticalShiftGrid::valueAt(int x, int y, float &out) const {
m_fp->seek(40 + sizeof(float) * (y * m_width + x));
if (m_fp->read(&out, sizeof(out)) != sizeof(out)) {
- pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return false;
}
if (IS_LSB) {
@@ -1389,7 +1389,7 @@ VerticalShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) {
auto set = std::unique_ptr<VerticalShiftGridSet>(
GTiffVGridShiftSet::open(ctx, std::move(fp), actualName));
if (!set)
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return set;
#else
pj_log(ctx, PJ_LOG_ERROR,
@@ -1570,7 +1570,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
/* Read the header. */
/* -------------------------------------------------------------------- */
if (fp->read(header, sizeof(header)) != sizeof(header)) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -1590,7 +1590,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
if (*((int *)(header + 8)) != 12) {
pj_log(ctx, PJ_LOG_ERROR,
"NTv1 grid shift file has wrong record count, corrupt?");
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -1609,7 +1609,7 @@ NTv1Grid *NTv1Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
extent.resY > 1e-10)) {
pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s",
filename.c_str());
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
const int columns = static_cast<int>(
@@ -1631,7 +1631,7 @@ bool NTv1Grid::valueAt(int x, int y, bool compensateNTConvention,
m_fp->seek(192 + 2 * sizeof(double) * (y * m_width + m_width - 1 - x));
if (m_fp->read(&two_doubles[0], sizeof(two_doubles)) !=
sizeof(two_doubles)) {
- pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return false;
}
if (IS_LSB) {
@@ -1692,7 +1692,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
/* Read the header. */
/* -------------------------------------------------------------------- */
if (fp->read(header, sizeof(header)) != sizeof(header)) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -1718,7 +1718,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
extent.resX > 1e-10 && extent.resY > 1e-10)) {
pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s",
filename.c_str());
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
int width;
@@ -1726,7 +1726,7 @@ CTable2Grid *CTable2Grid::open(PJ_CONTEXT *ctx, std::unique_ptr<File> fp,
memcpy(&width, header + 128, 4);
memcpy(&height, header + 132, 4);
if (width <= 0 || height <= 0) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
extent.east = extent.west + (width - 1) * extent.resX;
@@ -1744,7 +1744,7 @@ bool CTable2Grid::valueAt(int x, int y, bool compensateNTConvention,
float two_floats[2];
m_fp->seek(160 + 2 * sizeof(float) * (y * m_width + x));
if (m_fp->read(&two_floats[0], sizeof(two_floats)) != sizeof(two_floats)) {
- pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return false;
}
if (!IS_LSB) {
@@ -1828,7 +1828,7 @@ bool NTv2Grid::valueAt(int x, int y, bool compensateNTConvention,
4 * sizeof(float) *
(static_cast<unsigned long long>(y) * m_width + m_width - 1 - x));
if (m_fp->read(&two_float[0], sizeof(two_float)) != sizeof(two_float)) {
- pj_ctx_set_errno(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(m_ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return false;
}
if (m_mustSwap) {
@@ -1862,14 +1862,14 @@ std::unique_ptr<NTv2GridSet> NTv2GridSet::open(PJ_CONTEXT *ctx,
/* Read the header. */
/* -------------------------------------------------------------------- */
if (fpRaw->read(header, sizeof(header)) != sizeof(header)) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
constexpr int OFFSET_GS_TYPE = 56;
if (memcmp(header + OFFSET_GS_TYPE, "SECONDS", 7) != 0) {
pj_log(ctx, PJ_LOG_ERROR, "Only GS_TYPE=SECONDS is supported");
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -1899,12 +1899,12 @@ std::unique_ptr<NTv2GridSet> NTv2GridSet::open(PJ_CONTEXT *ctx,
for (unsigned subfile = 0; subfile < num_subfiles; subfile++) {
// Read header
if (fpRaw->read(header, sizeof(header)) != sizeof(header)) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
if (strncmp(header, "SUB_NAME", 8) != 0) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -1946,7 +1946,7 @@ std::unique_ptr<NTv2GridSet> NTv2GridSet::open(PJ_CONTEXT *ctx,
extent.resY > 1e-10)) {
pj_log(ctx, PJ_LOG_ERROR, "Inconsistent georeferencing for %s",
filename.c_str());
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
const int columns = static_cast<int>(
@@ -1966,7 +1966,7 @@ std::unique_ptr<NTv2GridSet> NTv2GridSet::open(PJ_CONTEXT *ctx,
pj_log(ctx, PJ_LOG_ERROR,
"GS_COUNT(%u) does not match expected cells (%dx%d)",
gs_count, columns, rows);
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return nullptr;
}
@@ -2367,7 +2367,7 @@ HorizontalShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) {
auto set = std::unique_ptr<HorizontalShiftGridSet>(
GTiffHGridShiftSet::open(ctx, std::move(fp), actualName));
if (!set)
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return set;
#else
pj_log(ctx, PJ_LOG_ERROR,
@@ -2703,7 +2703,7 @@ GenericShiftGridSet::open(PJ_CONTEXT *ctx, const std::string &filename) {
auto set = std::unique_ptr<GenericShiftGridSet>(
GTiffGenericGridShiftSet::open(ctx, std::move(fp), actualName));
if (!set)
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return set;
#else
pj_log(ctx, PJ_LOG_ERROR,
@@ -2786,11 +2786,12 @@ ListOfGenericGrids pj_generic_grid_init(PJ *P, const char *gridkey) {
if (!gridSet) {
if (!canFail) {
if (proj_context_errno(P->ctx) != PJD_ERR_NETWORK_ERROR) {
- pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
}
return {};
}
- pj_ctx_set_errno(P->ctx, 0); // don't treat as a persistent error
+ proj_context_errno_set(P->ctx,
+ 0); // don't treat as a persistent error
} else {
grids.emplace_back(std::move(gridSet));
}
@@ -2830,11 +2831,11 @@ static ListOfHGrids getListOfGridSets(PJ_CONTEXT *ctx, const char *grids) {
if (!gridSet) {
if (!canFail) {
if (proj_context_errno(ctx) != PJD_ERR_NETWORK_ERROR) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
}
return {};
}
- pj_ctx_set_errno(ctx, 0); // don't treat as a persistent error
+ proj_context_errno_set(ctx, 0); // don't treat as a persistent error
} else {
list.emplace_back(std::move(gridSet));
}
@@ -2948,7 +2949,7 @@ static PJ_LP pj_hgrid_interpolate(PJ_LP t, const HorizontalShiftGrid *grid,
#define MAX_ITERATIONS 10
#define TOL 1e-12
-static PJ_LP pj_hgrid_apply_internal(projCtx ctx, PJ_LP in,
+static PJ_LP pj_hgrid_apply_internal(PJ_CONTEXT *ctx, PJ_LP in,
PJ_DIRECTION direction,
const HorizontalShiftGrid *grid,
HorizontalShiftGridSet *gridset,
@@ -3066,7 +3067,7 @@ PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp,
HorizontalShiftGridSet *gridset = nullptr;
const auto grid = findGrid(grids, lp, gridset);
if (!grid) {
- pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(ctx, PJD_ERR_GRID_AREA);
return out;
}
if (grid->isNullGrid()) {
@@ -3082,7 +3083,7 @@ PJ_LP pj_hgrid_apply(PJ_CONTEXT *ctx, const ListOfHGrids &grids, PJ_LP lp,
}
if (out.lam == HUGE_VAL || out.phi == HUGE_VAL)
- pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(ctx, PJD_ERR_GRID_AREA);
return out;
}
@@ -3098,7 +3099,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) {
HorizontalShiftGridSet *gridset = nullptr;
const auto grid = findGrid(grids, lp, gridset);
if (!grid) {
- pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(P->ctx, PJD_ERR_GRID_AREA);
return out;
}
@@ -3107,7 +3108,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) {
if (!extent.isGeographic) {
pj_log(P->ctx, PJ_LOG_ERROR,
"Can only handle grids referenced in a geographic CRS");
- pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return out;
}
@@ -3130,7 +3131,7 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) {
}
if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) {
- pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(P->ctx, PJD_ERR_GRID_AREA);
}
return out;
@@ -3157,7 +3158,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids,
}
}
if (!grid) {
- pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(ctx, PJD_ERR_GRID_AREA);
return HUGE_VAL;
}
if (grid->isNullGrid()) {
@@ -3168,7 +3169,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids,
if (!extent.isGeographic) {
pj_log(ctx, PJ_LOG_ERROR,
"Can only handle grids referenced in a geographic CRS");
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return HUGE_VAL;
}
@@ -3200,7 +3201,7 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids,
if (!(grid_ix >= 0 && grid_ix < grid->width())) {
// in the unlikely case we end up here...
pj_log(ctx, PJ_LOG_ERROR, "grid_ix not in grid");
- pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
+ proj_context_errno_set(ctx, PJD_ERR_GRID_AREA);
return HUGE_VAL;
}
int grid_iy = static_cast<int>(lround(floor(grid_y)));
@@ -3309,11 +3310,12 @@ ListOfVGrids pj_vgrid_init(PJ *P, const char *gridkey) {
if (!gridSet) {
if (!canFail) {
if (proj_context_errno(P->ctx) != PJD_ERR_NETWORK_ERROR) {
- pj_ctx_set_errno(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
}
return {};
}
- pj_ctx_set_errno(P->ctx, 0); // don't treat as a persistent error
+ proj_context_errno_set(P->ctx,
+ 0); // don't treat as a persistent error
} else {
grids.emplace_back(std::move(gridSet));
}
@@ -3377,7 +3379,7 @@ bool pj_bilinear_interpolation_three_samples(
if (!extent.isGeographic) {
pj_log(ctx, PJ_LOG_ERROR,
"Can only handle grids referenced in a geographic CRS");
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ proj_context_errno_set(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
return false;
}
@@ -3442,50 +3444,3 @@ bool pj_bilinear_interpolation_three_samples(
}
NS_PROJ_END
-
-/************************************************************************/
-/* pj_apply_gridshift() */
-/* */
-/* This is the externally callable interface - part of the */
-/* public API - though it is not used internally any more and I */
-/* doubt it is used by any other applications. But we preserve */
-/* it to honour our public api. */
-/************************************************************************/
-
-int pj_apply_gridshift(projCtx ctx, const char *nadgrids, int inverse,
- long point_count, int point_offset, double *x, double *y,
- double * /*z */)
-
-{
- auto hgrids = NS_PROJ::getListOfGridSets(ctx, nadgrids);
- if (hgrids.empty()) {
- pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
- return 1;
- }
-
- for (long i = 0; i < point_count; i++) {
- PJ_LP input;
-
- long io = i * point_offset;
- input.phi = y[io];
- input.lam = x[io];
-
- auto output =
- pj_hgrid_apply(ctx, hgrids, input, inverse ? PJ_INV : PJ_FWD);
-
- if (output.lam != HUGE_VAL) {
- y[io] = output.phi;
- x[io] = output.lam;
- } else {
- if (ctx->debug_level >= PJ_LOG_DEBUG_MAJOR) {
- pj_log(ctx, PJ_LOG_DEBUG_MAJOR,
- "pj_apply_gridshift(): failed to find a grid shift "
- "table for\n"
- " location (%.7fdW,%.7fdN)",
- x[io] * RAD_TO_DEG, y[io] * RAD_TO_DEG);
- }
- }
- }
-
- return 0;
-}
diff --git a/src/init.cpp b/src/init.cpp
index 101fc8ad..1e89402d 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,7 +1,7 @@
/******************************************************************************
* Project: PROJ.4
* Purpose: Initialize projection object from string definition. Includes
- * pj_init(), pj_init_plus() and pj_free() function.
+ * pj_init(), and pj_init_plus() function.
* Author: Gerald Evenden, Frank Warmerdam <warmerdam@pobox.com>
*
******************************************************************************
@@ -55,7 +55,7 @@ static paralist *string_to_paralist (PJ_CONTEXT *ctx, char *definition) {
/* Keep a handle to the start of the list, so we have something to return */
auto param = pj_mkparam_ws (c, &c);
if (nullptr==param) {
- pj_dealloc_params (ctx, first, ENOMEM);
+ free_params (ctx, first, ENOMEM);
return nullptr;
}
if (nullptr==last) {
@@ -84,7 +84,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
char *buffer = nullptr;
size_t n;
- fname = static_cast<char*>(pj_malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3));
+ fname = static_cast<char*>(malloc (MAX_PATH_FILENAME+ID_TAG_MAX+3));
if (nullptr==fname) {
return nullptr;
}
@@ -96,7 +96,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
else
key += 5;
if (MAX_PATH_FILENAME + ID_TAG_MAX + 2 < strlen (key)) {
- pj_dealloc (fname);
+ free (fname);
return nullptr;
}
memmove (fname, key, strlen (key) + 1);
@@ -105,7 +105,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
section = strrchr(fname, ':');
if (nullptr==section) {
proj_context_errno_set (ctx, PJD_ERR_NO_COLON_IN_INIT_STRING);
- pj_dealloc (fname);
+ free (fname);
return nullptr;
}
*section = 0;
@@ -117,7 +117,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
auto file = NS_PROJ::FileManager::open_resource_file(ctx, fname);
if (nullptr==file) {
- pj_dealloc (fname);
+ free (fname);
proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE);
return nullptr;
}
@@ -131,7 +131,7 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
line = file->read_line(MAX_LINE_LENGTH, maxLenReached, eofReached);
/* End of file? */
if (maxLenReached || eofReached) {
- pj_dealloc (fname);
+ free (fname);
proj_context_errno_set (ctx, PJD_ERR_NO_OPTION_IN_INIT_FILE);
return nullptr;
}
@@ -149,9 +149,9 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
}
/* We're at the first line of the right section - copy line to buffer */
- buffer = static_cast<char*>(pj_malloc (current_buffer_size));
+ buffer = static_cast<char*>(malloc (current_buffer_size));
if (nullptr==buffer) {
- pj_dealloc (fname);
+ free (fname);
return nullptr;
}
@@ -183,22 +183,22 @@ static char *get_init_string (PJ_CONTEXT *ctx, const char *name) {
pj_chomp (&line[0]); /* Remove '#' style comments */
next_length = strlen (line.data()) + buffer_length + 2;
if (next_length > current_buffer_size) {
- char *b = static_cast<char*>(pj_malloc (2 * current_buffer_size));
+ char *b = static_cast<char*>(malloc (2 * current_buffer_size));
if (nullptr==b) {
- pj_dealloc (buffer);
+ free (buffer);
buffer = nullptr;
break;
}
strcpy (b, buffer);
current_buffer_size *= 2;
- pj_dealloc (buffer);
+ free (buffer);
buffer = b;
}
buffer[buffer_length] = ' ';
strcpy (buffer + buffer_length + 1, line.data());
}
- pj_dealloc (fname);
+ free (fname);
if (nullptr==buffer)
return nullptr;
pj_shrink (buffer);
@@ -257,7 +257,7 @@ Expand key from buffer or (if not in buffer) from init file
PJ* src;
const char* proj_string;
- pj_ctx_set_errno( ctx, 0 );
+ proj_context_errno_set( ctx, 0 );
if( !allow_init_epsg ) {
pj_log (ctx, PJ_LOG_TRACE, "%s expansion disallowed", xkey);
@@ -306,7 +306,7 @@ Expand key from buffer or (if not in buffer) from init file
definition,
init_items->param,
init_items->next ? init_items->next->param : "(empty)");
- pj_dealloc (definition);
+ free (definition);
if (nullptr==init_items)
return nullptr;
@@ -400,90 +400,6 @@ paralist *pj_expand_init(PJ_CONTEXT *ctx, paralist *init) {
/************************************************************************/
-/* pj_init_plus() */
-/* */
-/* Same as pj_init() except it takes one argument string with */
-/* individual arguments preceded by '+', such as "+proj=utm */
-/* +zone=11 +ellps=WGS84". */
-/************************************************************************/
-
-PJ *
-pj_init_plus( const char *definition )
-
-{
- return pj_init_plus_ctx( pj_get_default_ctx(), definition );
-}
-
-PJ *
-pj_init_plus_ctx( projCtx ctx, const char *definition )
-{
-#define MAX_ARG 200
- char *argv[MAX_ARG];
- char *defn_copy;
- int argc = 0, i, blank_count = 0;
- PJ *result = nullptr;
-
- /* make a copy that we can manipulate */
- defn_copy = (char *) pj_malloc( strlen(definition)+1 );
- if (!defn_copy)
- return nullptr;
- strcpy( defn_copy, definition );
-
- /* split into arguments based on '+' and trim white space */
-
- for( i = 0; defn_copy[i] != '\0'; i++ )
- {
- switch( defn_copy[i] )
- {
- case '+':
- if( i == 0 || defn_copy[i-1] == '\0' || blank_count > 0 )
- {
- /* trim trailing spaces from the previous param */
- if( blank_count > 0 )
- {
- defn_copy[i - blank_count] = '\0';
- blank_count = 0;
- }
-
- if( argc+1 == MAX_ARG )
- {
- pj_dalloc( defn_copy );
- pj_ctx_set_errno( ctx, PJD_ERR_UNPARSEABLE_CS_DEF );
- return nullptr;
- }
-
- argv[argc++] = defn_copy + i + 1;
- }
- break;
-
- case ' ':
- case '\t':
- case '\n':
- /* trim leading spaces from the current param */
- if( i == 0 || defn_copy[i-1] == '\0' || argc == 0 || argv[argc-1] == defn_copy + i )
- defn_copy[i] = '\0';
- else
- blank_count++;
- break;
-
- default:
- /* reset blank_count */
- blank_count = 0;
- }
- }
- /* trim trailing spaces from the last param */
- defn_copy[i - blank_count] = '\0';
-
- /* perform actual initialization */
- result = pj_init_ctx( ctx, argc, argv );
-
- pj_dalloc( defn_copy );
- return result;
-}
-
-
-
-/************************************************************************/
/* pj_init() */
/* */
/* Main entry point for initialing a PJ projections */
@@ -492,11 +408,6 @@ pj_init_plus_ctx( projCtx ctx, const char *definition )
/* large enough to hold projection specific parameters. */
/************************************************************************/
-PJ *
-pj_init(int argc, char **argv) {
- return pj_init_ctx( pj_get_default_ctx(), argc, argv );
-}
-
static PJ_CONSTRUCTOR locate_constructor (const char *name) {
int i;
@@ -511,15 +422,7 @@ static PJ_CONSTRUCTOR locate_constructor (const char *name) {
PJ *
-pj_init_ctx(projCtx ctx, int argc, char **argv) {
- /* Legacy interface: allow init=epsg:XXXX syntax by default */
- int allow_init_epsg = proj_context_get_use_proj4_init_rules(ctx, TRUE);
- return pj_init_ctx_with_allow_init_epsg(ctx, argc, argv, allow_init_epsg);
-}
-
-
-PJ *
-pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_init_epsg) {
+pj_init_ctx_with_allow_init_epsg(PJ_CONTEXT *ctx, int argc, char **argv, int allow_init_epsg) {
const char *s;
char *name;
PJ_CONSTRUCTOR proj;
@@ -538,7 +441,7 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
ctx->last_errno = 0;
if (argc <= 0) {
- pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS);
+ proj_context_errno_set (ctx, PJD_ERR_NO_ARGS);
return nullptr;
}
@@ -552,13 +455,13 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
/* can't have nested pipelines directly */
if (n_pipelines > 1) {
- pj_ctx_set_errno (ctx, PJD_ERR_MALFORMED_PIPELINE);
+ proj_context_errno_set (ctx, PJD_ERR_MALFORMED_PIPELINE);
return nullptr;
}
/* don't allow more than one +init in non-pipeline operations */
if (n_pipelines == 0 && n_inits > 1) {
- pj_ctx_set_errno (ctx, PJD_ERR_TOO_MANY_INITS);
+ proj_context_errno_set (ctx, PJD_ERR_TOO_MANY_INITS);
return nullptr;
}
@@ -566,14 +469,14 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
/* put arguments into internal linked list */
start = curr = pj_mkparam(argv[0]);
if (!curr) {
- pj_dealloc_params (ctx, start, ENOMEM);
+ free_params (ctx, start, ENOMEM);
return nullptr;
}
for (i = 1; i < argc; ++i) {
curr->next = pj_mkparam(argv[i]);
if (!curr->next) {
- pj_dealloc_params (ctx, start, ENOMEM);
+ free_params (ctx, start, ENOMEM);
return nullptr;
}
curr = curr->next;
@@ -588,31 +491,31 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
if (init && n_pipelines == 0) {
init = pj_expand_init_internal (ctx, init, allow_init_epsg);
if (!init) {
- pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS);
+ free_params (ctx, start, PJD_ERR_NO_ARGS);
return nullptr;
}
}
if (ctx->last_errno) {
- pj_dealloc_params (ctx, start, ctx->last_errno);
+ free_params (ctx, start, ctx->last_errno);
return nullptr;
}
/* Find projection selection */
curr = pj_param_exists (start, "proj");
if (nullptr==curr) {
- pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
+ free_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
return nullptr;
}
name = curr->param;
if (strlen (name) < 6) {
- pj_dealloc_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
+ free_params (ctx, start, PJD_ERR_PROJ_NOT_NAMED);
return nullptr;
}
name += 5;
proj = locate_constructor (name);
if (nullptr==proj) {
- pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID);
+ free_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID);
return nullptr;
}
@@ -621,7 +524,7 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
/* Allocate projection structure */
PIN = proj(nullptr);
if (nullptr==PIN) {
- pj_dealloc_params (ctx, start, ENOMEM);
+ free_params (ctx, start, ENOMEM);
return nullptr;
}
@@ -820,7 +723,7 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
PIN->from_greenwich = 0.0;
/* Private object for the geodesic functions */
- PIN->geod = static_cast<struct geod_geodesic*>(pj_calloc (1, sizeof (struct geod_geodesic)));
+ PIN->geod = static_cast<struct geod_geodesic*>(calloc (1, sizeof (struct geod_geodesic)));
if (nullptr==PIN->geod)
return pj_default_destructor (PIN, ENOMEM);
geod_init(PIN->geod, PIN->a, (1 - sqrt (1 - PIN->es)));
@@ -829,7 +732,7 @@ pj_init_ctx_with_allow_init_epsg(projCtx ctx, int argc, char **argv, int allow_i
err = proj_errno_reset (PIN);
PIN = proj(PIN);
if (proj_errno (PIN)) {
- pj_free(PIN);
+ proj_destroy(PIN);
return nullptr;
}
proj_errno_restore (PIN, err);
diff --git a/src/initcache.cpp b/src/initcache.cpp
index af20fb82..cf9460ab 100644
--- a/src/initcache.cpp
+++ b/src/initcache.cpp
@@ -48,7 +48,7 @@ paralist *pj_clone_paralist( const paralist *list)
for( ; list != nullptr; list = list->next )
{
paralist *newitem = (paralist *)
- pj_malloc(sizeof(paralist) + strlen(list->param));
+ malloc(sizeof(paralist) + strlen(list->param));
newitem->used = 0;
newitem->next = nullptr;
@@ -83,17 +83,17 @@ void pj_clear_initcache()
{
paralist *n, *t = cache_paralist[i];
- pj_dalloc( cache_key[i] );
+ free( cache_key[i] );
/* free parameter list elements */
for (; t != nullptr; t = n) {
n = t->next;
- pj_dalloc(t);
+ free(t);
}
}
- pj_dalloc( cache_key );
- pj_dalloc( cache_paralist );
+ free( cache_key );
+ free( cache_paralist );
cache_count = 0;
cache_alloc= 0;
cache_key = nullptr;
@@ -151,29 +151,29 @@ void pj_insert_initcache( const char *filekey, const paralist *list )
cache_alloc = cache_alloc * 2 + 15;
- cache_key_new = (char **) pj_malloc(sizeof(char*) * cache_alloc);
+ cache_key_new = (char **) malloc(sizeof(char*) * cache_alloc);
if( cache_key && cache_count )
{
memcpy( cache_key_new, cache_key, sizeof(char*) * cache_count);
}
- pj_dalloc( cache_key );
+ free( cache_key );
cache_key = cache_key_new;
cache_paralist_new = (paralist **)
- pj_malloc(sizeof(paralist*) * cache_alloc);
+ malloc(sizeof(paralist*) * cache_alloc);
if( cache_paralist && cache_count )
{
memcpy( cache_paralist_new, cache_paralist,
sizeof(paralist*) * cache_count );
}
- pj_dalloc( cache_paralist );
+ free( cache_paralist );
cache_paralist = cache_paralist_new;
}
/*
** Duplicate the filekey and paralist, and insert in cache.
*/
- cache_key[cache_count] = (char *) pj_malloc(strlen(filekey)+1);
+ cache_key[cache_count] = (char *) malloc(strlen(filekey)+1);
strcpy( cache_key[cache_count], filekey );
cache_paralist[cache_count] = pj_clone_paralist( list );
diff --git a/src/internal.cpp b/src/internal.cpp
index 91994077..175ffa9b 100644
--- a/src/internal.cpp
+++ b/src/internal.cpp
@@ -141,15 +141,15 @@ Check if a a PJ has an inverse.
void proj_context_set (PJ *P, PJ_CONTEXT *ctx) {
if (nullptr==ctx)
ctx = pj_get_default_ctx ();
- pj_set_ctx (P, ctx);
+ proj_assign_context (P, ctx);
}
void proj_context_inherit (PJ *parent, PJ *child) {
if (nullptr==parent)
- pj_set_ctx (child, pj_get_default_ctx());
+ proj_assign_context (child, pj_get_default_ctx());
else
- pj_set_ctx (child, pj_get_ctx(parent));
+ proj_assign_context (child, pj_get_ctx(parent));
}
@@ -411,13 +411,16 @@ to that context.
******************************************************************************/
if (nullptr==ctx)
ctx = pj_get_default_ctx();
- pj_ctx_set_errno (ctx, err);
+ ctx->last_errno = err;
+ if( err == 0 )
+ return;
+ errno = err;
}
/* logging */
/* pj_vlog resides in pj_log.c and relates to pj_log as vsprintf relates to sprintf */
-void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args );
+void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args );
/***************************************************************************************/
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 7582f37f..6bc1f166 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -79,10 +79,10 @@ static void PROJ_NO_INLINE proj_log_error(PJ_CONTEXT *ctx, const char *function,
msg += ": ";
msg += text;
ctx->logger(ctx->logger_app_data, PJ_LOG_ERROR, msg.c_str());
- auto previous_errno = pj_ctx_get_errno(ctx);
+ auto previous_errno = proj_context_errno(ctx);
if (previous_errno == 0) {
// only set errno if it wasn't set deeper down the call stack
- pj_ctx_set_errno(ctx, PJD_ERR_GENERIC_ERROR);
+ proj_context_errno_set(ctx, PJD_ERR_GENERIC_ERROR);
}
}
@@ -675,6 +675,9 @@ PJ *proj_create_from_database(PJ_CONTEXT *ctx, const char *auth_name,
codeStr, usePROJAlternativeGridNames != 0)
.as_nullable();
break;
+ case PJ_CATEGORY_DATUM_ENSEMBLE:
+ obj = factory->createDatumEnsemble(codeStr).as_nullable();
+ break;
}
return pj_obj_create(ctx, NN_NO_CHECK(obj));
} catch (const std::exception &e) {
@@ -916,7 +919,7 @@ convertPJObjectTypeToObjectType(PJ_TYPE type, bool &valid) {
break;
case PJ_TYPE_DATUM_ENSEMBLE:
- cppType = AuthorityFactory::ObjectType::DATUM;
+ cppType = AuthorityFactory::ObjectType::DATUM_ENSEMBLE;
break;
case PJ_TYPE_TEMPORAL_DATUM:
@@ -1418,6 +1421,13 @@ const char *proj_get_id_code(const PJ *obj, int index) {
* variants, for WKT1_GDAL for ProjectedCRS with easting/northing ordering
* (otherwise stripped), but not for WKT1_ESRI. Setting to YES will output
* them unconditionally, and to NO will omit them unconditionally.</li>
+ * <li>STRICT=YES/NO. Default is YES. If NO, a Geographic 3D CRS can be for
+ * example exported as WKT1_GDAL with 3 axes, whereas this is normally not
+ * allowed.</li>
+ * <li>ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES/NO. Default is NO. If set
+ * to YES and type == PJ_WKT1_GDAL, a Geographic 3D CRS or a Projected 3D CRS
+ * will be exported as a compound CRS whose vertical part represents an
+ * ellipsoidal height (for example for use with LAS 1.4 WKT1).</li>
* </ul>
* @return a string, or NULL in case of error.
*/
@@ -1468,6 +1478,11 @@ const char *proj_as_wkt(PJ_CONTEXT *ctx, const PJ *obj, PJ_WKT_TYPE type,
}
} else if ((value = getOptionValue(*iter, "STRICT="))) {
formatter->setStrict(ci_equal(value, "YES"));
+ } else if ((value = getOptionValue(
+ *iter,
+ "ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS="))) {
+ formatter->setAllowEllipsoidalHeightAsVerticalCRS(
+ ci_equal(value, "YES"));
} else {
std::string msg("Unknown option :");
msg += *iter;
@@ -2050,6 +2065,8 @@ PJ *proj_get_ellipsoid(PJ_CONTEXT *ctx, const PJ *obj) {
/** \brief Get the horizontal datum from a CRS
*
+ * This function may return a Datum or DatumEnsemble object.
+ *
* The returned object must be unreferenced with proj_destroy() after
* use.
* It should be used by at most one thread at a time.
@@ -2685,11 +2702,11 @@ proj_get_crs_info_list_from_database(PJ_CONTEXT *ctx, const char *auth_name,
void proj_crs_info_list_destroy(PROJ_CRS_INFO **list) {
if (list) {
for (int i = 0; list[i] != nullptr; i++) {
- pj_dalloc(list[i]->auth_name);
- pj_dalloc(list[i]->code);
- pj_dalloc(list[i]->name);
- pj_dalloc(list[i]->area_name);
- pj_dalloc(list[i]->projection_method_name);
+ free(list[i]->auth_name);
+ free(list[i]->code);
+ free(list[i]->name);
+ free(list[i]->area_name);
+ free(list[i]->projection_method_name);
delete list[i];
}
delete[] list;
@@ -2779,11 +2796,11 @@ PROJ_UNIT_INFO **proj_get_units_from_database(PJ_CONTEXT *ctx,
void proj_unit_list_destroy(PROJ_UNIT_INFO **list) {
if (list) {
for (int i = 0; list[i] != nullptr; i++) {
- pj_dalloc(list[i]->auth_name);
- pj_dalloc(list[i]->code);
- pj_dalloc(list[i]->name);
- pj_dalloc(list[i]->category);
- pj_dalloc(list[i]->proj_short_name);
+ free(list[i]->auth_name);
+ free(list[i]->code);
+ free(list[i]->name);
+ free(list[i]->category);
+ free(list[i]->proj_short_name);
delete list[i];
}
delete[] list;
@@ -4438,8 +4455,9 @@ PJ *proj_create_cartesian_2D_cs(PJ_CONTEXT *ctx, PJ_CARTESIAN_CS_2D_TYPE type,
*
* @param ctx PROJ context, or NULL for default context
* @param type Coordinate system type.
- * @param unit_name Unit name.
- * @param unit_conv_factor Unit conversion factor to SI.
+ * @param unit_name Name of the angular units. Or NULL for Degree
+ * @param unit_conv_factor Conversion factor from the angular unit to radian.
+ * Or 0 for Degree if unit_name == NULL. Otherwise should be not NULL
*
* @return Object that must be unreferenced with
* proj_destroy(), or NULL in case of error.
@@ -4478,13 +4496,17 @@ PJ *proj_create_ellipsoidal_2D_cs(PJ_CONTEXT *ctx,
*
* @param ctx PROJ context, or NULL for default context
* @param type Coordinate system type.
- * @param horizontal_angular_unit_name Horizontal angular unit name.
- * @param horizontal_angular_unit_conv_factor Horizontal angular unit conversion
- * factor to SI.
- * @param vertical_linear_unit_name Vertical linear unit name.
+ * @param horizontal_angular_unit_name Name of the angular units. Or NULL for
+ * Degree.
+ * @param horizontal_angular_unit_conv_factor Conversion factor from the angular
+ * unit to radian. Or 0 for Degree if horizontal_angular_unit_name == NULL.
+ * Otherwise should be not NULL
+ * @param vertical_linear_unit_name Vertical linear unit name. Or NULL for
+ * Metre.
* @param vertical_linear_unit_conv_factor Vertical linear unit conversion
- * factor to SI.
- *
+ * factor to metre. Or 0 for Metre if vertical_linear_unit_name == NULL.
+ * Otherwise should be not NULL
+
* @return Object that must be unreferenced with
* proj_destroy(), or NULL in case of error.
* @since 6.3
@@ -7987,6 +8009,9 @@ double proj_coordoperation_get_accuracy(PJ_CONTEXT *ctx,
/** \brief Returns the datum of a SingleCRS.
*
+ * If that function returns NULL, @see proj_crs_get_datum_ensemble() to
+ * potentially get a DatumEnsemble instead.
+ *
* The returned object must be unreferenced with proj_destroy() after
* use.
* It should be used by at most one thread at a time.
@@ -8018,6 +8043,9 @@ PJ *proj_crs_get_datum(PJ_CONTEXT *ctx, const PJ *crs) {
/** \brief Returns the datum ensemble of a SingleCRS.
*
+ * If that function returns NULL, @see proj_crs_get_datum() to
+ * potentially get a Datum instead.
+ *
* The returned object must be unreferenced with proj_destroy() after
* use.
* It should be used by at most one thread at a time.
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index be15b3e0..83b626b3 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -64,6 +64,30 @@
// #define DEBUG_CONCATENATED_OPERATION
#if defined(DEBUG_SORT) || defined(DEBUG_CONCATENATED_OPERATION)
#include <iostream>
+
+void dumpWKT(const NS_PROJ::crs::CRS *crs);
+void dumpWKT(const NS_PROJ::crs::CRS *crs) {
+ auto f(NS_PROJ::io::WKTFormatter::create(
+ NS_PROJ::io::WKTFormatter::Convention::WKT2_2019));
+ std::cerr << crs->exportToWKT(f.get()) << std::endl;
+}
+
+void dumpWKT(const NS_PROJ::crs::CRSPtr &crs);
+void dumpWKT(const NS_PROJ::crs::CRSPtr &crs) { dumpWKT(crs.get()); }
+
+void dumpWKT(const NS_PROJ::crs::CRSNNPtr &crs);
+void dumpWKT(const NS_PROJ::crs::CRSNNPtr &crs) {
+ dumpWKT(crs.as_nullable().get());
+}
+
+void dumpWKT(const NS_PROJ::crs::GeographicCRSPtr &crs);
+void dumpWKT(const NS_PROJ::crs::GeographicCRSPtr &crs) { dumpWKT(crs.get()); }
+
+void dumpWKT(const NS_PROJ::crs::GeographicCRSNNPtr &crs);
+void dumpWKT(const NS_PROJ::crs::GeographicCRSNNPtr &crs) {
+ dumpWKT(crs.as_nullable().get());
+}
+
#endif
using namespace NS_PROJ::internal;
@@ -6010,28 +6034,39 @@ void Conversion::_exportToPROJString(
!isHeightDepthReversal;
bool applyTargetCRSModifiers = applySourceCRSModifiers;
+ if (formatter->getCRSExport()) {
+ if (methodEPSGCode == EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC ||
+ methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC) {
+ throw io::FormattingException("Transformation cannot be exported "
+ "as a PROJ.4 string (but can be part "
+ "of a PROJ pipeline)");
+ }
+ }
+
auto l_sourceCRS = sourceCRS();
+ crs::GeographicCRSPtr srcGeogCRS;
if (!formatter->getCRSExport() && l_sourceCRS && applySourceCRSModifiers) {
- crs::CRS *horiz = l_sourceCRS.get();
- const auto compound = dynamic_cast<const crs::CompoundCRS *>(horiz);
+ crs::CRSPtr horiz = l_sourceCRS;
+ const auto compound =
+ dynamic_cast<const crs::CompoundCRS *>(l_sourceCRS.get());
if (compound) {
const auto &components = compound->componentReferenceSystems();
if (!components.empty()) {
- horiz = components.front().get();
+ horiz = components.front().as_nullable();
}
}
- auto geogCRS = dynamic_cast<const crs::GeographicCRS *>(horiz);
- if (geogCRS) {
+ srcGeogCRS = std::dynamic_pointer_cast<crs::GeographicCRS>(horiz);
+ if (srcGeogCRS) {
formatter->setOmitProjLongLatIfPossible(true);
formatter->startInversion();
- geogCRS->_exportToPROJString(formatter);
+ srcGeogCRS->_exportToPROJString(formatter);
formatter->stopInversion();
formatter->setOmitProjLongLatIfPossible(false);
}
- auto projCRS = dynamic_cast<const crs::ProjectedCRS *>(horiz);
+ auto projCRS = dynamic_cast<const crs::ProjectedCRS *>(horiz.get());
if (projCRS) {
formatter->startInversion();
formatter->pushOmitZUnitConversion();
@@ -6301,6 +6336,30 @@ void Conversion::_exportToPROJString(
}
bConversionDone = true;
bEllipsoidParametersDone = true;
+ } else if (methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC) {
+ if (!srcGeogCRS) {
+ throw io::FormattingException(
+ "Export of Geographic/Topocentric conversion to a PROJ string "
+ "requires an input geographic CRS");
+ }
+
+ formatter->addStep("cart");
+ srcGeogCRS->ellipsoid()->_exportToPROJString(formatter);
+
+ formatter->addStep("topocentric");
+ const auto latOrigin = parameterValueNumeric(
+ EPSG_CODE_PARAMETER_LATITUDE_TOPOGRAPHIC_ORIGIN,
+ common::UnitOfMeasure::DEGREE);
+ const auto lonOrigin = parameterValueNumeric(
+ EPSG_CODE_PARAMETER_LONGITUDE_TOPOGRAPHIC_ORIGIN,
+ common::UnitOfMeasure::DEGREE);
+ const auto heightOrigin = parameterValueNumeric(
+ EPSG_CODE_PARAMETER_ELLIPSOIDAL_HEIGHT_TOPOCENTRIC_ORIGIN,
+ common::UnitOfMeasure::METRE);
+ formatter->addParam("lat_0", latOrigin);
+ formatter->addParam("lon_0", lonOrigin);
+ formatter->addParam("h_0", heightOrigin);
+ bConversionDone = true;
}
auto l_targetCRS = targetCRS();
@@ -6425,7 +6484,9 @@ void Conversion::_exportToPROJString(
}
if (!bEllipsoidParametersDone) {
- auto targetGeogCRS = horiz->extractGeographicCRS();
+ auto targetGeodCRS = horiz->extractGeodeticCRS();
+ auto targetGeogCRS =
+ std::dynamic_pointer_cast<crs::GeographicCRS>(targetGeodCRS);
if (targetGeogCRS) {
if (formatter->getCRSExport()) {
targetGeogCRS->addDatumInfoToPROJString(formatter);
@@ -6434,6 +6495,8 @@ void Conversion::_exportToPROJString(
targetGeogCRS->primeMeridian()->_exportToPROJString(
formatter);
}
+ } else if (targetGeodCRS) {
+ targetGeodCRS->ellipsoid()->_exportToPROJString(formatter);
}
}
@@ -8836,11 +8899,16 @@ createSimilarPropertiesTransformation(TransformationNNPtr obj) {
// The domain(s) are unchanged
addDomains(map, obj.get());
- std::string forwardName = obj->nameStr();
+ const std::string &forwardName = obj->nameStr();
if (!forwardName.empty()) {
map.set(common::IdentifiedObject::NAME_KEY, forwardName);
}
+ const std::string &remarks = obj->remarks();
+ if (!remarks.empty()) {
+ map.set(common::IdentifiedObject::REMARKS_KEY, remarks);
+ }
+
addModifiedIdentifier(map, obj.get(), false, true);
return map;
@@ -9179,6 +9247,14 @@ static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
formatter->startInversion();
sourceCRSGeog->_exportToPROJString(formatter);
formatter->stopInversion();
+ if (util::isOfExactType<crs::DerivedGeographicCRS>(
+ *(sourceCRSGeog.get()))) {
+ // The export of a DerivedGeographicCRS in non-CRS mode adds
+ // unit conversion and axis swapping. We must compensate for that
+ formatter->startInversion();
+ sourceCRSGeog->addAngularUnitConvertAndAxisSwap(formatter);
+ formatter->stopInversion();
+ }
if (addPushV3) {
formatter->addStep("push");
@@ -9212,7 +9288,12 @@ static void setupPROJGeodeticTargetCRS(io::PROJStringFormatter *formatter,
formatter->addStep("pop");
formatter->addParam("v_3");
}
-
+ if (util::isOfExactType<crs::DerivedGeographicCRS>(
+ *(targetCRSGeog.get()))) {
+ // The export of a DerivedGeographicCRS in non-CRS mode adds
+ // unit conversion and axis swapping. We must compensate for that
+ targetCRSGeog->addAngularUnitConvertAndAxisSwap(formatter);
+ }
targetCRSGeog->_exportToPROJString(formatter);
} else {
auto targetCRSGeod = dynamic_cast<const crs::GeodeticCRS *>(crs.get());
@@ -11191,6 +11272,12 @@ struct CoordinateOperationFactory::Private {
const crs::GeographicCRS *geogDst,
std::vector<CoordinateOperationNNPtr> &res);
+ static void createOperationsVertToGeogBallpark(
+ const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
+ Private::Context &context, const crs::VerticalCRS *vertSrc,
+ const crs::GeographicCRS *geogDst,
+ std::vector<CoordinateOperationNNPtr> &res);
+
static void createOperationsBoundToBound(
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
Private::Context &context, const crs::BoundCRS *boundSrc,
@@ -11292,6 +11379,7 @@ struct PrecomputedOpCharacteristics {
bool gridsKnown_ = false;
size_t stepCount_ = 0;
bool isApprox_ = false;
+ bool hasBallparkVertical_ = false;
bool isNullTransformation_ = false;
PrecomputedOpCharacteristics() = default;
@@ -11299,10 +11387,12 @@ struct PrecomputedOpCharacteristics {
bool isPROJExportable, bool hasGrids,
bool gridsAvailable, bool gridsKnown,
size_t stepCount, bool isApprox,
+ bool hasBallparkVertical,
bool isNullTransformation)
: area_(area), accuracy_(accuracy), isPROJExportable_(isPROJExportable),
hasGrids_(hasGrids), gridsAvailable_(gridsAvailable),
gridsKnown_(gridsKnown), stepCount_(stepCount), isApprox_(isApprox),
+ hasBallparkVertical_(hasBallparkVertical),
isNullTransformation_(isNullTransformation) {}
};
@@ -11346,6 +11436,15 @@ struct SortFunction {
return false;
}
+ if (!iterA->second.hasBallparkVertical_ &&
+ iterB->second.hasBallparkVertical_) {
+ return true;
+ }
+ if (iterA->second.hasBallparkVertical_ &&
+ !iterB->second.hasBallparkVertical_) {
+ return false;
+ }
+
if (!iterA->second.isNullTransformation_ &&
iterB->second.isNullTransformation_) {
return true;
@@ -11612,7 +11711,9 @@ struct FilterResults {
? CoordinateOperationContext::SpatialCriterion::
STRICT_CONTAINMENT
: context->getSpatialCriterion();
- bool hasFoundOpWithExtent = false;
+ bool hasOnlyBallpark = true;
+ bool hasNonBallparkWithoutExtent = false;
+ bool hasNonBallparkOpWithExtent = false;
const bool allowBallpark = context->getAllowBallparkTransformations();
for (const auto &op : sourceList) {
if (desiredAccuracy != 0) {
@@ -11627,9 +11728,15 @@ struct FilterResults {
if (areaOfInterest) {
bool emptyIntersection = false;
auto extent = getExtent(op, true, emptyIntersection);
- if (!extent)
+ if (!extent) {
+ if (!op->hasBallparkTransformation()) {
+ hasNonBallparkWithoutExtent = true;
+ }
continue;
- hasFoundOpWithExtent = true;
+ }
+ if (!op->hasBallparkTransformation()) {
+ hasNonBallparkOpWithExtent = true;
+ }
bool extentContains =
extent->contains(NN_NO_CHECK(areaOfInterest));
if (!hasOpThatContainsAreaOfInterestAndNoGrid &&
@@ -11656,9 +11763,15 @@ struct FilterResults {
BOTH) {
bool emptyIntersection = false;
auto extent = getExtent(op, true, emptyIntersection);
- if (!extent)
+ if (!extent) {
+ if (!op->hasBallparkTransformation()) {
+ hasNonBallparkWithoutExtent = true;
+ }
continue;
- hasFoundOpWithExtent = true;
+ }
+ if (!op->hasBallparkTransformation()) {
+ hasNonBallparkOpWithExtent = true;
+ }
bool extentContainsExtent1 =
!extent1 || extent->contains(NN_NO_CHECK(extent1));
bool extentContainsExtent2 =
@@ -11688,12 +11801,16 @@ struct FilterResults {
}
}
}
+ if (!op->hasBallparkTransformation()) {
+ hasOnlyBallpark = false;
+ }
res.emplace_back(op);
}
// In case no operation has an extent and no result is found,
// retain all initial operations that match accuracy criterion.
- if (res.empty() && !hasFoundOpWithExtent) {
+ if ((res.empty() && !hasNonBallparkOpWithExtent) ||
+ (hasOnlyBallpark && hasNonBallparkWithoutExtent)) {
for (const auto &op : sourceList) {
if (desiredAccuracy != 0) {
const double accuracy = getAccuracy(op);
@@ -11797,6 +11914,8 @@ struct FilterResults {
area, getAccuracy(op), isPROJExportable, hasGrids,
gridsAvailable, gridsKnown, stepCount,
op->hasBallparkTransformation(),
+ op->nameStr().find("ballpark vertical transformation") !=
+ std::string::npos,
isNullTransformation(op->nameStr()));
}
@@ -12615,6 +12734,55 @@ createGeodToGeodPROJBased(const crs::CRSNNPtr &geodSrc,
// ---------------------------------------------------------------------------
+static std::string
+getRemarks(const std::vector<operation::CoordinateOperationNNPtr> &ops) {
+ std::string remarks;
+ for (const auto &op : ops) {
+ const auto &opRemarks = op->remarks();
+ if (!opRemarks.empty()) {
+ if (!remarks.empty()) {
+ remarks += '\n';
+ }
+
+ std::string opName(op->nameStr());
+ if (starts_with(opName, INVERSE_OF)) {
+ opName = opName.substr(INVERSE_OF.size());
+ }
+
+ remarks += "For ";
+ remarks += opName;
+
+ const auto &ids = op->identifiers();
+ if (!ids.empty()) {
+ std::string authority(*ids.front()->codeSpace());
+ if (starts_with(authority, "INVERSE(") &&
+ authority.back() == ')') {
+ authority = authority.substr(strlen("INVERSE("),
+ authority.size() - 1 -
+ strlen("INVERSE("));
+ }
+ if (starts_with(authority, "DERIVED_FROM(") &&
+ authority.back() == ')') {
+ authority = authority.substr(strlen("DERIVED_FROM("),
+ authority.size() - 1 -
+ strlen("DERIVED_FROM("));
+ }
+
+ remarks += " (";
+ remarks += authority;
+ remarks += ':';
+ remarks += ids.front()->code();
+ remarks += ')';
+ }
+ remarks += ": ";
+ remarks += opRemarks;
+ }
+ }
+ return remarks;
+}
+
+// ---------------------------------------------------------------------------
+
static CoordinateOperationNNPtr createHorizVerticalPROJBased(
const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
const operation::CoordinateOperationNNPtr &horizTransform,
@@ -12640,6 +12808,10 @@ static CoordinateOperationNNPtr createHorizVerticalPROJBased(
properties.set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
NN_NO_CHECK(extent));
}
+ const auto &remarks = verticalTransform->remarks();
+ if (!remarks.empty()) {
+ properties.set(common::IdentifiedObject::REMARKS_KEY, remarks);
+ }
return createPROJBased(
properties, exportable, sourceCRS, targetCRS, nullptr,
verticalTransform->coordinateOperationAccuracies(),
@@ -12664,6 +12836,11 @@ static CoordinateOperationNNPtr createHorizVerticalPROJBased(
NN_NO_CHECK(extent));
}
+ const auto remarks = getRemarks(ops);
+ if (!remarks.empty()) {
+ properties.set(common::IdentifiedObject::REMARKS_KEY, remarks);
+ }
+
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
const double accuracy = getAccuracy(ops);
if (accuracy >= 0.0) {
@@ -12724,6 +12901,11 @@ static CoordinateOperationNNPtr createHorizVerticalHorizPROJBased(
NN_NO_CHECK(extent));
}
+ const auto remarks = getRemarks(ops);
+ if (!remarks.empty()) {
+ properties.set(common::IdentifiedObject::REMARKS_KEY, remarks);
+ }
+
std::vector<metadata::PositionalAccuracyNNPtr> accuracies;
const double accuracy = getAccuracy(ops);
if (accuracy >= 0.0) {
@@ -13542,11 +13724,17 @@ bool CoordinateOperationFactory::Private::createOperationsFromDatabase(
ENTER_FUNCTION();
if (geogSrc && vertDst) {
- res = createOperationsGeogToVertFromGeoid(sourceCRS, targetCRS, vertDst,
- context);
+ createOperationsFromDatabase(targetCRS, sourceCRS, context, geodDst,
+ geodSrc, geogDst, geogSrc, vertDst,
+ vertSrc, res);
+ res = applyInverse(res);
} else if (geogDst && vertSrc) {
res = applyInverse(createOperationsGeogToVertFromGeoid(
targetCRS, sourceCRS, vertSrc, context));
+ if (!res.empty()) {
+ createOperationsVertToGeogBallpark(sourceCRS, targetCRS, context,
+ vertSrc, geogDst, res);
+ }
}
if (!res.empty()) {
@@ -14222,6 +14410,20 @@ void CoordinateOperationFactory::Private::createOperationsBoundToGeog(
const auto &hubSrc = boundSrc->hubCRS();
auto hubSrcGeog = dynamic_cast<const crs::GeographicCRS *>(hubSrc.get());
auto geogCRSOfBaseOfBoundSrc = boundSrc->baseCRS()->extractGeographicCRS();
+ {
+ // If geogCRSOfBaseOfBoundSrc is a DerivedGeographicCRS, use its base
+ // instead (if it is a GeographicCRS)
+ auto derivedGeogCRS =
+ std::dynamic_pointer_cast<crs::DerivedGeographicCRS>(
+ geogCRSOfBaseOfBoundSrc);
+ if (derivedGeogCRS) {
+ auto baseCRS = std::dynamic_pointer_cast<crs::GeographicCRS>(
+ derivedGeogCRS->baseCRS().as_nullable());
+ if (baseCRS) {
+ geogCRSOfBaseOfBoundSrc = baseCRS;
+ }
+ }
+ }
const auto &authFactory = context.context->getAuthorityFactory();
const auto dbContext =
@@ -14643,23 +14845,38 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeog(
match.get(),
util::IComparable::Criterion::EQUIVALENT) &&
!match->identifiers().empty()) {
- res = createOperations(
+ auto resTmp = createOperations(
NN_NO_CHECK(
util::nn_dynamic_pointer_cast<crs::VerticalCRS>(
match)),
targetCRS, context);
+ res.insert(res.end(), resTmp.begin(), resTmp.end());
return;
}
}
}
}
+ createOperationsVertToGeogBallpark(sourceCRS, targetCRS, context, vertSrc,
+ geogDst, res);
+}
+
+// ---------------------------------------------------------------------------
+
+void CoordinateOperationFactory::Private::createOperationsVertToGeogBallpark(
+ const crs::CRSNNPtr &sourceCRS, const crs::CRSNNPtr &targetCRS,
+ Private::Context &, const crs::VerticalCRS *vertSrc,
+ const crs::GeographicCRS *geogDst,
+ std::vector<CoordinateOperationNNPtr> &res) {
+
+ ENTER_FUNCTION();
+
const auto &srcAxis = vertSrc->coordinateSystem()->axisList()[0];
const double convSrc = srcAxis->unit().conversionToSI();
double convDst = 1.0;
const auto &geogAxis = geogDst->coordinateSystem()->axisList();
bool dstIsUp = true;
- bool dstIsDown = true;
+ bool dstIsDown = false;
if (geogAxis.size() == 3) {
const auto &dstAxis = geogAxis[2];
convDst = dstAxis->unit().conversionToSI();
@@ -14672,12 +14889,24 @@ void CoordinateOperationFactory::Private::createOperationsVertToGeog(
((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp));
const double factor = convSrc / convDst;
- auto conv = Transformation::createChangeVerticalUnit(
- util::PropertyMap().set(
- common::IdentifiedObject::NAME_KEY,
+
+ const auto &sourceCRSExtent = getExtent(sourceCRS);
+ const auto &targetCRSExtent = getExtent(targetCRS);
+ const bool sameExtent =
+ sourceCRSExtent && targetCRSExtent &&
+ sourceCRSExtent->_isEquivalentTo(
+ targetCRSExtent.get(), util::IComparable::Criterion::EQUIVALENT);
+
+ util::PropertyMap map;
+ map.set(common::IdentifiedObject::NAME_KEY,
buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()) +
- BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT),
- sourceCRS, targetCRS,
+ BALLPARK_VERTICAL_TRANSFORMATION_NO_ELLIPSOID_VERT_HEIGHT)
+ .set(common::ObjectUsage::DOMAIN_OF_VALIDITY_KEY,
+ sameExtent ? NN_NO_CHECK(sourceCRSExtent)
+ : metadata::Extent::WORLD);
+
+ auto conv = Transformation::createChangeVerticalUnit(
+ map, sourceCRS, targetCRS,
common::Scale(heightDepthReversal ? -factor : factor), {});
conv->setHasBallparkTransformation(true);
res.push_back(conv);
@@ -15477,149 +15706,6 @@ void CoordinateOperationFactory::Private::createOperationsBoundToCompound(
// ---------------------------------------------------------------------------
-static crs::CRSNNPtr
-getResolvedCRS(const crs::CRSNNPtr &crs,
- const CoordinateOperationContextNNPtr &context,
- metadata::ExtentPtr &extentOut) {
- const auto &authFactory = context->getAuthorityFactory();
- const auto &ids = crs->identifiers();
- const auto &name = crs->nameStr();
-
- bool approxExtent;
- extentOut = getExtentPossiblySynthetized(crs, approxExtent);
-
- // We try to "identify" the provided CRS with the ones of the database,
- // but in a more restricted way that what identify() does.
- // If we get a match from id in priority, and from name as a fallback, and
- // that they are equivalent to the input CRS, then use the identified CRS.
- // Even if they aren't equivalent, we update extentOut with the one of the
- // identified CRS if our input one is absent/not reliable.
-
- const auto tryToIdentifyByName = [&crs, &name, &authFactory, approxExtent,
- &extentOut](
- io::AuthorityFactory::ObjectType objectType) {
- if (name != "unknown" && name != "unnamed") {
- auto matches = authFactory->createObjectsFromName(
- name, {objectType}, false, 2);
- if (matches.size() == 1) {
- const auto match =
- util::nn_static_pointer_cast<crs::CRS>(matches.front());
- if (approxExtent || !extentOut) {
- extentOut = getExtent(match);
- }
- if (match->isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
- return match;
- }
- }
- }
- return crs;
- };
-
- auto geogCRS = dynamic_cast<crs::GeographicCRS *>(crs.get());
- if (geogCRS && authFactory) {
- if (!ids.empty()) {
- const auto tmpAuthFactory = io::AuthorityFactory::create(
- authFactory->databaseContext(), *ids.front()->codeSpace());
- try {
- auto resolvedCrs(
- tmpAuthFactory->createGeographicCRS(ids.front()->code()));
- if (approxExtent || !extentOut) {
- extentOut = getExtent(resolvedCrs);
- }
- if (resolvedCrs->isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
- return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
- }
- } catch (const std::exception &) {
- }
- } else {
- return tryToIdentifyByName(
- geogCRS->coordinateSystem()->axisList().size() == 2
- ? io::AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS
- : io::AuthorityFactory::ObjectType::GEOGRAPHIC_3D_CRS);
- }
- }
-
- auto projectedCrs = dynamic_cast<crs::ProjectedCRS *>(crs.get());
- if (projectedCrs && authFactory) {
- if (!ids.empty()) {
- const auto tmpAuthFactory = io::AuthorityFactory::create(
- authFactory->databaseContext(), *ids.front()->codeSpace());
- try {
- auto resolvedCrs(
- tmpAuthFactory->createProjectedCRS(ids.front()->code()));
- if (approxExtent || !extentOut) {
- extentOut = getExtent(resolvedCrs);
- }
- if (resolvedCrs->isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
- return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
- }
- } catch (const std::exception &) {
- }
- } else {
- return tryToIdentifyByName(
- io::AuthorityFactory::ObjectType::PROJECTED_CRS);
- }
- }
-
- auto compoundCrs = dynamic_cast<crs::CompoundCRS *>(crs.get());
- if (compoundCrs && authFactory) {
- if (!ids.empty()) {
- const auto tmpAuthFactory = io::AuthorityFactory::create(
- authFactory->databaseContext(), *ids.front()->codeSpace());
- try {
- auto resolvedCrs(
- tmpAuthFactory->createCompoundCRS(ids.front()->code()));
- if (approxExtent || !extentOut) {
- extentOut = getExtent(resolvedCrs);
- }
- if (resolvedCrs->isEquivalentTo(
- crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
- return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
- }
- } catch (const std::exception &) {
- }
- } else {
- auto outCrs = tryToIdentifyByName(
- io::AuthorityFactory::ObjectType::COMPOUND_CRS);
- const auto &components = compoundCrs->componentReferenceSystems();
- if (outCrs.get() != crs.get()) {
- bool hasGeoid = false;
- if (components.size() == 2) {
- auto vertCRS =
- dynamic_cast<crs::VerticalCRS *>(components[1].get());
- if (vertCRS && !vertCRS->geoidModel().empty()) {
- hasGeoid = true;
- }
- }
- if (!hasGeoid) {
- return outCrs;
- }
- }
- if (approxExtent || !extentOut) {
- // If we still did not get a reliable extent, then try to
- // resolve the components of the compoundCRS, and take the
- // intersection of their extent.
- extentOut = metadata::ExtentPtr();
- for (const auto &component : components) {
- metadata::ExtentPtr componentExtent;
- getResolvedCRS(component, context, componentExtent);
- if (extentOut && componentExtent)
- extentOut = extentOut->intersection(
- NN_NO_CHECK(componentExtent));
- else if (componentExtent)
- extentOut = componentExtent;
- }
- }
- }
- }
- return crs;
-}
-
-// ---------------------------------------------------------------------------
-
/** \brief Find a list of CoordinateOperation from sourceCRS to targetCRS.
*
* The operations are sorted with the most relevant ones first: by
@@ -15655,13 +15741,14 @@ CoordinateOperationFactory::createOperations(
const auto &targetBoundCRS = targetCRS->canonicalBoundCRS();
auto l_sourceCRS = srcBoundCRS ? NN_NO_CHECK(srcBoundCRS) : sourceCRS;
auto l_targetCRS = targetBoundCRS ? NN_NO_CHECK(targetBoundCRS) : targetCRS;
+ const auto &authFactory = context->getAuthorityFactory();
metadata::ExtentPtr sourceCRSExtent;
auto l_resolvedSourceCRS =
- getResolvedCRS(l_sourceCRS, context, sourceCRSExtent);
+ crs::CRS::getResolvedCRS(l_sourceCRS, authFactory, sourceCRSExtent);
metadata::ExtentPtr targetCRSExtent;
auto l_resolvedTargetCRS =
- getResolvedCRS(l_targetCRS, context, targetCRSExtent);
+ crs::CRS::getResolvedCRS(l_targetCRS, authFactory, targetCRSExtent);
Private::Context contextPrivate(sourceCRSExtent, targetCRSExtent, context);
if (context->getSourceAndTargetCRSExtentUse() ==
@@ -15986,4 +16073,152 @@ PROJBasedOperation::gridsNeeded(const io::DatabaseContextPtr &databaseContext,
// ---------------------------------------------------------------------------
} // namespace operation
+
+namespace crs {
+// ---------------------------------------------------------------------------
+
+//! @cond Doxygen_Suppress
+
+crs::CRSNNPtr CRS::getResolvedCRS(const crs::CRSNNPtr &crs,
+ const io::AuthorityFactoryPtr &authFactory,
+ metadata::ExtentPtr &extentOut) {
+ const auto &ids = crs->identifiers();
+ const auto &name = crs->nameStr();
+
+ bool approxExtent;
+ extentOut = getExtentPossiblySynthetized(crs, approxExtent);
+
+ // We try to "identify" the provided CRS with the ones of the database,
+ // but in a more restricted way that what identify() does.
+ // If we get a match from id in priority, and from name as a fallback, and
+ // that they are equivalent to the input CRS, then use the identified CRS.
+ // Even if they aren't equivalent, we update extentOut with the one of the
+ // identified CRS if our input one is absent/not reliable.
+
+ const auto tryToIdentifyByName = [&crs, &name, &authFactory, approxExtent,
+ &extentOut](
+ io::AuthorityFactory::ObjectType objectType) {
+ if (name != "unknown" && name != "unnamed") {
+ auto matches = authFactory->createObjectsFromName(
+ name, {objectType}, false, 2);
+ if (matches.size() == 1) {
+ const auto match =
+ util::nn_static_pointer_cast<crs::CRS>(matches.front());
+ if (approxExtent || !extentOut) {
+ extentOut = getExtent(match);
+ }
+ if (match->isEquivalentTo(
+ crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
+ return match;
+ }
+ }
+ }
+ return crs;
+ };
+
+ auto geogCRS = dynamic_cast<crs::GeographicCRS *>(crs.get());
+ if (geogCRS && authFactory) {
+ if (!ids.empty()) {
+ const auto tmpAuthFactory = io::AuthorityFactory::create(
+ authFactory->databaseContext(), *ids.front()->codeSpace());
+ try {
+ auto resolvedCrs(
+ tmpAuthFactory->createGeographicCRS(ids.front()->code()));
+ if (approxExtent || !extentOut) {
+ extentOut = getExtent(resolvedCrs);
+ }
+ if (resolvedCrs->isEquivalentTo(
+ crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
+ return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
+ }
+ } catch (const std::exception &) {
+ }
+ } else {
+ return tryToIdentifyByName(
+ geogCRS->coordinateSystem()->axisList().size() == 2
+ ? io::AuthorityFactory::ObjectType::GEOGRAPHIC_2D_CRS
+ : io::AuthorityFactory::ObjectType::GEOGRAPHIC_3D_CRS);
+ }
+ }
+
+ auto projectedCrs = dynamic_cast<crs::ProjectedCRS *>(crs.get());
+ if (projectedCrs && authFactory) {
+ if (!ids.empty()) {
+ const auto tmpAuthFactory = io::AuthorityFactory::create(
+ authFactory->databaseContext(), *ids.front()->codeSpace());
+ try {
+ auto resolvedCrs(
+ tmpAuthFactory->createProjectedCRS(ids.front()->code()));
+ if (approxExtent || !extentOut) {
+ extentOut = getExtent(resolvedCrs);
+ }
+ if (resolvedCrs->isEquivalentTo(
+ crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
+ return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
+ }
+ } catch (const std::exception &) {
+ }
+ } else {
+ return tryToIdentifyByName(
+ io::AuthorityFactory::ObjectType::PROJECTED_CRS);
+ }
+ }
+
+ auto compoundCrs = dynamic_cast<crs::CompoundCRS *>(crs.get());
+ if (compoundCrs && authFactory) {
+ if (!ids.empty()) {
+ const auto tmpAuthFactory = io::AuthorityFactory::create(
+ authFactory->databaseContext(), *ids.front()->codeSpace());
+ try {
+ auto resolvedCrs(
+ tmpAuthFactory->createCompoundCRS(ids.front()->code()));
+ if (approxExtent || !extentOut) {
+ extentOut = getExtent(resolvedCrs);
+ }
+ if (resolvedCrs->isEquivalentTo(
+ crs.get(), util::IComparable::Criterion::EQUIVALENT)) {
+ return util::nn_static_pointer_cast<crs::CRS>(resolvedCrs);
+ }
+ } catch (const std::exception &) {
+ }
+ } else {
+ auto outCrs = tryToIdentifyByName(
+ io::AuthorityFactory::ObjectType::COMPOUND_CRS);
+ const auto &components = compoundCrs->componentReferenceSystems();
+ if (outCrs.get() != crs.get()) {
+ bool hasGeoid = false;
+ if (components.size() == 2) {
+ auto vertCRS =
+ dynamic_cast<crs::VerticalCRS *>(components[1].get());
+ if (vertCRS && !vertCRS->geoidModel().empty()) {
+ hasGeoid = true;
+ }
+ }
+ if (!hasGeoid) {
+ return outCrs;
+ }
+ }
+ if (approxExtent || !extentOut) {
+ // If we still did not get a reliable extent, then try to
+ // resolve the components of the compoundCRS, and take the
+ // intersection of their extent.
+ extentOut = metadata::ExtentPtr();
+ for (const auto &component : components) {
+ metadata::ExtentPtr componentExtent;
+ getResolvedCRS(component, authFactory, componentExtent);
+ if (extentOut && componentExtent)
+ extentOut = extentOut->intersection(
+ NN_NO_CHECK(componentExtent));
+ else if (componentExtent)
+ extentOut = componentExtent;
+ }
+ }
+ }
+ }
+ return crs;
+}
+
+//! @endcond
+
+} // namespace crs
NS_PROJ_END
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index edc8a71f..573dd6db 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -533,8 +533,12 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible(
auto authFactory = io::AuthorityFactory::create(
NN_NO_CHECK(dbContext),
authority == "any" ? std::string() : authority);
+ metadata::ExtentPtr extentResolved(extent);
+ if (!extent) {
+ getResolvedCRS(thisAsCRS, authFactory, extentResolved);
+ }
auto ctxt = operation::CoordinateOperationContext::create(
- authFactory, extent, 0.0);
+ authFactory, extentResolved, 0.0);
ctxt->setAllowUseIntermediateCRS(allowIntermediateCRSUse);
// ctxt->setSpatialCriterion(
// operation::CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
@@ -1616,6 +1620,34 @@ static bool exportAsESRIWktCompoundCRSWithEllipsoidalHeight(
vertCRSList.front()->_exportToWKT(formatter);
return true;
}
+
+// ---------------------------------------------------------------------------
+
+// Try to format a Geographic/ProjectedCRS 3D CRS as a
+// GEOGCS[]/PROJCS[],VERTCS["Ellipsoid (metre)",DATUM["Ellipsoid",2002],...]
+static bool exportAsWKT1CompoundCRSWithEllipsoidalHeight(
+ const CRSNNPtr &base2DCRS,
+ const cs::CoordinateSystemAxisNNPtr &verticalAxis,
+ io::WKTFormatter *formatter) {
+ std::string verticalCRSName = "Ellipsoid (";
+ verticalCRSName += verticalAxis->unit().name();
+ verticalCRSName += ')';
+ auto vertDatum = datum::VerticalReferenceFrame::create(
+ util::PropertyMap()
+ .set(common::IdentifiedObject::NAME_KEY, "Ellipsoid")
+ .set("VERT_DATUM_TYPE", "2002"));
+ auto vertCRS = VerticalCRS::create(
+ util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
+ verticalCRSName),
+ vertDatum.as_nullable(), nullptr,
+ cs::VerticalCS::create(util::PropertyMap(), verticalAxis));
+ formatter->startNode(io::WKTConstants::COMPD_CS, false);
+ formatter->addQuotedString(base2DCRS->nameStr() + " + " + verticalCRSName);
+ base2DCRS->_exportToWKT(formatter);
+ vertCRS->_exportToWKT(formatter);
+ formatter->endNode();
+ return true;
+}
//! @endcond
// ---------------------------------------------------------------------------
@@ -1683,6 +1715,13 @@ void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const {
return;
}
+ if (formatter->isAllowedEllipsoidalHeightAsVerticalCRS()) {
+ if (exportAsWKT1CompoundCRSWithEllipsoidalHeight(
+ geogCRS2D, axisList[2], formatter)) {
+ return;
+ }
+ }
+
io::FormattingException::Throw(
"WKT1 does not support Geographic 3D CRS.");
}
@@ -1922,11 +1961,19 @@ getStandardCriterion(util::IComparable::Criterion criterion) {
bool GeodeticCRS::_isEquivalentTo(
const util::IComparable *other, util::IComparable::Criterion criterion,
const io::DatabaseContextPtr &dbContext) const {
+ if (other == nullptr || !util::isOfExactType<GeodeticCRS>(*other)) {
+ return false;
+ }
+ return _isEquivalentToNoTypeCheck(other, criterion, dbContext);
+}
+
+bool GeodeticCRS::_isEquivalentToNoTypeCheck(
+ const util::IComparable *other, util::IComparable::Criterion criterion,
+ const io::DatabaseContextPtr &dbContext) const {
const auto standardCriterion = getStandardCriterion(criterion);
- auto otherGeodCRS = dynamic_cast<const GeodeticCRS *>(other);
+
// TODO test velocityModel
- return otherGeodCRS != nullptr &&
- SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext);
+ return SingleCRS::baseIsEquivalentTo(other, standardCriterion, dbContext);
}
//! @endcond
@@ -2482,12 +2529,13 @@ bool GeographicCRS::is2DPartOf3D(util::nn<const GeographicCRS *> other,
bool GeographicCRS::_isEquivalentTo(
const util::IComparable *other, util::IComparable::Criterion criterion,
const io::DatabaseContextPtr &dbContext) const {
- auto otherGeogCRS = dynamic_cast<const GeographicCRS *>(other);
- if (otherGeogCRS == nullptr) {
+ if (other == nullptr || !util::isOfExactType<GeographicCRS>(*other)) {
return false;
}
+
const auto standardCriterion = getStandardCriterion(criterion);
- if (GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext)) {
+ if (GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion,
+ dbContext)) {
return true;
}
if (criterion !=
@@ -2506,7 +2554,29 @@ bool GeographicCRS::_isEquivalentTo(
cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH
? cs::EllipsoidalCS::createLatitudeLongitude(unit)
: cs::EllipsoidalCS::createLongitudeLatitude(unit))
- ->GeodeticCRS::_isEquivalentTo(other, standardCriterion, dbContext);
+ ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion,
+ dbContext);
+ }
+ if (axisOrder ==
+ cs::EllipsoidalCS::AxisOrder::LONG_EAST_LAT_NORTH_HEIGHT_UP ||
+ axisOrder ==
+ cs::EllipsoidalCS::AxisOrder::LAT_NORTH_LONG_EAST_HEIGHT_UP) {
+ const auto &angularUnit = coordinateSystem()->axisList()[0]->unit();
+ const auto &linearUnit = coordinateSystem()->axisList()[2]->unit();
+ return GeographicCRS::create(
+ util::PropertyMap().set(common::IdentifiedObject::NAME_KEY,
+ nameStr()),
+ datum(), datumEnsemble(),
+ axisOrder == cs::EllipsoidalCS::AxisOrder::
+ LONG_EAST_LAT_NORTH_HEIGHT_UP
+ ? cs::EllipsoidalCS::
+ createLatitudeLongitudeEllipsoidalHeight(
+ angularUnit, linearUnit)
+ : cs::EllipsoidalCS::
+ createLongitudeLatitudeEllipsoidalHeight(
+ angularUnit, linearUnit))
+ ->GeodeticCRS::_isEquivalentToNoTypeCheck(other, standardCriterion,
+ dbContext);
}
return false;
}
@@ -3605,6 +3675,14 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
return;
}
+ if (!formatter->useESRIDialect() &&
+ formatter->isAllowedEllipsoidalHeightAsVerticalCRS()) {
+ if (exportAsWKT1CompoundCRSWithEllipsoidalHeight(
+ projCRS2D, axisList[2], formatter)) {
+ return;
+ }
+ }
+
io::FormattingException::Throw(
"Projected 3D CRS can only be exported since WKT2:2019");
}
@@ -3885,8 +3963,7 @@ ProjectedCRS::create(const util::PropertyMap &properties,
bool ProjectedCRS::_isEquivalentTo(
const util::IComparable *other, util::IComparable::Criterion criterion,
const io::DatabaseContextPtr &dbContext) const {
- auto otherProjCRS = dynamic_cast<const ProjectedCRS *>(other);
- return otherProjCRS != nullptr &&
+ return other != nullptr && util::isOfExactType<ProjectedCRS>(*other) &&
DerivedCRS::_isEquivalentTo(other, criterion, dbContext);
}
diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp
index 5bc8074c..8e1b8257 100644
--- a/src/iso19111/datum.cpp
+++ b/src/iso19111/datum.cpp
@@ -43,7 +43,6 @@
// clang-format off
#include "proj.h"
#include "proj_internal.h"
-#include "proj_api.h"
// clang-format on
#include "proj_json_streaming_writer.hpp"
@@ -352,6 +351,23 @@ void PrimeMeridian::_exportToWKT(
if (!(isWKT2 && formatter->primeMeridianOmittedIfGreenwich() &&
l_name == "Greenwich")) {
formatter->startNode(io::WKTConstants::PRIMEM, !identifiers().empty());
+
+ if (formatter->useESRIDialect()) {
+ bool aliasFound = false;
+ const auto &dbContext = formatter->databaseContext();
+ if (dbContext) {
+ auto l_alias = dbContext->getAliasFromOfficialName(
+ l_name, "prime_meridian", "ESRI");
+ if (!l_alias.empty()) {
+ l_name = l_alias;
+ aliasFound = true;
+ }
+ }
+ if (!aliasFound) {
+ l_name = io::WKTFormatter::morphNameToESRI(l_name);
+ }
+ }
+
formatter->addQuotedString(l_name);
const auto &l_long = longitude();
if (formatter->primeMeridianInDegree()) {
@@ -418,7 +434,7 @@ std::string
PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) {
const double valRad = angle.getSIValue();
std::string projPMName;
- projCtx ctxt = pj_ctx_alloc();
+ PJ_CONTEXT *ctxt = proj_context_create();
auto proj_pm = proj_list_prime_meridians();
for (int i = 0; proj_pm[i].id != nullptr; ++i) {
double valRefRad = dmstor_ctx(ctxt, proj_pm[i].defn, nullptr);
@@ -427,7 +443,7 @@ PrimeMeridian::getPROJStringWellKnownName(const common::Angle &angle) {
break;
}
}
- pj_ctx_free(ctxt);
+ proj_context_destroy(ctxt);
return projPMName;
}
//! @endcond
@@ -1731,6 +1747,14 @@ void DatumEnsemble::_exportToWKT(
formatter->startNode(io::WKTConstants::ENSEMBLEACCURACY, false);
formatter->add(positionalAccuracy()->value());
formatter->endNode();
+
+ // In theory, we should do the following, but currently the WKT grammar
+ // doesn't allow this
+ // ObjectUsage::baseExportToWKT(formatter);
+ if (formatter->outputId()) {
+ formatID(formatter);
+ }
+
formatter->endNode();
}
//! @endcond
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 5d02aeea..2a03fd4e 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -65,7 +65,6 @@
// clang-format off
#include "proj.h"
#include "proj_internal.h"
-#include "proj_api.h"
// clang-format on
#include <sqlite3.h>
@@ -94,6 +93,12 @@ namespace io {
#define GEOG_3D_SINGLE_QUOTED "'geographic 3D'"
#define GEOCENTRIC_SINGLE_QUOTED "'geocentric'"
+// See data/sql/metadata.sql for the semantics of those constants
+constexpr int DATABASE_LAYOUT_VERSION_MAJOR = 1;
+// If the code depends on the new additions, then DATABASE_LAYOUT_VERSION_MINOR
+// must be incremented.
+constexpr int DATABASE_LAYOUT_VERSION_MINOR = 0;
+
// ---------------------------------------------------------------------------
struct SQLValues {
@@ -192,6 +197,13 @@ struct DatabaseContext::Private {
void cache(const std::string &code,
const datum::GeodeticReferenceFrameNNPtr &datum);
+ datum::DatumEnsemblePtr
+ // cppcheck-suppress functionStatic
+ getDatumEnsembleFromCache(const std::string &code);
+ // cppcheck-suppress functionStatic
+ void cache(const std::string &code,
+ const datum::DatumEnsembleNNPtr &datumEnsemble);
+
datum::EllipsoidPtr
// cppcheck-suppress functionStatic
getEllipsoidFromCache(const std::string &code);
@@ -258,6 +270,7 @@ struct DatabaseContext::Private {
LRUCacheOfObjects cacheCRS_{CACHE_SIZE};
LRUCacheOfObjects cacheEllipsoid_{CACHE_SIZE};
LRUCacheOfObjects cacheGeodeticDatum_{CACHE_SIZE};
+ LRUCacheOfObjects cacheDatumEnsemble_{CACHE_SIZE};
LRUCacheOfObjects cachePrimeMeridian_{CACHE_SIZE};
LRUCacheOfObjects cacheCS_{CACHE_SIZE};
LRUCacheOfObjects cacheExtent_{CACHE_SIZE};
@@ -270,6 +283,8 @@ struct DatabaseContext::Private {
lru11::Cache<std::string, std::list<std::string>> cacheAliasNames_{
CACHE_SIZE};
+ void checkDatabaseLayout();
+
static void insertIntoCache(LRUCacheOfObjects &cache,
const std::string &code,
const util::BaseObjectPtr &obj);
@@ -417,6 +432,22 @@ void DatabaseContext::Private::cache(
// ---------------------------------------------------------------------------
+datum::DatumEnsemblePtr
+DatabaseContext::Private::getDatumEnsembleFromCache(const std::string &code) {
+ util::BaseObjectPtr obj;
+ getFromCache(cacheDatumEnsemble_, code, obj);
+ return std::static_pointer_cast<datum::DatumEnsemble>(obj);
+}
+
+// ---------------------------------------------------------------------------
+
+void DatabaseContext::Private::cache(
+ const std::string &code, const datum::DatumEnsembleNNPtr &datumEnsemble) {
+ insertIntoCache(cacheDatumEnsemble_, code, datumEnsemble.as_nullable());
+}
+
+// ---------------------------------------------------------------------------
+
datum::EllipsoidPtr
DatabaseContext::Private::getEllipsoidFromCache(const std::string &code) {
util::BaseObjectPtr obj;
@@ -548,6 +579,61 @@ void DatabaseContext::Private::open(const std::string &databasePath,
// ---------------------------------------------------------------------------
+void DatabaseContext::Private::checkDatabaseLayout() {
+ auto res = run("SELECT key, value FROM metadata WHERE key IN "
+ "('DATABASE.LAYOUT.VERSION.MAJOR', "
+ "'DATABASE.LAYOUT.VERSION.MINOR')");
+ if (res.size() != 2) {
+ // The database layout of PROJ 7.2 that shipped with EPSG v10.003 is
+ // at the time of writing still compatible of the one we support.
+ static_assert(
+ // cppcheck-suppress knownConditionTrueFalse
+ DATABASE_LAYOUT_VERSION_MAJOR == 1 &&
+ // cppcheck-suppress knownConditionTrueFalse
+ DATABASE_LAYOUT_VERSION_MINOR == 0,
+ "remove that assertion and below lines next time we upgrade "
+ "database structure");
+ res = run("SELECT 1 FROM metadata WHERE key = 'EPSG.VERSION' AND "
+ "value = 'v10.003'");
+ if (!res.empty()) {
+ return;
+ }
+
+ throw FactoryException(
+ databasePath_ +
+ " lacks DATABASE.LAYOUT.VERSION.MAJOR / "
+ "DATABASE.LAYOUT.VERSION.MINOR "
+ "metadata. It comes from another PROJ installation.");
+ }
+ int nMajor = 0;
+ int nMinor = 0;
+ for (const auto &row : res) {
+ if (row[0] == "DATABASE.LAYOUT.VERSION.MAJOR") {
+ nMajor = atoi(row[1].c_str());
+ } else if (row[0] == "DATABASE.LAYOUT.VERSION.MINOR") {
+ nMinor = atoi(row[1].c_str());
+ }
+ }
+ if (nMajor != DATABASE_LAYOUT_VERSION_MAJOR) {
+ throw FactoryException(databasePath_ +
+ " contains DATABASE.LAYOUT.VERSION.MAJOR = " +
+ toString(nMajor) + " whereas " +
+ toString(DATABASE_LAYOUT_VERSION_MAJOR) +
+ " is expected. "
+ "It comes from another PROJ installation.");
+ }
+ if (nMinor < DATABASE_LAYOUT_VERSION_MINOR) {
+ throw FactoryException(databasePath_ +
+ " contains DATABASE.LAYOUT.VERSION.MINOR = " +
+ toString(nMinor) + " whereas a number >= " +
+ toString(DATABASE_LAYOUT_VERSION_MINOR) +
+ " is expected. "
+ "It comes from another PROJ installation.");
+ }
+}
+
+// ---------------------------------------------------------------------------
+
void DatabaseContext::Private::setHandle(sqlite3 *sqlite_handle) {
assert(sqlite_handle);
@@ -865,6 +951,7 @@ DatabaseContext::create(const std::string &databasePath,
if (!auxiliaryDatabasePaths.empty()) {
dbCtx->getPrivate()->attachExtraDatabases(auxiliaryDatabasePaths);
}
+ dbCtx->getPrivate()->checkDatabaseLayout();
return dbCtx;
}
@@ -1064,18 +1151,6 @@ std::string DatabaseContext::getOldProjGridName(const std::string &gridName) {
// ---------------------------------------------------------------------------
-// FIXME: as we don't support datum ensemble yet, add it from name
-static std::string removeEnsembleSuffix(const std::string &name) {
- if (name == "World Geodetic System 1984 ensemble") {
- return "World Geodetic System 1984";
- } else if (name == "European Terrestrial Reference System 1989 ensemble") {
- return "European Terrestrial Reference System 1989";
- }
- return name;
-}
-
-// ---------------------------------------------------------------------------
-
/** \brief Gets the alias name from an official name.
*
* @param officialName Official name. Mandatory
@@ -2012,18 +2087,38 @@ AuthorityFactory::createEllipsoid(const std::string &code) const {
datum::GeodeticReferenceFrameNNPtr
AuthorityFactory::createGeodeticDatum(const std::string &code) const {
+
+ datum::GeodeticReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = true;
+ createGeodeticDatumOrEnsemble(code, datum, datumEnsemble,
+ turnEnsembleAsDatum);
+ return NN_NO_CHECK(datum);
+}
+
+// ---------------------------------------------------------------------------
+
+void AuthorityFactory::createGeodeticDatumOrEnsemble(
+ const std::string &code, datum::GeodeticReferenceFramePtr &outDatum,
+ datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const {
const auto cacheKey(d->authority() + code);
{
- auto datum = d->context()->d->getGeodeticDatumFromCache(cacheKey);
- if (datum) {
- return NN_NO_CHECK(datum);
+ outDatumEnsemble = d->context()->d->getDatumEnsembleFromCache(cacheKey);
+ if (outDatumEnsemble) {
+ if (!turnEnsembleAsDatum)
+ return;
+ outDatumEnsemble = nullptr;
+ }
+ outDatum = d->context()->d->getGeodeticDatumFromCache(cacheKey);
+ if (outDatum) {
+ return;
}
}
auto res =
d->runWithCodeParam("SELECT name, ellipsoid_auth_name, ellipsoid_code, "
"prime_meridian_auth_name, prime_meridian_code, "
"publication_date, frame_reference_epoch, "
- "deprecated FROM geodetic_datum "
+ "ensemble_accuracy, deprecated FROM geodetic_datum "
"WHERE "
"auth_name = ? AND code = ?",
code);
@@ -2040,29 +2135,63 @@ AuthorityFactory::createGeodeticDatum(const std::string &code) const {
const auto &prime_meridian_code = row[4];
const auto &publication_date = row[5];
const auto &frame_reference_epoch = row[6];
- const bool deprecated = row[7] == "1";
- auto ellipsoid = d->createFactory(ellipsoid_auth_name)
- ->createEllipsoid(ellipsoid_code);
- auto pm = d->createFactory(prime_meridian_auth_name)
- ->createPrimeMeridian(prime_meridian_code);
- auto props = d->createPropertiesSearchUsages(
- "geodetic_datum", code, removeEnsembleSuffix(name), deprecated);
- auto anchor = util::optional<std::string>();
- if (!publication_date.empty()) {
- props.set("PUBLICATION_DATE", publication_date);
- }
- auto datum =
- frame_reference_epoch.empty()
- ? datum::GeodeticReferenceFrame::create(props, ellipsoid,
- anchor, pm)
- : util::nn_static_pointer_cast<datum::GeodeticReferenceFrame>(
- datum::DynamicGeodeticReferenceFrame::create(
- props, ellipsoid, anchor, pm,
- common::Measure(c_locale_stod(frame_reference_epoch),
- common::UnitOfMeasure::YEAR),
- util::optional<std::string>()));
- d->context()->d->cache(cacheKey, datum);
- return datum;
+ const auto &ensemble_accuracy = row[7];
+ const bool deprecated = row[8] == "1";
+
+ std::string massagedName = name;
+ if (turnEnsembleAsDatum) {
+ if (name == "World Geodetic System 1984 ensemble") {
+ massagedName = "World Geodetic System 1984";
+ } else if (name ==
+ "European Terrestrial Reference System 1989 ensemble") {
+ massagedName = "European Terrestrial Reference System 1989";
+ }
+ }
+ auto props = d->createPropertiesSearchUsages("geodetic_datum", code,
+ massagedName, deprecated);
+
+ if (!turnEnsembleAsDatum && !ensemble_accuracy.empty()) {
+ auto resMembers =
+ d->run("SELECT member_auth_name, member_code FROM "
+ "geodetic_datum_ensemble_member WHERE "
+ "ensemble_auth_name = ? AND ensemble_code = ? "
+ "ORDER BY sequence",
+ {d->authority(), code});
+
+ std::vector<datum::DatumNNPtr> members;
+ for (const auto &memberRow : resMembers) {
+ members.push_back(
+ d->createFactory(memberRow[0])->createDatum(memberRow[1]));
+ }
+ auto datumEnsemble = datum::DatumEnsemble::create(
+ props, std::move(members),
+ metadata::PositionalAccuracy::create(ensemble_accuracy));
+ d->context()->d->cache(cacheKey, datumEnsemble);
+ outDatumEnsemble = datumEnsemble.as_nullable();
+ } else {
+ auto ellipsoid = d->createFactory(ellipsoid_auth_name)
+ ->createEllipsoid(ellipsoid_code);
+ auto pm = d->createFactory(prime_meridian_auth_name)
+ ->createPrimeMeridian(prime_meridian_code);
+
+ auto anchor = util::optional<std::string>();
+ if (!publication_date.empty()) {
+ props.set("PUBLICATION_DATE", publication_date);
+ }
+ auto datum = frame_reference_epoch.empty()
+ ? datum::GeodeticReferenceFrame::create(
+ props, ellipsoid, anchor, pm)
+ : util::nn_static_pointer_cast<
+ datum::GeodeticReferenceFrame>(
+ datum::DynamicGeodeticReferenceFrame::create(
+ props, ellipsoid, anchor, pm,
+ common::Measure(
+ c_locale_stod(frame_reference_epoch),
+ common::UnitOfMeasure::YEAR),
+ util::optional<std::string>()));
+ d->context()->d->cache(cacheKey, datum);
+ outDatum = datum.as_nullable();
+ }
} catch (const std::exception &ex) {
throw buildFactoryException("geodetic reference frame", code, ex);
}
@@ -2080,9 +2209,23 @@ AuthorityFactory::createGeodeticDatum(const std::string &code) const {
datum::VerticalReferenceFrameNNPtr
AuthorityFactory::createVerticalDatum(const std::string &code) const {
+ datum::VerticalReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = true;
+ createVerticalDatumOrEnsemble(code, datum, datumEnsemble,
+ turnEnsembleAsDatum);
+ return NN_NO_CHECK(datum);
+}
+
+// ---------------------------------------------------------------------------
+
+void AuthorityFactory::createVerticalDatumOrEnsemble(
+ const std::string &code, datum::VerticalReferenceFramePtr &outDatum,
+ datum::DatumEnsemblePtr &outDatumEnsemble, bool turnEnsembleAsDatum) const {
auto res =
d->runWithCodeParam("SELECT name, publication_date, "
- "frame_reference_epoch, deprecated FROM "
+ "frame_reference_epoch, ensemble_accuracy, "
+ "deprecated FROM "
"vertical_datum WHERE auth_name = ? AND code = ?",
code);
if (res.empty()) {
@@ -2094,24 +2237,49 @@ AuthorityFactory::createVerticalDatum(const std::string &code) const {
const auto &name = row[0];
const auto &publication_date = row[1];
const auto &frame_reference_epoch = row[2];
- const bool deprecated = row[3] == "1";
+ const auto &ensemble_accuracy = row[3];
+ const bool deprecated = row[4] == "1";
auto props = d->createPropertiesSearchUsages("vertical_datum", code,
name, deprecated);
- if (!publication_date.empty()) {
- props.set("PUBLICATION_DATE", publication_date);
- }
- if (d->authority() == "ESRI" && starts_with(code, "from_geogdatum_")) {
- props.set("VERT_DATUM_TYPE", "2002");
- }
- auto anchor = util::optional<std::string>();
- if (frame_reference_epoch.empty()) {
- return datum::VerticalReferenceFrame::create(props, anchor);
+ if (!turnEnsembleAsDatum && !ensemble_accuracy.empty()) {
+ auto resMembers =
+ d->run("SELECT member_auth_name, member_code FROM "
+ "vertical_datum_ensemble_member WHERE "
+ "ensemble_auth_name = ? AND ensemble_code = ? "
+ "ORDER BY sequence",
+ {d->authority(), code});
+
+ std::vector<datum::DatumNNPtr> members;
+ for (const auto &memberRow : resMembers) {
+ members.push_back(
+ d->createFactory(memberRow[0])->createDatum(memberRow[1]));
+ }
+ auto datumEnsemble = datum::DatumEnsemble::create(
+ props, std::move(members),
+ metadata::PositionalAccuracy::create(ensemble_accuracy));
+ outDatumEnsemble = datumEnsemble.as_nullable();
} else {
- return datum::DynamicVerticalReferenceFrame::create(
- props, anchor, util::optional<datum::RealizationMethod>(),
- common::Measure(c_locale_stod(frame_reference_epoch),
- common::UnitOfMeasure::YEAR),
- util::optional<std::string>());
+ if (!publication_date.empty()) {
+ props.set("PUBLICATION_DATE", publication_date);
+ }
+ if (d->authority() == "ESRI" &&
+ starts_with(code, "from_geogdatum_")) {
+ props.set("VERT_DATUM_TYPE", "2002");
+ }
+ auto anchor = util::optional<std::string>();
+ if (frame_reference_epoch.empty()) {
+ outDatum = datum::VerticalReferenceFrame::create(props, anchor)
+ .as_nullable();
+ } else {
+ outDatum =
+ datum::DynamicVerticalReferenceFrame::create(
+ props, anchor,
+ util::optional<datum::RealizationMethod>(),
+ common::Measure(c_locale_stod(frame_reference_epoch),
+ common::UnitOfMeasure::YEAR),
+ util::optional<std::string>())
+ .as_nullable();
+ }
}
} catch (const std::exception &ex) {
throw buildFactoryException("vertical reference frame", code, ex);
@@ -2472,20 +2640,24 @@ AuthorityFactory::createGeodeticCRS(const std::string &code,
auto cs =
d->createFactory(cs_auth_name)->createCoordinateSystem(cs_code);
- auto datum =
- d->createFactory(datum_auth_name)->createGeodeticDatum(datum_code);
+ datum::GeodeticReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = false;
+ d->createFactory(datum_auth_name)
+ ->createGeodeticDatumOrEnsemble(datum_code, datum, datumEnsemble,
+ turnEnsembleAsDatum);
auto ellipsoidalCS =
util::nn_dynamic_pointer_cast<cs::EllipsoidalCS>(cs);
if ((type == GEOG_2D || type == GEOG_3D) && ellipsoidalCS) {
auto crsRet = crs::GeographicCRS::create(
- props, datum, NN_NO_CHECK(ellipsoidalCS));
+ props, datum, datumEnsemble, NN_NO_CHECK(ellipsoidalCS));
d->context()->d->cache(cacheKey, crsRet);
return crsRet;
}
auto geocentricCS = util::nn_dynamic_pointer_cast<cs::CartesianCS>(cs);
if (type == GEOCENTRIC && geocentricCS) {
- auto crsRet = crs::GeodeticCRS::create(props, datum,
+ auto crsRet = crs::GeodeticCRS::create(props, datum, datumEnsemble,
NN_NO_CHECK(geocentricCS));
d->context()->d->cache(cacheKey, crsRet);
return crsRet;
@@ -2539,16 +2711,19 @@ AuthorityFactory::createVerticalCRS(const std::string &code) const {
const bool deprecated = row[5] == "1";
auto cs =
d->createFactory(cs_auth_name)->createCoordinateSystem(cs_code);
- auto datum =
- d->createFactory(datum_auth_name)->createVerticalDatum(datum_code);
-
+ datum::VerticalReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = false;
+ d->createFactory(datum_auth_name)
+ ->createVerticalDatumOrEnsemble(datum_code, datum, datumEnsemble,
+ turnEnsembleAsDatum);
auto props = d->createPropertiesSearchUsages("vertical_crs", code, name,
deprecated);
auto verticalCS = util::nn_dynamic_pointer_cast<cs::VerticalCS>(cs);
if (verticalCS) {
- auto crsRet =
- crs::VerticalCRS::create(props, datum, NN_NO_CHECK(verticalCS));
+ auto crsRet = crs::VerticalCRS::create(props, datum, datumEnsemble,
+ NN_NO_CHECK(verticalCS));
d->context()->d->cache(cacheKey, crsRet);
return crsRet;
}
@@ -5340,6 +5515,11 @@ AuthorityFactory::getAuthorityCodes(const ObjectType &type,
case ObjectType::CONCATENATED_OPERATION:
sql = "SELECT code FROM concatenated_operation WHERE ";
break;
+ case ObjectType::DATUM_ENSEMBLE:
+ sql = "SELECT code FROM object_view WHERE table_name IN "
+ "('geodetic_datum', 'vertical_datum') AND "
+ "type = 'ensemble' AND ";
+ break;
}
sql += "auth_name = ?";
@@ -5617,7 +5797,7 @@ std::string AuthorityFactory::getOfficialNameFromAlias(
if (res.empty()) { // shouldn't happen normally
return std::string();
}
- return removeEnsembleSuffix(res.front()[0]);
+ return res.front()[0];
}
}
return std::string();
@@ -5667,7 +5847,7 @@ std::string AuthorityFactory::getOfficialNameFromAlias(
outTableName = row[1];
outAuthName = row[2];
outCode = row[3];
- return removeEnsembleSuffix(row[0]);
+ return row[0];
}
}
@@ -5849,12 +6029,28 @@ AuthorityFactory::createObjectsFromNameEx(
res.emplace_back(
TableType("concatenated_operation", std::string()));
break;
+ case ObjectType::DATUM_ENSEMBLE:
+ res.emplace_back(TableType("geodetic_datum", "ensemble"));
+ res.emplace_back(TableType("vertical_datum", "ensemble"));
+ break;
}
}
}
return res;
};
+ bool datumEnsembleAllowed = false;
+ if (allowedObjectTypes.empty()) {
+ datumEnsembleAllowed = true;
+ } else {
+ for (const auto type : allowedObjectTypes) {
+ if (type == ObjectType::DATUM_ENSEMBLE) {
+ datumEnsembleAllowed = true;
+ break;
+ }
+ }
+ }
+
const auto listTableNameType = getTableAndTypeConstraints();
bool first = true;
ListOfParams params;
@@ -5872,6 +6068,8 @@ AuthorityFactory::createObjectsFromNameEx(
if (!tableNameTypePair.second.empty()) {
if (tableNameTypePair.second == "frame_reference_epoch") {
sql += "AND frame_reference_epoch IS NOT NULL ";
+ } else if (tableNameTypePair.second == "ensemble") {
+ sql += "AND ensemble_accuracy IS NOT NULL ";
} else {
sql += "AND type = '";
sql += tableNameTypePair.second;
@@ -5906,6 +6104,8 @@ AuthorityFactory::createObjectsFromNameEx(
if (!tableNameTypePair.second.empty()) {
if (tableNameTypePair.second == "frame_reference_epoch") {
sql += "AND ov.frame_reference_epoch IS NOT NULL ";
+ } else if (tableNameTypePair.second == "ensemble") {
+ sql += "AND ov.ensemble_accuracy IS NOT NULL ";
} else {
sql += "AND ov.type = '";
sql += tableNameTypePair.second;
@@ -6019,6 +6219,8 @@ AuthorityFactory::createObjectsFromNameEx(
auto sqlRes = d->run(sql, params);
bool isFirst = true;
bool firstIsDeprecated = false;
+ bool foundExactMatch = false;
+ std::size_t hashCodeFirstMatch = 0;
for (const auto &row : sqlRes) {
const auto &name = row[3];
if (approximateMatch) {
@@ -6053,7 +6255,7 @@ AuthorityFactory::createObjectsFromNameEx(
break;
}
auto factory = d->createFactory(auth_name);
- auto getObject = [&factory](
+ auto getObject = [&factory, datumEnsembleAllowed](
const std::string &l_table_name,
const std::string &l_code) -> common::IdentifiedObjectNNPtr {
if (l_table_name == "prime_meridian") {
@@ -6061,8 +6263,32 @@ AuthorityFactory::createObjectsFromNameEx(
} else if (l_table_name == "ellipsoid") {
return factory->createEllipsoid(l_code);
} else if (l_table_name == "geodetic_datum") {
+ if (datumEnsembleAllowed) {
+ datum::GeodeticReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = false;
+ factory->createGeodeticDatumOrEnsemble(
+ l_code, datum, datumEnsemble, turnEnsembleAsDatum);
+ if (datum) {
+ return NN_NO_CHECK(datum);
+ }
+ assert(datumEnsemble);
+ return NN_NO_CHECK(datumEnsemble);
+ }
return factory->createGeodeticDatum(l_code);
} else if (l_table_name == "vertical_datum") {
+ if (datumEnsembleAllowed) {
+ datum::VerticalReferenceFramePtr datum;
+ datum::DatumEnsemblePtr datumEnsemble;
+ constexpr bool turnEnsembleAsDatum = false;
+ factory->createVerticalDatumOrEnsemble(
+ l_code, datum, datumEnsemble, turnEnsembleAsDatum);
+ if (datum) {
+ return NN_NO_CHECK(datum);
+ }
+ assert(datumEnsemble);
+ return NN_NO_CHECK(datumEnsemble);
+ }
return factory->createVerticalDatum(l_code);
} else if (l_table_name == "geodetic_crs") {
return factory->createGeodeticCRS(l_code);
@@ -6082,11 +6308,38 @@ AuthorityFactory::createObjectsFromNameEx(
}
throw std::runtime_error("Unsupported table_name");
};
- res.emplace_back(PairObjectName(getObject(table_name, code), name));
+ const auto obj = getObject(table_name, code);
+ if (metadata::Identifier::canonicalizeName(obj->nameStr()) ==
+ canonicalizedSearchedName) {
+ foundExactMatch = true;
+ }
+
+ const auto objPtr = obj.get();
+ if (res.empty()) {
+ hashCodeFirstMatch = typeid(*objPtr).hash_code();
+ } else if (hashCodeFirstMatch != typeid(*objPtr).hash_code()) {
+ hashCodeFirstMatch = 0;
+ }
+
+ res.emplace_back(PairObjectName(obj, name));
if (limitResultCount > 0 && res.size() == limitResultCount) {
break;
}
}
+
+ // If we found a name that is an exact match, and all objects have the
+ // same type, and we are not in approximate mode, only keep the objet(s)
+ // with the exact name match.
+ if (foundExactMatch && hashCodeFirstMatch != 0 && !approximateMatch) {
+ std::list<PairObjectName> resTmp;
+ for (const auto &pair : res) {
+ if (metadata::Identifier::canonicalizeName(
+ pair.first->nameStr()) == canonicalizedSearchedName) {
+ resTmp.emplace_back(pair);
+ }
+ }
+ res = std::move(resTmp);
+ }
}
auto sortLambda = [](const PairObjectName &a, const PairObjectName &b) {
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index f4ec7740..8a42e7ee 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -70,7 +70,6 @@
// clang-format off
#include "proj.h"
#include "proj_internal.h"
-#include "proj_api.h"
// clang-format on
using namespace NS_PROJ::common;
@@ -140,6 +139,7 @@ struct WKTFormatter::Private {
bool primeMeridianInDegree_ = false;
bool use2019Keywords_ = false;
bool useESRIDialect_ = false;
+ bool allowEllipsoidalHeightAsVerticalCRS_ = false;
OutputAxisRule outputAxis_ = WKTFormatter::OutputAxisRule::YES;
};
Params params_{};
@@ -251,6 +251,8 @@ WKTFormatter::setOutputAxis(OutputAxisRule outputAxisIn) noexcept {
*
* The default is strict mode, in which case a FormattingException can be
* thrown.
+ * In non-strict mode, a Geographic 3D CRS can be for example exported as
+ * WKT1_GDAL with 3 axes, whereas this is normally not allowed.
*/
WKTFormatter &WKTFormatter::setStrict(bool strictIn) noexcept {
d->params_.strict_ = strictIn;
@@ -264,6 +266,28 @@ bool WKTFormatter::isStrict() const noexcept { return d->params_.strict_; }
// ---------------------------------------------------------------------------
+/** \brief Set whether the formatter should export, in WKT1, a Geographic or
+ * Projected 3D CRS as a compound CRS whose vertical part represents an
+ * ellipsoidal height.
+ */
+WKTFormatter &
+WKTFormatter::setAllowEllipsoidalHeightAsVerticalCRS(bool allow) noexcept {
+ d->params_.allowEllipsoidalHeightAsVerticalCRS_ = allow;
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+
+/** \brief Return whether the formatter should export, in WKT1, a Geographic or
+ * Projected 3D CRS as a compound CRS whose vertical part represents an
+ * ellipsoidal height.
+ */
+bool WKTFormatter::isAllowedEllipsoidalHeightAsVerticalCRS() const noexcept {
+ return d->params_.allowEllipsoidalHeightAsVerticalCRS_;
+}
+
+// ---------------------------------------------------------------------------
+
/** Returns the WKT string from the formatter. */
const std::string &WKTFormatter::toString() const {
if (d->indentLevel_ > 0 || d->level_ > 0) {
@@ -1979,14 +2003,80 @@ PrimeMeridianNNPtr WKTParser::Private::buildPrimeMeridian(
try {
double angleValue = asDouble(children[1]);
- // Correct for GDAL WKT1 departure
+ // Correct for GDAL WKT1 and WKT1-ESRI departure
if (name == "Paris" && std::fabs(angleValue - 2.33722917) < 1e-8 &&
- unit == UnitOfMeasure::GRAD) {
+ unit._isEquivalentTo(UnitOfMeasure::GRAD,
+ util::IComparable::Criterion::EQUIVALENT)) {
angleValue = 2.5969213;
+ } else {
+ static const struct {
+ const char *name;
+ int deg;
+ int min;
+ double sec;
+ } primeMeridiansDMS[] = {
+ {"Lisbon", -9, 7, 54.862}, {"Bogota", -74, 4, 51.3},
+ {"Madrid", -3, 41, 14.55}, {"Rome", 12, 27, 8.4},
+ {"Bern", 7, 26, 22.5}, {"Jakarta", 106, 48, 27.79},
+ {"Ferro", -17, 40, 0}, {"Brussels", 4, 22, 4.71},
+ {"Stockholm", 18, 3, 29.8}, {"Athens", 23, 42, 58.815},
+ {"Oslo", 10, 43, 22.5}, {"Paris RGS", 2, 20, 13.95},
+ {"Paris_RGS", 2, 20, 13.95}};
+
+ // Current epsg.org output may use the EPSG:9110 "sexagesimal DMS"
+ // unit and a DD.MMSSsss value, but this will likely be changed to
+ // use decimal degree.
+ // Or WKT1 may for example use the Paris RGS decimal degree value
+ // but with a GEOGCS with UNIT["Grad"]
+ for (const auto &pmDef : primeMeridiansDMS) {
+ if (name == pmDef.name) {
+ double dmsAsDecimalValue =
+ (pmDef.deg >= 0 ? 1 : -1) *
+ (std::abs(pmDef.deg) + pmDef.min / 100. +
+ pmDef.sec / 10000.);
+ double dmsAsDecimalDegreeValue =
+ (pmDef.deg >= 0 ? 1 : -1) *
+ (std::abs(pmDef.deg) + pmDef.min / 60. +
+ pmDef.sec / 3600.);
+ if (std::fabs(angleValue - dmsAsDecimalValue) < 1e-8 ||
+ std::fabs(angleValue - dmsAsDecimalDegreeValue) <
+ 1e-8) {
+ angleValue = dmsAsDecimalDegreeValue;
+ unit = UnitOfMeasure::DEGREE;
+ }
+ break;
+ }
+ }
+ }
+
+ auto &properties = buildProperties(node);
+ if (dbContext_ && esriStyle_) {
+ std::string outTableName;
+ std::string codeFromAlias;
+ std::string authNameFromAlias;
+ auto authFactory = AuthorityFactory::create(NN_NO_CHECK(dbContext_),
+ std::string());
+ auto officialName = authFactory->getOfficialNameFromAlias(
+ name, "prime_meridian", "ESRI", false, outTableName,
+ authNameFromAlias, codeFromAlias);
+ if (!officialName.empty()) {
+ properties.set(IdentifiedObject::NAME_KEY, officialName);
+ if (!authNameFromAlias.empty()) {
+ auto identifiers = ArrayOfBaseObject::create();
+ identifiers->add(Identifier::create(
+ codeFromAlias,
+ PropertyMap()
+ .set(Identifier::CODESPACE_KEY, authNameFromAlias)
+ .set(Identifier::AUTHORITY_KEY,
+ authNameFromAlias)));
+ properties.set(IdentifiedObject::IDENTIFIERS_KEY,
+ identifiers);
+ }
+ }
}
Angle angle(angleValue, unit);
- return PrimeMeridian::create(buildProperties(node), angle);
+ return PrimeMeridian::create(properties, angle);
} catch (const std::exception &e) {
throw buildRethrow(__FUNCTION__, e);
}
@@ -2098,9 +2188,15 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
return false;
};
- if (name == "WGS_1984") {
+ // Remap GDAL WGS_1984 to EPSG v9 "World Geodetic System 1984" official
+ // name.
+ // Also remap EPSG v10 datum ensemble names to non-ensemble EPSG v9
+ if (name == "WGS_1984" || name == "World Geodetic System 1984 ensemble") {
properties.set(IdentifiedObject::NAME_KEY,
GeodeticReferenceFrame::EPSG_6326->nameStr());
+ } else if (name == "European Terrestrial Reference System 1989 ensemble") {
+ properties.set(IdentifiedObject::NAME_KEY,
+ "European Terrestrial Reference System 1989");
} else if (starts_with(name, "D_")) {
esriStyle_ = true;
const char *tableNameForAlias = nullptr;
@@ -2110,6 +2206,10 @@ GeodeticReferenceFrameNNPtr WKTParser::Private::buildGeodeticReferenceFrame(
name = "World Geodetic System 1984";
authNameFromAlias = Identifier::EPSG;
codeFromAlias = "6326";
+ } else if (name == "D_ETRS_1989") {
+ name = "European Terrestrial Reference System 1989";
+ authNameFromAlias = Identifier::EPSG;
+ codeFromAlias = "6258";
} else {
tableNameForAlias = "geodetic_datum";
}
@@ -2734,6 +2834,9 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) {
throw ParsingException("Missing DATUM or ENSEMBLE node");
}
+ // Do that now so that esriStyle_ can be set before buildPrimeMeridian()
+ auto props = buildProperties(node);
+
auto &dynamicNode = nodeP->lookForChild(WKTConstants::DYNAMIC);
auto &csNode = nodeP->lookForChild(WKTConstants::CS_);
@@ -2771,7 +2874,6 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) {
angularUnit = primeMeridian->longitude().unit();
}
- auto props = buildProperties(node);
addExtensionProj4ToProp(nodeP, props);
// No explicit AXIS node ? (WKT1)
@@ -2790,6 +2892,32 @@ WKTParser::Private::buildGeodeticCRS(const WKTNodeNNPtr &node) {
.as_nullable()
: nullptr;
auto cs = buildCS(csNode, node, angularUnit);
+
+ // If there's no CS[] node, typically for a BASEGEODCRS of a projected CRS,
+ // in a few rare cases, this might be a Geocentric CRS, and thus a
+ // Cartesian CS, and not the ellipsoidalCS we assumed above. The only way
+ // to figure that is to resolve the CRS from its code...
+ if (isNull(csNode) && dbContext_ &&
+ ci_equal(nodeName, WKTConstants::BASEGEODCRS)) {
+ const auto &nodeChildren = nodeP->children();
+ for (const auto &subNode : nodeChildren) {
+ const auto &subNodeName(subNode->GP()->value());
+ if (ci_equal(subNodeName, WKTConstants::ID) ||
+ ci_equal(subNodeName, WKTConstants::AUTHORITY)) {
+ auto id = buildId(subNode, true, false);
+ if (id) {
+ try {
+ auto authFactory = AuthorityFactory::create(
+ NN_NO_CHECK(dbContext_), *id->codeSpace());
+ auto dbCRS = authFactory->createGeodeticCRS(id->code());
+ cs = dbCRS->coordinateSystem();
+ } catch (const util::Exception &) {
+ }
+ }
+ }
+ }
+ }
+
auto ellipsoidalCS = nn_dynamic_pointer_cast<EllipsoidalCS>(cs);
if (ellipsoidalCS) {
if (ci_equal(nodeName, WKTConstants::GEOCCS)) {
@@ -2940,7 +3068,8 @@ UnitOfMeasure WKTParser::Private::guessUnitForParameter(
const UnitOfMeasure &defaultAngularUnit) {
UnitOfMeasure unit;
// scale must be first because of 'Scale factor on pseudo standard parallel'
- if (ci_find(paramName, "scale") != std::string::npos) {
+ if (ci_find(paramName, "scale") != std::string::npos ||
+ ci_find(paramName, "scaling factor") != std::string::npos) {
unit = UnitOfMeasure::SCALE_UNITY;
} else if (ci_find(paramName, "latitude") != std::string::npos ||
ci_find(paramName, "longitude") != std::string::npos ||
@@ -3872,8 +4001,16 @@ WKTParser::Private::buildProjectedCRS(const WKTNodeNNPtr &node) {
return createPseudoMercator(props, NN_NO_CHECK(cartesianCS));
}
- auto linearUnit = buildUnitInSubNode(node, UnitOfMeasure::Type::LINEAR);
- auto angularUnit = baseGeodCRS->coordinateSystem()->axisList()[0]->unit();
+ // For WKT2, if there is no explicit parameter unit, use metre for linear
+ // units and degree for angular units
+ auto linearUnit =
+ !isNull(conversionNode)
+ ? UnitOfMeasure::METRE
+ : buildUnitInSubNode(node, UnitOfMeasure::Type::LINEAR);
+ auto angularUnit =
+ !isNull(conversionNode)
+ ? UnitOfMeasure::DEGREE
+ : baseGeodCRS->coordinateSystem()->axisList()[0]->unit();
auto conversion =
!isNull(conversionNode)
@@ -4941,6 +5078,10 @@ class JSONParser {
TransformationNNPtr buildTransformation(const json &j);
ConcatenatedOperationNNPtr buildConcatenatedOperation(const json &j);
+ void buildGeodeticDatumOrDatumEnsemble(const json &j,
+ GeodeticReferenceFramePtr &datum,
+ DatumEnsemblePtr &datumEnsemble);
+
static util::optional<std::string> getAnchor(const json &j) {
util::optional<std::string> anchor;
if (j.contains("anchor")) {
@@ -5400,9 +5541,9 @@ BaseObjectNNPtr JSONParser::create(const json &j)
// ---------------------------------------------------------------------------
-GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
- GeodeticReferenceFramePtr datum;
- DatumEnsemblePtr datumEnsemble;
+void JSONParser::buildGeodeticDatumOrDatumEnsemble(
+ const json &j, GeodeticReferenceFramePtr &datum,
+ DatumEnsemblePtr &datumEnsemble) {
if (j.contains("datum")) {
auto datumJ = getObject(j, "datum");
datum = util::nn_dynamic_pointer_cast<GeodeticReferenceFrame>(
@@ -5415,6 +5556,14 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
datumEnsemble =
buildDatumEnsemble(getObject(j, "datum_ensemble")).as_nullable();
}
+}
+
+// ---------------------------------------------------------------------------
+
+GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
+ GeodeticReferenceFramePtr datum;
+ DatumEnsemblePtr datumEnsemble;
+ buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble);
auto csJ = getObject(j, "coordinate_system");
auto ellipsoidalCS =
util::nn_dynamic_pointer_cast<EllipsoidalCS>(buildCS(csJ));
@@ -5428,12 +5577,9 @@ GeographicCRSNNPtr JSONParser::buildGeographicCRS(const json &j) {
// ---------------------------------------------------------------------------
GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(const json &j) {
- auto datumJ = getObject(j, "datum");
- if (getType(datumJ) != "GeodeticReferenceFrame") {
- throw ParsingException("Unsupported type for datum.");
- }
- auto datum = buildGeodeticReferenceFrame(datumJ);
+ GeodeticReferenceFramePtr datum;
DatumEnsemblePtr datumEnsemble;
+ buildGeodeticDatumOrDatumEnsemble(j, datum, datumEnsemble);
auto csJ = getObject(j, "coordinate_system");
auto cs = buildCS(csJ);
auto props = buildProperties(j);
@@ -5468,7 +5614,13 @@ GeodeticCRSNNPtr JSONParser::buildGeodeticCRS(const json &j) {
// ---------------------------------------------------------------------------
ProjectedCRSNNPtr JSONParser::buildProjectedCRS(const json &j) {
- auto baseCRS = buildGeographicCRS(getObject(j, "base_crs"));
+ auto jBaseCRS = getObject(j, "base_crs");
+ auto jBaseCS = getObject(jBaseCRS, "coordinate_system");
+ auto baseCS = buildCS(jBaseCS);
+ auto baseCRS = dynamic_cast<EllipsoidalCS *>(baseCS.get()) != nullptr
+ ? util::nn_static_pointer_cast<GeodeticCRS>(
+ buildGeographicCRS(jBaseCRS))
+ : buildGeodeticCRS(jBaseCRS);
auto csJ = getObject(j, "coordinate_system");
auto cartesianCS = util::nn_dynamic_pointer_cast<CartesianCS>(buildCS(csJ));
if (!cartesianCS) {
@@ -6263,6 +6415,9 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
if (type == "datum") {
return factory->createDatum(code);
}
+ if (type == "ensemble") {
+ return factory->createDatumEnsemble(code);
+ }
if (type == "ellipsoid") {
return factory->createEllipsoid(code);
}
@@ -6381,6 +6536,8 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text,
AuthorityFactory::ObjectType::
DATUM,
AuthorityFactory::ObjectType::
+ DATUM_ENSEMBLE,
+ AuthorityFactory::ObjectType::
COORDINATE_OPERATION},
goOn);
} catch (const std::exception &) {
@@ -9460,8 +9617,8 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
std::string methodName = "PROJ " + step.name;
for (const auto &param : step.paramValues) {
if (is_in_stringlist(param.key,
- "wktext,no_defs,datum,ellps,a,b,R,towgs84,"
- "nadgrids,geoidgrids,"
+ "wktext,no_defs,datum,ellps,a,b,R,f,rf,"
+ "towgs84,nadgrids,geoidgrids,"
"units,to_meter,vunits,vto_meter,type")) {
continue;
}
@@ -9761,7 +9918,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
paralist *list = pj_expand_init(ctx, init);
ctx->projStringParserCreateFromPROJStringRecursionCounter--;
if (!list) {
- pj_dealloc(init);
+ free(init);
throw ParsingException("cannot expand " + projString);
}
std::string expanded;
@@ -9784,7 +9941,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
}
auto n = t->next;
- pj_dealloc(t);
+ free(t);
t = n;
}
for (const auto &pair : d->steps_[0].paramValues) {
diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake
index 67bc1f4e..3a4880c6 100644
--- a/src/lib_proj.cmake
+++ b/src/lib_proj.cmake
@@ -173,6 +173,7 @@ set(SRC_LIBPROJ_CONVERSIONS
conversions/geoc.cpp
conversions/geocent.cpp
conversions/noop.cpp
+ conversions/topocentric.cpp
conversions/set.cpp
conversions/unitconvert.cpp
)
@@ -217,9 +218,7 @@ set(SRC_LIBPROJ_CORE
dmstor.cpp
ell_set.cpp
ellps.cpp
- errno.cpp
factors.cpp
- fileapi.cpp
fwd.cpp
gauss.cpp
generic_inverse.cpp
@@ -246,10 +245,8 @@ set(SRC_LIBPROJ_CORE
rtodms.cpp
strerrno.cpp
strtod.cpp
- transform.cpp
tsfn.cpp
units.cpp
- utils.cpp
wkt1_generated_parser.c
wkt1_generated_parser.h
wkt1_parser.cpp
@@ -275,7 +272,6 @@ set(SRC_LIBPROJ_CORE
)
set(HEADERS_LIBPROJ
- proj_api.h
proj.h
proj_experimental.h
proj_constants.h
diff --git a/src/log.cpp b/src/log.cpp
index 3cc10cfd..c343e65b 100644
--- a/src/log.cpp
+++ b/src/log.cpp
@@ -48,9 +48,9 @@ void pj_stderr_logger( void *app_data, int level, const char *msg )
/************************************************************************/
/* pj_vlog() */
/************************************************************************/
-void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args );
+void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args );
/* Workhorse for the log functions - relates to pj_log as vsprintf relates to sprintf */
-void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args )
+void pj_vlog( PJ_CONTEXT *ctx, int level, const char *fmt, va_list args )
{
char *msg_buf;
@@ -84,7 +84,7 @@ void pj_vlog( projCtx ctx, int level, const char *fmt, va_list args )
/* pj_log() */
/************************************************************************/
-void pj_log( projCtx ctx, int level, const char *fmt, ... )
+void pj_log( PJ_CONTEXT *ctx, int level, const char *fmt, ... )
{
va_list args;
diff --git a/src/malloc.cpp b/src/malloc.cpp
index c8de6630..6b7fbf26 100644
--- a/src/malloc.cpp
+++ b/src/malloc.cpp
@@ -53,99 +53,13 @@
using namespace NS_PROJ;
-/**********************************************************************/
-void *pj_malloc(size_t size) {
-/***********************************************************************
-Currently, pj_malloc is a hack to solve an errno problem.
-The problem is described in more details at
-https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=86420.
-It seems, that pj_init and similar functions incorrectly
-(under debian/glibs-2.3.2) assume that pj_malloc resets
-errno after success. pj_malloc tries to mimic this.
-
-NOTE (2017-09-29): The problem described at the bugzilla page
-referred to above, is most likely a case of someone not
-understanding the proper usage of errno. We should review
-whether "the problem is actually a problem" in PROJ.4 code.
-
-Library specific allocators can be useful, and improve
-interoperability, if properly used. That is, by making them
-run/initialization time switchable, somewhat like the file i/o
-interface.
-
-But as things stand, we are more likely to get benefit
-from reviewing the code for proper errno usage, which is hard,
-due to the presence of context local and global pj_errnos.
-
-Probably, these were introduced in order to support incomplete
-implementations of thread local errnos at an early phase of the
-implementation of multithreading support in PROJ.4).
-
-It is likely too late to get rid of contexts, but we can still
-benefit from a better usage of errno.
-***********************************************************************/
- int old_errno = errno;
- void *res = malloc(size);
- if ( res && !old_errno )
- errno = 0;
- return res;
-}
-
-
-/**********************************************************************/
-void *pj_calloc (size_t n, size_t size) {
-/***********************************************************************
-pj_calloc is the pj-equivalent of calloc().
-
-It allocates space for an array of <n> elements of size <size>.
-The array is initialized to zeros.
-***********************************************************************/
- void *res = pj_malloc (n*size);
- if (nullptr==res)
- return nullptr;
- memset (res, 0, n*size);
- return res;
-}
-
-
-/**********************************************************************/
-void pj_dalloc(void *ptr) {
-/**********************************************************************/
- free(ptr);
-}
-
-
-/**********************************************************************/
-void *pj_dealloc (void *ptr) {
-/***********************************************************************
-pj_dealloc supports the common use case of "clean up and return a null
-pointer" to signal an error in a multi level allocation:
-
- struct foo { int bar; int *baz; };
-
- struct foo *p = pj_calloc (1, sizeof (struct foo));
- if (0==p)
- return 0;
-
- p->baz = pj_calloc (10, sizeof(int));
- if (0==p->baz)
- return pj_dealloc (p); // clean up + signal error by 0-return
-
- return p; // success
-
-***********************************************************************/
- if (nullptr==ptr)
- return nullptr;
- pj_dalloc (ptr);
- return nullptr;
-}
/**********************************************************************/
char *pj_strdup(const char *str)
/**********************************************************************/
{
size_t len = strlen(str) + 1;
- char *dup = static_cast<char*>(pj_malloc(len));
+ char *dup = static_cast<char*>(malloc(len));
if (dup)
memcpy(dup, str, len);
return dup;
@@ -153,7 +67,7 @@ char *pj_strdup(const char *str)
/*****************************************************************************/
-void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) {
+void *free_params (PJ_CONTEXT *ctx, paralist *start, int errlev) {
/*****************************************************************************
Companion to pj_default_destructor (below). Deallocates a linked list
of "+proj=xxx" initialization parameters.
@@ -164,9 +78,9 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) {
paralist *t, *n;
for (t = start; t; t = n) {
n = t->next;
- pj_dealloc(t);
+ free(t);
}
- pj_ctx_set_errno (ctx, errlev);
+ proj_context_errno_set (ctx, errlev);
return (void *) nullptr;
}
@@ -174,7 +88,7 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) {
/************************************************************************/
-/* pj_free() */
+/* proj_destroy() */
/* */
/* This is the application callable entry point for destroying */
/* a projection definition. It does work generic to all */
@@ -183,15 +97,16 @@ void *pj_dealloc_params (PJ_CONTEXT *ctx, paralist *start, int errlev) {
/* In most cases P->destructor()==pj_default_destructor. */
/************************************************************************/
-void pj_free(PJ *P) {
+PJ *proj_destroy(PJ *P) {
if (nullptr==P || !P->destructor)
- return;
+ return nullptr;
/* free projection parameters - all the hard work is done by */
/* pj_default_destructor, which is supposed */
/* to be called as the last step of the local destructor */
/* pointed to by P->destructor. In most cases, */
/* pj_default_destructor actually *is* what is pointed to */
P->destructor (P, proj_errno(P));
+ return nullptr;
}
/*****************************************************************************/
@@ -218,42 +133,42 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */
/* Note that both, in the multithreaded case, may then contain undefined */
/* values. This is expected behavior. For MT have one ctx per thread */
if (0!=errlev)
- pj_ctx_set_errno (pj_get_ctx(P), errlev);
+ proj_context_errno_set (pj_get_ctx(P), errlev);
if (nullptr==P)
return nullptr;
- pj_dealloc(P->def_size);
- pj_dealloc(P->def_shape);
- pj_dealloc(P->def_spherification);
- pj_dealloc(P->def_ellps);
+ free(P->def_size);
+ free(P->def_shape);
+ free(P->def_spherification);
+ free(P->def_ellps);
delete static_cast<ListOfHGrids*>(P->hgrids_legacy);
delete static_cast<ListOfVGrids*>(P->vgrids_legacy);
- /* We used to call pj_dalloc( P->catalog ), but this will leak */
+ /* We used to call free( P->catalog ), but this will leak */
/* memory. The safe way to clear catalog and grid is to call */
- /* pj_gc_unloadall(pj_get_default_ctx()); and pj_deallocate_grids(); */
+ /* pj_gc_unloadall(pj_get_default_ctx()); and freeate_grids(); */
/* TODO: we should probably have a public pj_cleanup() method to do all */
/* that */
/* free the interface to Charles Karney's geodesic library */
- pj_dealloc( P->geod );
+ free( P->geod );
/* free parameter list elements */
- pj_dealloc_params (pj_get_ctx(P), P->params, errlev);
- pj_dealloc (P->def_full);
+ free_params (pj_get_ctx(P), P->params, errlev);
+ free (P->def_full);
/* free the cs2cs emulation elements */
- pj_free (P->axisswap);
- pj_free (P->helmert);
- pj_free (P->cart);
- pj_free (P->cart_wgs84);
- pj_free (P->hgridshift);
- pj_free (P->vgridshift);
-
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque));
+ proj_destroy (P->axisswap);
+ proj_destroy (P->helmert);
+ proj_destroy (P->cart);
+ proj_destroy (P->cart_wgs84);
+ proj_destroy (P->hgridshift);
+ proj_destroy (P->vgridshift);
+
+ free (static_cast<struct pj_opaque*>(P->opaque));
delete P;
return nullptr;
}
@@ -262,7 +177,6 @@ PJ *pj_default_destructor (PJ *P, int errlev) { /* Destructor */
void proj_cleanup() {
/*****************************************************************************/
pj_clear_initcache();
- pj_deallocate_grids();
FileManager::clearMemoryCache();
pj_clear_hgridshift_knowngrids_cache();
pj_clear_vgridshift_knowngrids_cache();
diff --git a/src/mlfn.cpp b/src/mlfn.cpp
index 80f9163b..763d83ee 100644
--- a/src/mlfn.cpp
+++ b/src/mlfn.cpp
@@ -26,7 +26,7 @@
double *pj_enfn(double es) {
double t, *en;
- en = (double *) pj_malloc(EN_SIZE * sizeof (double));
+ en = (double *) malloc(EN_SIZE * sizeof (double));
if (nullptr==en)
return nullptr;
@@ -45,7 +45,7 @@ pj_mlfn(double phi, double sphi, double cphi, const double *en) {
}
double
-pj_inv_mlfn(projCtx ctx, double arg, double es, const double *en) {
+pj_inv_mlfn(PJ_CONTEXT *ctx, double arg, double es, const double *en) {
double sinphi_ignored;
double cosphi_ignored;
return inline_pj_inv_mlfn(ctx, arg, es, en, &sinphi_ignored, &cosphi_ignored);
diff --git a/src/mlfn.hpp b/src/mlfn.hpp
index 26a2959f..228c65a4 100644
--- a/src/mlfn.hpp
+++ b/src/mlfn.hpp
@@ -15,7 +15,7 @@ inline static double inline_pj_mlfn(double phi, double sphi, double cphi, const
}
inline static double
-inline_pj_inv_mlfn(projCtx ctx, double arg, double es, const double *en,
+inline_pj_inv_mlfn(PJ_CONTEXT *ctx, double arg, double es, const double *en,
double* sinphi, double* cosphi) {
const double k = 1./(1.-es);
constexpr double INV_MLFN_EPS = 1e-11;
@@ -66,7 +66,7 @@ inline_pj_inv_mlfn(projCtx ctx, double arg, double es, const double *en,
}
*sinphi = s;
*cosphi = c;
- pj_ctx_set_errno( ctx, PJD_ERR_NON_CONV_INV_MERI_DIST );
+ proj_context_errno_set( ctx, PJD_ERR_NON_CONV_INV_MERI_DIST );
return phi;
}
diff --git a/src/mutex.cpp b/src/mutex.cpp
index da415e55..b1a23ccd 100644
--- a/src/mutex.cpp
+++ b/src/mutex.cpp
@@ -33,13 +33,8 @@
#include "proj.h"
#ifndef _WIN32
#include "proj_config.h"
-#include "proj_internal.h"
-#else
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-#include "proj_api.h"
#endif
+#include "proj_internal.h"
/* on win32 we always use win32 mutexes, even if pthreads are available */
#if defined(_WIN32) && !defined(MUTEX_stub)
@@ -184,7 +179,7 @@ void pj_cleanup_lock()
#include <windows.h>
-static HANDLE mutex_lock = NULL;
+static HANDLE mutex_lock = nullptr;
#if _WIN32_WINNT >= 0x0600
@@ -199,7 +194,7 @@ static BOOL CALLBACK pj_create_lock(PINIT_ONCE InitOnce,
(void)InitOnce;
(void)Parameter;
(void)Context;
- mutex_lock = CreateMutex( NULL, FALSE, NULL );
+ mutex_lock = CreateMutex( nullptr, FALSE, nullptr );
return TRUE;
}
#endif
@@ -213,10 +208,10 @@ static void pj_init_lock()
{
#if _WIN32_WINNT >= 0x0600
static INIT_ONCE sInitOnce = INIT_ONCE_STATIC_INIT;
- InitOnceExecuteOnce( &sInitOnce, pj_create_lock, NULL, NULL );
+ InitOnceExecuteOnce( &sInitOnce, pj_create_lock, nullptr, nullptr );
#else
- if( mutex_lock == NULL )
- mutex_lock = CreateMutex( NULL, FALSE, NULL );
+ if( mutex_lock == nullptr )
+ mutex_lock = CreateMutex( nullptr, FALSE, nullptr );
#endif
}
@@ -228,7 +223,7 @@ static void pj_init_lock()
void pj_acquire_lock()
{
- if( mutex_lock == NULL )
+ if( mutex_lock == nullptr )
pj_init_lock();
WaitForSingleObject( mutex_lock, INFINITE );
@@ -242,7 +237,7 @@ void pj_acquire_lock()
void pj_release_lock()
{
- if( mutex_lock == NULL )
+ if( mutex_lock == nullptr )
pj_init_lock();
else
ReleaseMutex( mutex_lock );
@@ -253,10 +248,10 @@ void pj_release_lock()
/************************************************************************/
void pj_cleanup_lock()
{
- if( mutex_lock != NULL )
+ if( mutex_lock != nullptr )
{
CloseHandle( mutex_lock );
- mutex_lock = NULL;
+ mutex_lock = nullptr;
}
}
diff --git a/src/networkfilemanager.cpp b/src/networkfilemanager.cpp
index f6521ed2..9edffaad 100644
--- a/src/networkfilemanager.cpp
+++ b/src/networkfilemanager.cpp
@@ -1315,7 +1315,7 @@ std::unique_ptr<File> NetworkFile::open(PJ_CONTEXT *ctx, const char *filename) {
errorBuffer.resize(strlen(errorBuffer.data()));
pj_log(ctx, PJ_LOG_ERROR, "Cannot open %s: %s", filename,
errorBuffer.c_str());
- pj_ctx_set_errno(ctx, PJD_ERR_NETWORK_ERROR);
+ proj_context_errno_set(ctx, PJD_ERR_NETWORK_ERROR);
}
bool ok = false;
@@ -1404,7 +1404,7 @@ size_t NetworkFile::read(void *buffer, size_t sizeBytes) {
&nRead, errorBuffer.size(), &errorBuffer[0],
m_ctx->networking.user_data);
if (!m_handle) {
- pj_ctx_set_errno(m_ctx, PJD_ERR_NETWORK_ERROR);
+ proj_context_errno_set(m_ctx, PJD_ERR_NETWORK_ERROR);
return 0;
}
} else {
@@ -1420,7 +1420,7 @@ size_t NetworkFile::read(void *buffer, size_t sizeBytes) {
pj_log(m_ctx, PJ_LOG_ERROR, "Cannot read in %s: %s",
m_url.c_str(), errorBuffer.c_str());
}
- pj_ctx_set_errno(m_ctx, PJD_ERR_NETWORK_ERROR);
+ proj_context_errno_set(m_ctx, PJD_ERR_NETWORK_ERROR);
return 0;
}
diff --git a/src/param.cpp b/src/param.cpp
index 289faca3..28d6bc3e 100644
--- a/src/param.cpp
+++ b/src/param.cpp
@@ -38,7 +38,7 @@ static void unquote_string(char* param_str) {
paralist *pj_mkparam(const char *str) {
paralist *newitem;
- if((newitem = (paralist *)pj_malloc(sizeof(paralist) + strlen(str))) != nullptr) {
+ if((newitem = (paralist *)malloc(sizeof(paralist) + strlen(str))) != nullptr) {
newitem->used = 0;
newitem->next = nullptr;
if (*str == '+')
@@ -82,7 +82,7 @@ paralist *pj_mkparam_ws (const char *str, const char **next_str) {
*next_str = str + len;
/* Use calloc to automagically 0-terminate the copy */
- newitem = (paralist *) pj_calloc (1, sizeof(paralist) + len + 1);
+ newitem = (paralist *) calloc (1, sizeof(paralist) + len + 1);
if (nullptr==newitem)
return nullptr;
memcpy(newitem->param, str, len);
@@ -151,7 +151,7 @@ paralist *pj_param_exists (paralist *list, const char *parameter) {
/* */
/************************************************************************/
-PROJVALUE pj_param (projCtx ctx, paralist *pl, const char *opt) {
+PROJVALUE pj_param (PJ_CONTEXT *ctx, paralist *pl, const char *opt) {
int type;
unsigned l;
@@ -220,7 +220,7 @@ PROJVALUE pj_param (projCtx ctx, paralist *pl, const char *opt) {
value.i = 1;
break;
default:
- pj_ctx_set_errno (ctx, PJD_ERR_INVALID_BOOLEAN_PARAM);
+ proj_context_errno_set (ctx, PJD_ERR_INVALID_BOOLEAN_PARAM);
value.i = 0;
break;
}
diff --git a/src/phi2.cpp b/src/phi2.cpp
index b81456b0..2f258e47 100644
--- a/src/phi2.cpp
+++ b/src/phi2.cpp
@@ -1,68 +1,134 @@
/* Determine latitude angle phi-2. */
#include <math.h>
+#include <limits>
+#include <algorithm>
#include "proj.h"
#include "proj_internal.h"
-static const double TOL = 1.0e-10;
-static const int N_ITER = 15;
+double pj_sinhpsi2tanphi(PJ_CONTEXT *ctx, const double taup, const double e) {
+ /****************************************************************************
+ * Convert tau' = sinh(psi) = tan(chi) to tau = tan(phi). The code is taken
+ * from GeographicLib::Math::tauf(taup, e).
+ *
+ * Here
+ * phi = geographic latitude (radians)
+ * psi is the isometric latitude
+ * psi = asinh(tan(phi)) - e * atanh(e * sin(phi))
+ * = asinh(tan(chi))
+ * chi is the conformal latitude
+ *
+ * The representation of latitudes via their tangents, tan(phi) and tan(chi),
+ * maintains full *relative* accuracy close to latitude = 0 and +/- pi/2.
+ * This is sometimes important, e.g., to compute the scale of the transverse
+ * Mercator projection which involves cos(phi)/cos(chi) tan(phi)
+ *
+ * From Karney (2011), Eq. 7,
+ *
+ * tau' = sinh(psi) = sinh(asinh(tan(phi)) - e * atanh(e * sin(phi)))
+ * = tan(phi) * cosh(e * atanh(e * sin(phi))) -
+ * sec(phi) * sinh(e * atanh(e * sin(phi)))
+ * = tau * sqrt(1 + sigma^2) - sqrt(1 + tau^2) * sigma
+ * where
+ * sigma = sinh(e * atanh( e * tau / sqrt(1 + tau^2) ))
+ *
+ * For e small,
+ *
+ * tau' = (1 - e^2) * tau
+ *
+ * The relation tau'(tau) can therefore by reliably inverted by Newton's
+ * method with
+ *
+ * tau = tau' / (1 - e^2)
+ *
+ * as an initial guess. Newton's method requires dtau'/dtau. Noting that
+ *
+ * dsigma/dtau = e^2 * sqrt(1 + sigma^2) /
+ * (sqrt(1 + tau^2) * (1 + (1 - e^2) * tau^2))
+ * d(sqrt(1 + tau^2))/dtau = tau / sqrt(1 + tau^2)
+ *
+ * we have
+ *
+ * dtau'/dtau = (1 - e^2) * sqrt(1 + tau'^2) * sqrt(1 + tau^2) /
+ * (1 + (1 - e^2) * tau^2)
+ *
+ * This works fine unless tau^2 and tau'^2 overflows. This may be partially
+ * cured by writing, e.g., sqrt(1 + tau^2) as hypot(1, tau). However, nan
+ * will still be generated with tau' = inf, since (inf - inf) will appear in
+ * the Newton iteration.
+ *
+ * If we note that for sufficiently large |tau|, i.e., |tau| >= 2/sqrt(eps),
+ * sqrt(1 + tau^2) = |tau| and
+ *
+ * tau' = exp(- e * atanh(e)) * tau
+ *
+ * So
+ *
+ * tau = exp(e * atanh(e)) * tau'
+ *
+ * can be returned unless |tau| >= 2/sqrt(eps); this then avoids overflow
+ * problems for large tau' and returns the correct result for tau' = +/-inf
+ * and nan.
+ *
+ * Newton's method usually take 2 iterations to converge to double precision
+ * accuracy (for WGS84 flattening). However only 1 iteration is needed for
+ * |chi| < 3.35 deg. In addition, only 1 iteration is needed for |chi| >
+ * 89.18 deg (tau' > 70), if tau = exp(e * atanh(e)) * tau' is used as the
+ * starting guess.
+ ****************************************************************************/
-/*****************************************************************************/
-double pj_phi2(projCtx ctx, const double ts0, const double e) {
-/******************************************************************************
-Determine latitude angle phi-2.
-Inputs:
- ts = exp(-psi) where psi is the isometric latitude (dimensionless)
- e = eccentricity of the ellipsoid (dimensionless)
-Output:
- phi = geographic latitude (radians)
-Here isometric latitude is defined by
- psi = log( tan(pi/4 + phi/2) *
- ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) )
- = asinh(tan(phi)) - e * atanh(e * sin(phi))
-This routine inverts this relation using the iterative scheme given
-by Snyder (1987), Eqs. (7-9) - (7-11)
-*******************************************************************************/
- const double eccnth = .5 * e;
- double ts = ts0;
-#ifdef no_longer_used_original_convergence_on_exact_dphi
- double Phi = M_HALFPI - 2. * atan(ts);
-#endif
- int i = N_ITER;
+ constexpr int numit = 5;
+ // min iterations = 1, max iterations = 2; mean = 1.954
+ static const double rooteps = sqrt(std::numeric_limits<double>::epsilon());
+ static const double tol = rooteps / 10; // the criterion for Newton's method
+ static const double tmax = 2 / rooteps; // threshold for large arg limit exact
+ const double e2m = 1 - e * e;
+ const double stol = tol * std::max(1.0, fabs(taup));
+ // The initial guess. 70 corresponds to chi = 89.18 deg (see above)
+ double tau = fabs(taup) > 70 ? taup * exp(e * atanh(e)) : taup / e2m;
+ if (!(fabs(tau) < tmax)) // handles +/-inf and nan and e = 1
+ return tau;
+ // If we need to deal with e > 1, then we could include:
+ // if (e2m < 0) return std::numeric_limits<double>::quiet_NaN();
+ int i = numit;
+ for (; i; --i) {
+ double tau1 = sqrt(1 + tau * tau);
+ double sig = sinh( e * atanh(e * tau / tau1) );
+ double taupa = sqrt(1 + sig * sig) * tau - sig * tau1;
+ double dtau = ( (taup - taupa) * (1 + e2m * (tau * tau)) /
+ (e2m * tau1 * sqrt(1 + taupa * taupa)) );
+ tau += dtau;
+ if (!(fabs(dtau) >= stol)) // backwards test to allow nans to succeed.
+ break;
+ }
+ if (i == 0)
+ proj_context_errno_set(ctx, PJD_ERR_NON_CONV_SINHPSI2TANPHI);
+ return tau;
+}
- for(;;) {
- /*
- * sin(Phi) = sin(PI/2 - 2* atan(ts))
- * = cos(2*atan(ts))
- * = 2*cos^2(atan(ts)) - 1
- * = 2 / (1 + ts^2) - 1
- * = (1 - ts^2) / (1 + ts^2)
- */
- const double sinPhi = (1 - ts * ts) / (1 + ts * ts);
- const double con = e * sinPhi;
- double old_ts = ts;
- ts = ts0 * pow((1. - con) / (1. + con), eccnth);
-#ifdef no_longer_used_original_convergence_on_exact_dphi
- /* The convergence criterion is nominally on exact dphi */
- const double newPhi = M_HALFPI - 2. * atan(ts);
- const double dphi = newPhi - Phi;
- Phi = newPhi;
-#else
- /* If we don't immediately update Phi from this, we can
- * change the conversion criterion to save us computing atan() at each step.
- * Particularly we can observe that:
- * |atan(ts) - atan(old_ts)| <= |ts - old_ts|
- * So if |ts - old_ts| matches our convergence criterion, we're good.
- */
- const double dphi = 2 * (ts - old_ts);
-#endif
- if (fabs(dphi) > TOL && --i) {
- continue;
- }
- break;
- }
- if (i <= 0)
- pj_ctx_set_errno(ctx, PJD_ERR_NON_CON_INV_PHI2);
- return M_HALFPI - 2. * atan(ts);
+/*****************************************************************************/
+double pj_phi2(PJ_CONTEXT *ctx, const double ts0, const double e) {
+ /****************************************************************************
+ * Determine latitude angle phi-2.
+ * Inputs:
+ * ts = exp(-psi) where psi is the isometric latitude (dimensionless)
+ * this variable is defined in Snyder (1987), Eq. (7-10)
+ * e = eccentricity of the ellipsoid (dimensionless)
+ * Output:
+ * phi = geographic latitude (radians)
+ * Here isometric latitude is defined by
+ * psi = log( tan(pi/4 + phi/2) *
+ * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) )
+ * = asinh(tan(phi)) - e * atanh(e * sin(phi))
+ * = asinh(tan(chi))
+ * chi = conformal latitude
+ *
+ * This routine converts t = exp(-psi) to
+ *
+ * tau' = tan(chi) = sinh(psi) = (1/t - t)/2
+ *
+ * returns atan(sinpsi2tanphi(tau'))
+ ***************************************************************************/
+ return atan(pj_sinhpsi2tanphi(ctx, (1/ts0 - ts0) / 2, e));
}
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index 80ee0397..e9d11604 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -294,8 +294,8 @@ static PJ *destructor (PJ *P, int errlev) {
auto pipeline = static_cast<struct Pipeline*>(P->opaque);
- pj_dealloc (pipeline->argv);
- pj_dealloc (pipeline->current_argv);
+ free (pipeline->argv);
+ free (pipeline->current_argv);
delete pipeline;
P->opaque = nullptr;
@@ -321,7 +321,7 @@ static const char *argv_sentinel = "step";
static char **argv_params (paralist *params, size_t argc) {
char **argv;
size_t i = 0;
- argv = static_cast<char**>(pj_calloc (argc, sizeof (char *)));
+ argv = static_cast<char**>(calloc (argc, sizeof (char *)));
if (nullptr==argv)
return nullptr;
for (; params != nullptr; params = params->next)
@@ -461,7 +461,7 @@ PJ *OPERATION(pipeline,0) {
if (nullptr==argv)
return destructor (P, ENOMEM);
- pipeline->current_argv = current_argv = static_cast<char**>(pj_calloc (argc, sizeof (char *)));
+ pipeline->current_argv = current_argv = static_cast<char**>(calloc (argc, sizeof (char *)));
if (nullptr==current_argv)
return destructor (P, ENOMEM);
@@ -533,7 +533,7 @@ PJ *OPERATION(pipeline,0) {
int err_to_report = proj_errno(P);
if (0==err_to_report)
err_to_report = PJD_ERR_MALFORMED_PIPELINE;
- proj_log_error (P, "Pipeline: Bad step definition: %s (%s)", current_argv[0], pj_strerrno (err_to_report));
+ proj_log_error (P, "Pipeline: Bad step definition: %s (%s)", current_argv[0], proj_errno_string (err_to_report));
return destructor (P, err_to_report); /* ERROR: bad pipeline def */
}
next_step->parent = P;
@@ -679,7 +679,7 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) {
static PJ *setup_pushpop(PJ *P) {
- auto pushpop = static_cast<struct PushPop*>(pj_calloc (1, sizeof(struct PushPop)));
+ auto pushpop = static_cast<struct PushPop*>(calloc (1, sizeof(struct PushPop)));
P->opaque = pushpop;
if (nullptr==P->opaque)
return destructor(P, ENOMEM);
diff --git a/src/pj_list.h b/src/pj_list.h
index bcdc189e..d00e780f 100644
--- a/src/pj_list.h
+++ b/src/pj_list.h
@@ -155,6 +155,7 @@ PROJ_HEAD(tinshift, "Triangulation based transformation")
PROJ_HEAD(tissot, "Tissot Conic")
PROJ_HEAD(tmerc, "Transverse Mercator")
PROJ_HEAD(tobmerc, "Tobler-Mercator")
+PROJ_HEAD(topocentric, "Geocentric/Topocentric conversion")
PROJ_HEAD(tpeqd, "Two Point Equidistant")
PROJ_HEAD(tpers, "Tilted perspective")
PROJ_HEAD(unitconvert, "Unit conversion")
diff --git a/src/pr_list.cpp b/src/pr_list.cpp
index 77db5bfb..30fc6571 100644
--- a/src/pr_list.cpp
+++ b/src/pr_list.cpp
@@ -66,7 +66,7 @@ char *pj_get_def( PJ *P, int options )
size_t def_max = 10;
(void) options;
- definition = (char *) pj_malloc(def_max);
+ definition = (char *) malloc(def_max);
if (!definition)
return nullptr;
definition[0] = '\0';
@@ -84,14 +84,14 @@ char *pj_get_def( PJ *P, int options )
char *def2;
def_max = def_max * 2 + l + 5;
- def2 = (char *) pj_malloc(def_max);
+ def2 = (char *) malloc(def_max);
if (def2) {
strcpy( def2, definition );
- pj_dalloc( definition );
+ free( definition );
definition = def2;
}
else {
- pj_dalloc( definition );
+ free( definition );
return nullptr;
}
}
diff --git a/src/proj.h b/src/proj.h
index e77a5984..d4defc47 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -119,8 +119,8 @@
#include <stddef.h> /* For size_t */
-#ifdef PROJ_API_H
-#error proj.h must be included before proj_api.h
+#ifdef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
+ #error "The proj_api.h header has been removed from PROJ with version 8.0.0"
#endif
#ifdef PROJ_RENAME_SYMBOLS
@@ -340,9 +340,9 @@ typedef enum PJ_LOG_LEVEL {
typedef void (*PJ_LOG_FUNCTION)(void *, int, const char *);
-/* The context type - properly namespaced synonym for projCtx */
-struct projCtx_t;
-typedef struct projCtx_t PJ_CONTEXT;
+/* The context type - properly namespaced synonym for pj_ctx */
+struct pj_ctx;
+typedef struct pj_ctx PJ_CONTEXT;
/* A P I */
@@ -694,7 +694,8 @@ typedef enum
PJ_CATEGORY_PRIME_MERIDIAN,
PJ_CATEGORY_DATUM,
PJ_CATEGORY_CRS,
- PJ_CATEGORY_COORDINATE_OPERATION
+ PJ_CATEGORY_COORDINATE_OPERATION,
+ PJ_CATEGORY_DATUM_ENSEMBLE
} PJ_CATEGORY;
/** \brief Object type. */
diff --git a/src/proj_api.h b/src/proj_api.h
deleted file mode 100644
index a26088ca..00000000
--- a/src/proj_api.h
+++ /dev/null
@@ -1,227 +0,0 @@
-/******************************************************************************
- * Project: PROJ.4
- * Purpose: Public (application) include file for PROJ.4 API, and constants.
- * Author: Frank Warmerdam, <warmerdam@pobox.com>
- *
- ******************************************************************************
- * Copyright (c) 2001, Frank Warmerdam <warmerdam@pobox.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.
- *****************************************************************************/
-
-/*
- * This version number should be updated with every release!
- *
- * This file is expected to be removed from the PROJ distribution
- * when a few minor-version releases has been made.
- *
- */
-
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#error 'To use the proj_api.h you must define the macro ACCEPT_USE_OF_DEPRECATED_PROJ_API_H'
-#endif
-
-#ifndef PJ_VERSION
-#define PJ_VERSION 800
-#endif
-
-#ifdef PROJ_RENAME_SYMBOLS
-#include "proj_symbol_rename.h"
-#endif
-
-
-/* If we're not asked for PJ_VERSION only, give them everything */
-#ifndef PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY
-/* General projections header file */
-#ifndef PROJ_API_H
-#define PROJ_API_H
-
-/* standard inclusions */
-#include <math.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-#ifndef PROJ_DLL
-#ifdef PROJ_MSVC_DLL_EXPORT
-#define PROJ_DLL __declspec(dllexport)
-#elif defined(PROJ_MSVC_DLL_IMPORT)
-#define PROJ_DLL __declspec(dllimport)
-#elif defined(__GNUC__)
-#define PROJ_DLL __attribute__ ((visibility("default")))
-#else
-#define PROJ_DLL
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* pj_init() and similar functions can be used with a non-C locale */
-/* Can be detected too at runtime if the symbol pj_atof exists */
-#define PJ_LOCALE_SAFE 1
-
-#define RAD_TO_DEG 57.295779513082321
-#define DEG_TO_RAD .017453292519943296
-
-
-#if defined(PROJ_H)
-#define PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API
-#endif
-
-
-
-extern char const PROJ_DLL pj_release[]; /* global release id string */
-PROJ_DLL extern int pj_errno; /* global error return code */
-
-#ifndef PROJ_INTERNAL_H
-/* replaced by enum proj_log_level in proj_internal.h */
-#define PJ_LOG_NONE 0
-#define PJ_LOG_ERROR 1
-#define PJ_LOG_DEBUG_MAJOR 2
-#define PJ_LOG_DEBUG_MINOR 3
-#endif
-
-#ifdef PROJ_API_H_NOT_INVOKED_AS_PRIMARY_API
- /* These make the function declarations below conform with classic proj */
- typedef PJ *projPJ; /* projPJ is a pointer to PJ */
- typedef struct projCtx_t *projCtx; /* projCtx is a pointer to projCtx_t */
-# define projXY PJ_XY
-# define projLP PJ_LP
-# define projXYZ PJ_XYZ
-# define projLPZ PJ_LPZ
-
-#else
- /* i.e. proj_api invoked as primary API */
- typedef struct { double u, v; } projUV;
- typedef struct { double u, v, w; } projUVW;
- typedef void *projPJ;
- #define projXY projUV
- #define projLP projUV
- #define projXYZ projUVW
- #define projLPZ projUVW
- typedef void *projCtx;
-#endif
-
-
-/* If included *after* proj.h finishes, we have alternative names */
-/* file reading api, like stdio */
-typedef int *PAFile;
-typedef struct projFileAPI_t {
- PAFile (*FOpen)(projCtx ctx, const char *filename, const char *access);
- size_t (*FRead)(void *buffer, size_t size, size_t nmemb, PAFile file);
- int (*FSeek)(PAFile file, long offset, int whence);
- long (*FTell)(PAFile file);
- void (*FClose)(PAFile);
-} projFileAPI;
-
-
-
-/* procedure prototypes */
-
-projCtx PROJ_DLL pj_get_default_ctx(void);
-projCtx PROJ_DLL pj_get_ctx( projPJ );
-
-projXY PROJ_DLL pj_fwd(projLP, projPJ);
-projLP PROJ_DLL pj_inv(projXY, projPJ);
-
-projXYZ PROJ_DLL pj_fwd3d(projLPZ, projPJ);
-projLPZ PROJ_DLL pj_inv3d(projXYZ, projPJ);
-
-
-int PROJ_DLL pj_transform( projPJ src, projPJ dst, long point_count, int point_offset,
- double *x, double *y, double *z );
-int PROJ_DLL pj_datum_transform( projPJ src, projPJ dst, long point_count, int point_offset,
- double *x, double *y, double *z );
-int PROJ_DLL pj_geocentric_to_geodetic( double a, double es,
- long point_count, int point_offset,
- double *x, double *y, double *z );
-int PROJ_DLL pj_geodetic_to_geocentric( double a, double es,
- long point_count, int point_offset,
- double *x, double *y, double *z );
-int PROJ_DLL pj_compare_datums( projPJ srcdefn, projPJ dstdefn );
-int PROJ_DLL pj_apply_gridshift( projCtx, const char *, int,
- long point_count, int point_offset,
- double *x, double *y, double *z );
-void PROJ_DLL pj_deallocate_grids(void);
-void PROJ_DLL pj_clear_initcache(void);
-int PROJ_DLL pj_is_latlong(projPJ);
-int PROJ_DLL pj_is_geocent(projPJ);
-void PROJ_DLL pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared);
-void PROJ_DLL pj_pr_list(projPJ);
-void PROJ_DLL pj_free(projPJ);
-void PROJ_DLL pj_set_finder( const char *(*)(const char *) );
-void PROJ_DLL pj_set_searchpath ( int count, const char **path );
-projPJ PROJ_DLL pj_init(int, char **);
-projPJ PROJ_DLL pj_init_plus(const char *);
-projPJ PROJ_DLL pj_init_ctx( projCtx, int, char ** );
-projPJ PROJ_DLL pj_init_plus_ctx( projCtx, const char * );
-char PROJ_DLL *pj_get_def(projPJ, int);
-projPJ PROJ_DLL pj_latlong_from_proj( projPJ );
-int PROJ_DLL pj_has_inverse(projPJ);
-
-
-void PROJ_DLL *pj_malloc(size_t);
-void PROJ_DLL pj_dalloc(void *);
-void PROJ_DLL *pj_calloc (size_t n, size_t size);
-void PROJ_DLL *pj_dealloc (void *ptr);
-char PROJ_DLL *pj_strdup(const char *str);
-char PROJ_DLL *pj_strerrno(int);
-int PROJ_DLL *pj_get_errno_ref(void);
-const char PROJ_DLL *pj_get_release(void);
-void PROJ_DLL pj_acquire_lock(void);
-void PROJ_DLL pj_release_lock(void);
-void PROJ_DLL pj_cleanup_lock(void);
-
-void PROJ_DLL pj_set_ctx( projPJ, projCtx );
-projCtx PROJ_DLL pj_ctx_alloc(void);
-void PROJ_DLL pj_ctx_free( projCtx );
-int PROJ_DLL pj_ctx_get_errno( projCtx );
-void PROJ_DLL pj_ctx_set_errno( projCtx, int );
-void PROJ_DLL pj_ctx_set_debug( projCtx, int );
-void PROJ_DLL pj_ctx_set_logger( projCtx, void (*)(void *, int, const char *) );
-void PROJ_DLL pj_ctx_set_app_data( projCtx, void * );
-void PROJ_DLL *pj_ctx_get_app_data( projCtx );
-void PROJ_DLL pj_ctx_set_fileapi( projCtx, projFileAPI *);
-projFileAPI PROJ_DLL *pj_ctx_get_fileapi( projCtx );
-
-void PROJ_DLL pj_log( projCtx ctx, int level, const char *fmt, ... );
-void PROJ_DLL pj_stderr_logger( void *, int, const char * );
-
-/* file api */
-projFileAPI PROJ_DLL *pj_get_default_fileapi(void);
-
-PAFile PROJ_DLL pj_ctx_fopen(projCtx ctx, const char *filename, const char *access);
-size_t PROJ_DLL pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file);
-int PROJ_DLL pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence);
-long PROJ_DLL pj_ctx_ftell(projCtx ctx, PAFile file);
-void PROJ_DLL pj_ctx_fclose(projCtx ctx, PAFile file);
-char PROJ_DLL *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file);
-
-PAFile PROJ_DLL pj_open_lib(projCtx, const char *, const char *);
-int PROJ_DLL pj_find_file(projCtx ctx, const char *short_filename,
- char* out_full_filename, size_t out_full_filename_size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ndef PROJ_API_H */
-#endif /* ndef PROJ_API_INCLUDED_FOR_PJ_VERSION_ONLY */
diff --git a/src/proj_constants.h b/src/proj_constants.h
index a3da2c10..ce3b2157 100644
--- a/src/proj_constants.h
+++ b/src/proj_constants.h
@@ -651,4 +651,24 @@
#define EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL 1068
#define EPSG_NAME_METHOD_HEIGHT_DEPTH_REVERSAL "Height Depth Reversal"
+/* ------------------------------------------------------------------------ */
+
+#define EPSG_NAME_METHOD_GEOCENTRIC_TOPOCENTRIC "Geocentric/topocentric conversions"
+#define EPSG_CODE_METHOD_GEOCENTRIC_TOPOCENTRIC 9836
+
+#define EPSG_NAME_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN "Geocentric X of topocentric origin"
+#define EPSG_CODE_PARAMETER_GEOCENTRIC_X_TOPOCENTRIC_ORIGIN 8837
+
+#define EPSG_NAME_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN "Geocentric Y of topocentric origin"
+#define EPSG_CODE_PARAMETER_GEOCENTRIC_Y_TOPOCENTRIC_ORIGIN 8838
+
+#define EPSG_NAME_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN "Geocentric Z of topocentric origin"
+#define EPSG_CODE_PARAMETER_GEOCENTRIC_Z_TOPOCENTRIC_ORIGIN 8839
+
+/* ------------------------------------------------------------------------ */
+
+#define EPSG_NAME_METHOD_GEOGRAPHIC_TOPOCENTRIC "Geographic/topocentric conversions"
+#define EPSG_CODE_METHOD_GEOGRAPHIC_TOPOCENTRIC 9837
+
+
#endif /* PROJ_CONSTANTS_INCLUDED */
diff --git a/src/proj_internal.h b/src/proj_internal.h
index 79b1da10..32aaa1ec 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -33,10 +33,6 @@
#error "proj_internal.h can only be included from a C++ file"
#endif
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-
#ifdef _MSC_VER
# ifndef _CRT_SECURE_NO_DEPRECATE
# define _CRT_SECURE_NO_DEPRECATE
@@ -66,10 +62,6 @@
#include "proj.h"
-#ifdef PROJ_API_H
-#error proj_internal.h must be included before proj_api.h
-#endif
-
#ifdef PROJ_RENAME_SYMBOLS
#include "proj_symbol_rename.h"
#endif
@@ -248,8 +240,6 @@ struct PJ_AREA {
double north_lat_degree;
};
-struct projCtx_t;
-typedef struct projCtx_t projCtx_t;
/*****************************************************************************
@@ -360,7 +350,7 @@ struct PJconsts {
**************************************************************************************/
- projCtx_t *ctx = nullptr;
+ PJ_CONTEXT *ctx = nullptr;
const char *descr = nullptr; /* From pj_list.h or individual PJ_*.c file */
paralist *params = nullptr; /* Parameter list */
char *def_full = nullptr; /* Full textual definition (usually 0 - set by proj_pj_info) */
@@ -401,7 +391,7 @@ struct PJconsts {
PJ_OPERATOR inv4d = nullptr;
PJ_DESTRUCTOR destructor = nullptr;
- void (*reassign_context)(PJ*, projCtx_t *) = nullptr;
+ void (*reassign_context)(PJ*, PJ_CONTEXT*) = nullptr;
/*************************************************************************************
@@ -626,7 +616,7 @@ struct FACTORS {
#define PJD_ERR_INVALID_X_OR_Y -15
#define PJD_ERR_WRONG_FORMAT_DMS_VALUE -16
#define PJD_ERR_NON_CONV_INV_MERI_DIST -17
-#define PJD_ERR_NON_CON_INV_PHI2 -18
+#define PJD_ERR_NON_CONV_SINHPSI2TANPHI -18
#define PJD_ERR_ACOS_ASIN_ARG_TOO_LARGE -19
#define PJD_ERR_TOLERANCE_CONDITION -20
#define PJD_ERR_CONIC_LAT_EQUAL -21
@@ -716,12 +706,11 @@ struct projFileApiCallbackAndData
};
/* proj thread context */
-struct projCtx_t {
+struct pj_ctx{
int last_errno = 0;
int debug_level = 0;
void (*logger)(void *, int, const char *) = nullptr;
void *logger_app_data = nullptr;
- struct projFileAPI_t *fileapi_legacy = nullptr; // for proj_api.h legacy API
struct projCppContext* cpp_context = nullptr; /* internal context for C++ code */
int use_proj4_init_rules = -1; /* -1 = unknown, 0 = no, 1 = yes */
int epsg_file_exists = -1; /* -1 = unknown, 0 = no, 1 = yes */
@@ -753,18 +742,18 @@ struct projCtx_t {
int pipelineInitRecursiongCounter = 0; // to avoid potential infinite recursion in pipeline.cpp
- projCtx_t() = default;
- projCtx_t(const projCtx_t&);
- ~projCtx_t();
+ pj_ctx() = default;
+ pj_ctx(const pj_ctx&);
+ ~pj_ctx();
- projCtx_t& operator= (const projCtx_t&) = delete;
+ pj_ctx& operator= (const pj_ctx&) = delete;
projCppContext* get_cpp_context();
void safeAutoCloseDbIfNeeded();
void set_search_paths(const std::vector<std::string>& search_paths_in);
void set_ca_bundle_path(const std::string& ca_bundle_path_in);
- static projCtx_t createDefault();
+ static pj_ctx createDefault();
};
/* Generate pj_list external or make list from include file */
@@ -812,40 +801,41 @@ PJ *pj_projection_specific_setup_##name (PJ *P)
/* procedure prototypes */
double PROJ_DLL dmstor(const char *, char **);
-double dmstor_ctx(projCtx_t *ctx, const char *, char **);
+double dmstor_ctx(PJ_CONTEXT *ctx, const char *, char **);
void PROJ_DLL set_rtodms(int, int);
char PROJ_DLL *rtodms(char *, double, int, int);
double PROJ_DLL adjlon(double);
-double aacos(projCtx_t *,double);
-double aasin(projCtx_t *,double);
+double aacos(PJ_CONTEXT *,double);
+double aasin(PJ_CONTEXT *,double);
double asqrt(double);
double aatan2(double, double);
-PROJVALUE PROJ_DLL pj_param(projCtx_t *ctx, paralist *, const char *);
+PROJVALUE PROJ_DLL pj_param(PJ_CONTEXT *ctx, paralist *, const char *);
paralist PROJ_DLL *pj_param_exists (paralist *list, const char *parameter);
paralist PROJ_DLL *pj_mkparam(const char *);
paralist *pj_mkparam_ws (const char *str, const char **next_str);
-int PROJ_DLL pj_ell_set(projCtx_t *ctx, paralist *, double *, double *);
-int pj_datum_set(projCtx_t *,paralist *, PJ *);
+int PROJ_DLL pj_ell_set(PJ_CONTEXT *ctx, paralist *, double *, double *);
+int pj_datum_set(PJ_CONTEXT *,paralist *, PJ *);
int pj_angular_units_set(paralist *, PJ *);
paralist *pj_clone_paralist( const paralist* );
paralist *pj_search_initcache( const char *filekey );
void pj_insert_initcache( const char *filekey, const paralist *list);
-paralist *pj_expand_init(projCtx_t *ctx, paralist *init);
+paralist *pj_expand_init(PJ_CONTEXT *ctx, paralist *init);
-void *pj_dealloc_params (projCtx_t *ctx, paralist *start, int errlev);
+void *free_params (PJ_CONTEXT *ctx, paralist *start, int errlev);
double *pj_enfn(double);
double pj_mlfn(double, double, double, const double *);
-double pj_inv_mlfn(projCtx_t *, double, double, const double *);
+double pj_inv_mlfn(PJ_CONTEXT *, double, double, const double *);
double pj_qsfn(double, double, double);
double pj_tsfn(double, double, double);
double pj_msfn(double, double, double);
-double PROJ_DLL pj_phi2(projCtx_t *, const double, const double);
+double PROJ_DLL pj_phi2(PJ_CONTEXT *, const double, const double);
+double pj_sinhpsi2tanphi(PJ_CONTEXT *, const double, const double);
double pj_qsfn_(double, PJ *);
double *pj_authset(double);
double pj_authlat(double, double *);
@@ -858,10 +848,10 @@ int pj_factors(PJ_LP, const PJ *, double, struct FACTORS *);
void *proj_mdist_ini(double);
double proj_mdist(double, double, double, const void *);
-double proj_inv_mdist(projCtx_t *ctx, double, const void *);
+double proj_inv_mdist(PJ_CONTEXT *ctx, double, const void *);
void *pj_gauss_ini(double, double, double *,double *);
-PJ_LP pj_gauss(projCtx_t *, PJ_LP, const void *);
-PJ_LP pj_inv_gauss(projCtx_t *, PJ_LP, const void *);
+PJ_LP pj_gauss(PJ_CONTEXT *, PJ_LP, const void *);
+PJ_LP pj_inv_gauss(PJ_CONTEXT *, PJ_LP, const void *);
struct PJ_DATUMS PROJ_DLL *pj_get_datums_ref( void );
@@ -872,7 +862,7 @@ double PROJ_DLL pj_atof( const char* nptr );
double pj_strtod( const char *nptr, char **endptr );
void pj_freeup_plain (PJ *P);
-PJ* pj_init_ctx_with_allow_init_epsg( projCtx_t *ctx, int argc, char **argv, int allow_init_epsg );
+PJ* pj_init_ctx_with_allow_init_epsg( PJ_CONTEXT *ctx, int argc, char **argv, int allow_init_epsg );
std::string PROJ_DLL pj_add_type_crs_if_needed(const std::string& str);
std::string pj_double_quote_string_param_if_needed(const std::string& str);
@@ -909,7 +899,68 @@ void pj_clear_vgridshift_knowngrids_cache();
PJ_LP pj_generic_inverse_2d(PJ_XY xy, PJ *P, PJ_LP lpInitial);
-/* classic public API */
-#include "proj_api.h"
+
+
+
+/*****************************************************************************/
+/* */
+/* proj_api.h */
+/* */
+/* The rest of this header file includes what used to be "proj_api.h" */
+/* */
+/*****************************************************************************/
+
+/* pj_init() and similar functions can be used with a non-C locale */
+/* Can be detected too at runtime if the symbol pj_atof exists */
+#define PJ_LOCALE_SAFE 1
+
+#define RAD_TO_DEG 57.295779513082321
+#define DEG_TO_RAD .017453292519943296
+
+
+
+
+extern char const PROJ_DLL pj_release[]; /* global release id string */
+
+#ifndef PROJ_INTERNAL_H
+/* replaced by enum proj_log_level in proj_internal.h */
+#define PJ_LOG_NONE 0
+#define PJ_LOG_ERROR 1
+#define PJ_LOG_DEBUG_MAJOR 2
+#define PJ_LOG_DEBUG_MINOR 3
+#endif
+
+
+/* procedure prototypes */
+
+PJ_CONTEXT PROJ_DLL *pj_get_default_ctx(void);
+PJ_CONTEXT *pj_get_ctx( PJ *);
+
+PJ_XY PROJ_DLL pj_fwd(PJ_LP, PJ *);
+PJ_LP PROJ_DLL pj_inv(PJ_XY, PJ *);
+
+PJ_XYZ pj_fwd3d(PJ_LPZ, PJ *);
+PJ_LPZ pj_inv3d(PJ_XYZ, PJ *);
+
+
+void pj_clear_initcache(void);
+void PROJ_DLL pj_pr_list(PJ *); /* used by proj.cpp */
+char *pj_get_def(PJ *, int);
+int pj_has_inverse(PJ *);
+
+
+char *pj_strdup(const char *str);
+const char PROJ_DLL *pj_get_release(void);
+void pj_acquire_lock(void);
+void pj_release_lock(void);
+void pj_cleanup_lock(void);
+
+void pj_log( PJ_CONTEXT * ctx, int level, const char *fmt, ... );
+void pj_stderr_logger( void *, int, const char * );
+
+int pj_find_file(PJ_CONTEXT * ctx, const char *short_filename,
+ char* out_full_filename, size_t out_full_filename_size);
+
+
#endif /* ndef PROJ_INTERNAL_H */
diff --git a/src/proj_mdist.cpp b/src/proj_mdist.cpp
index c515f6c5..ed07ffd1 100644
--- a/src/proj_mdist.cpp
+++ b/src/proj_mdist.cpp
@@ -107,7 +107,7 @@ proj_mdist(double phi, double sphi, double cphi, const void *data) {
return(D + sc * sum);
}
double
-proj_inv_mdist(projCtx ctx, double dist, const void *data) {
+proj_inv_mdist(PJ_CONTEXT *ctx, double dist, const void *data) {
const struct MDIST *b = (const struct MDIST *)data;
double s, t, phi, k;
int i;
@@ -124,6 +124,6 @@ proj_inv_mdist(projCtx ctx, double dist, const void *data) {
return phi;
}
/* convergence failed */
- pj_ctx_set_errno(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST);
+ proj_context_errno_set(ctx, PJD_ERR_NON_CONV_INV_MERI_DIST);
return phi;
}
diff --git a/src/projections/adams.cpp b/src/projections/adams.cpp
index 4f7d1a03..d1217ff1 100644
--- a/src/projections/adams.cpp
+++ b/src/projections/adams.cpp
@@ -205,7 +205,7 @@ static PJ_LP adams_inverse(PJ_XY xy, PJ *P)
static PJ *setup(PJ *P, projection_type mode) {
struct pj_opaque *Q = static_cast<struct pj_opaque*>(
- pj_calloc (1, sizeof (struct pj_opaque)));
+ calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
diff --git a/src/projections/aea.cpp b/src/projections/aea.cpp
index 6ffb4fd6..af0f292d 100644
--- a/src/projections/aea.cpp
+++ b/src/projections/aea.cpp
@@ -94,7 +94,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
@@ -219,7 +219,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(aea) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -232,7 +232,7 @@ PJ *PROJECTION(aea) {
PJ *PROJECTION(leac) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/aeqd.cpp b/src/projections/aeqd.cpp
index ad8c289e..d5d90b62 100644
--- a/src/projections/aeqd.cpp
+++ b/src/projections/aeqd.cpp
@@ -69,7 +69,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
@@ -274,7 +274,7 @@ static PJ_LP aeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(aeqd) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/airy.cpp b/src/projections/airy.cpp
index f7602e53..15ff60d8 100644
--- a/src/projections/airy.cpp
+++ b/src/projections/airy.cpp
@@ -120,7 +120,7 @@ static PJ_XY airy_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward
PJ *PROJECTION(airy) {
double beta;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
diff --git a/src/projections/aitoff.cpp b/src/projections/aitoff.cpp
index 7920309c..857ebb80 100644
--- a/src/projections/aitoff.cpp
+++ b/src/projections/aitoff.cpp
@@ -170,7 +170,7 @@ static PJ_LP aitoff_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
if (iter == MAXITER && round == MAXROUND)
{
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
/* fprintf(stderr, "Warning: Accuracy of 1e-12 not reached. Last increments: dlat=%e and dlon=%e\n", dp, dl); */
}
@@ -187,7 +187,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(aitoff) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -198,7 +198,7 @@ PJ *PROJECTION(aitoff) {
PJ *PROJECTION(wintri) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/bacon.cpp b/src/projections/bacon.cpp
index 3efd4dbe..7ff2a7ac 100644
--- a/src/projections/bacon.cpp
+++ b/src/projections/bacon.cpp
@@ -43,7 +43,7 @@ static PJ_XY bacon_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar
PJ *PROJECTION(bacon) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -57,7 +57,7 @@ PJ *PROJECTION(bacon) {
PJ *PROJECTION(apian) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -70,7 +70,7 @@ PJ *PROJECTION(apian) {
PJ *PROJECTION(ortel) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/bertin1953.cpp b/src/projections/bertin1953.cpp
index b864f83a..58509e16 100644
--- a/src/projections/bertin1953.cpp
+++ b/src/projections/bertin1953.cpp
@@ -75,7 +75,7 @@ static PJ_XY bertin1953_s_forward (PJ_LP lp, PJ *P) {
PJ *PROJECTION(bertin1953) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/bipc.cpp b/src/projections/bipc.cpp
index bf4ba834..743acd1c 100644
--- a/src/projections/bipc.cpp
+++ b/src/projections/bipc.cpp
@@ -168,7 +168,7 @@ static PJ_LP bipc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(bipc) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/bonne.cpp b/src/projections/bonne.cpp
index c94764cf..7817e968 100644
--- a/src/projections/bonne.cpp
+++ b/src/projections/bonne.cpp
@@ -106,14 +106,14 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(bonne) {
double c;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/calcofi.cpp b/src/projections/calcofi.cpp
index 57c12dde..d1e96de8 100644
--- a/src/projections/calcofi.cpp
+++ b/src/projections/calcofi.cpp
@@ -4,7 +4,6 @@
#include "proj.h"
#include "proj_internal.h"
-#include "proj_api.h"
PROJ_HEAD(calcofi,
"Cal Coop Ocean Fish Invest Lines/Stations") "\n\tCyl, Sph&Ell";
diff --git a/src/projections/cass.cpp b/src/projections/cass.cpp
index e253cafc..f5531f6a 100644
--- a/src/projections/cass.cpp
+++ b/src/projections/cass.cpp
@@ -95,7 +95,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
@@ -111,7 +111,7 @@ PJ *PROJECTION(cass) {
}
/* otherwise it's ellipsoidal */
- P->opaque = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ P->opaque = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==P->opaque)
return pj_default_destructor (P, ENOMEM);
P->destructor = destructor;
diff --git a/src/projections/ccon.cpp b/src/projections/ccon.cpp
index df995f21..7b3b7105 100644
--- a/src/projections/ccon.cpp
+++ b/src/projections/ccon.cpp
@@ -75,14 +75,14 @@ static PJ *destructor (PJ *P, int errlev) {
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(ccon) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/cea.cpp b/src/projections/cea.cpp
index 7e6d3212..b7874b90 100644
--- a/src/projections/cea.cpp
+++ b/src/projections/cea.cpp
@@ -66,14 +66,14 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->apa);
+ free (static_cast<struct pj_opaque*>(P->opaque)->apa);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(cea) {
double t = 0.0;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/chamb.cpp b/src/projections/chamb.cpp
index 36609e79..b315832a 100644
--- a/src/projections/chamb.cpp
+++ b/src/projections/chamb.cpp
@@ -29,7 +29,7 @@ PROJ_HEAD(chamb, "Chamberlin Trimetric") "\n\tMisc Sph, no inv"
#define TOL 1e-9
/* distance and azimuth from point 1 to point 2 */
-static VECT vect(projCtx ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) {
+static VECT vect(PJ_CONTEXT *ctx, double dphi, double c1, double s1, double c2, double s2, double dlam) {
VECT v;
double cdl, dp, dl;
@@ -49,7 +49,7 @@ static VECT vect(projCtx ctx, double dphi, double c1, double s1, double c2, doub
}
/* law of cosines */
-static double lc(projCtx ctx, double b,double c,double a) {
+static double lc(PJ_CONTEXT *ctx, double b,double c,double a) {
return aacos(ctx, .5 * (b * b + c * c - a * a) / (b * c));
}
@@ -103,7 +103,7 @@ static PJ_XY chamb_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar
PJ *PROJECTION(chamb) {
int i, j;
char line[10];
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/col_urban.cpp b/src/projections/col_urban.cpp
index 5bc8407f..de0c178f 100644
--- a/src/projections/col_urban.cpp
+++ b/src/projections/col_urban.cpp
@@ -54,7 +54,7 @@ static PJ_LP col_urban_inverse (PJ_XY xy, PJ *P) {
}
PJ *PROJECTION(col_urban) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/comill.cpp b/src/projections/comill.cpp
index 189e583e..44524990 100644
--- a/src/projections/comill.cpp
+++ b/src/projections/comill.cpp
@@ -66,7 +66,7 @@ static PJ_LP comill_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
}
}
if( i == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.phi = yc;
/* longitude */
diff --git a/src/projections/eck3.cpp b/src/projections/eck3.cpp
index 0deeb4f3..2563053f 100644
--- a/src/projections/eck3.cpp
+++ b/src/projections/eck3.cpp
@@ -52,7 +52,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(eck3) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -67,7 +67,7 @@ PJ *PROJECTION(eck3) {
PJ *PROJECTION(kav7) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -85,7 +85,7 @@ PJ *PROJECTION(kav7) {
PJ *PROJECTION(wag6) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -100,7 +100,7 @@ PJ *PROJECTION(wag6) {
PJ *PROJECTION(putp1) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/eqc.cpp b/src/projections/eqc.cpp
index 194625ef..9ebc9286 100644
--- a/src/projections/eqc.cpp
+++ b/src/projections/eqc.cpp
@@ -39,7 +39,7 @@ static PJ_LP eqc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(eqc) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/eqdc.cpp b/src/projections/eqdc.cpp
index 659488b1..28767d74 100644
--- a/src/projections/eqdc.cpp
+++ b/src/projections/eqdc.cpp
@@ -68,7 +68,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
@@ -77,7 +77,7 @@ PJ *PROJECTION(eqdc) {
double cosphi, sinphi;
int secant;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/eqearth.cpp b/src/projections/eqearth.cpp
index 832c9444..2ef2775b 100644
--- a/src/projections/eqearth.cpp
+++ b/src/projections/eqearth.cpp
@@ -110,7 +110,7 @@ static PJ_LP eqearth_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal/sphe
}
if( i == 0 ) {
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
return lp;
}
@@ -137,13 +137,13 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor */
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->apa);
+ free (static_cast<struct pj_opaque*>(P->opaque)->apa);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(eqearth) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/fouc_s.cpp b/src/projections/fouc_s.cpp
index c5989514..f7607635 100644
--- a/src/projections/fouc_s.cpp
+++ b/src/projections/fouc_s.cpp
@@ -55,7 +55,7 @@ static PJ_LP fouc_s_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
PJ *PROJECTION(fouc_s) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/geos.cpp b/src/projections/geos.cpp
index 338f07c2..5de4c7ca 100644
--- a/src/projections/geos.cpp
+++ b/src/projections/geos.cpp
@@ -199,7 +199,7 @@ static PJ_LP geos_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse
PJ *PROJECTION(geos) {
char *sweep_axis;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/gn_sinu.cpp b/src/projections/gn_sinu.cpp
index 815de8be..ef312613 100644
--- a/src/projections/gn_sinu.cpp
+++ b/src/projections/gn_sinu.cpp
@@ -102,7 +102,7 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
@@ -121,7 +121,7 @@ static void setup(PJ *P) {
PJ *PROJECTION(sinu) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -143,7 +143,7 @@ PJ *PROJECTION(sinu) {
PJ *PROJECTION(eck6) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -158,7 +158,7 @@ PJ *PROJECTION(eck6) {
PJ *PROJECTION(mbtfps) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -173,7 +173,7 @@ PJ *PROJECTION(mbtfps) {
PJ *PROJECTION(gn_sinu) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/gnom.cpp b/src/projections/gnom.cpp
index 23dee030..9abbb7ce 100644
--- a/src/projections/gnom.cpp
+++ b/src/projections/gnom.cpp
@@ -124,7 +124,7 @@ static PJ_LP gnom_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(gnom) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/goode.cpp b/src/projections/goode.cpp
index fdace387..c0afd2d8 100644
--- a/src/projections/goode.cpp
+++ b/src/projections/goode.cpp
@@ -54,15 +54,15 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor */
return nullptr;
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_free (static_cast<struct pj_opaque*>(P->opaque)->sinu);
- pj_free (static_cast<struct pj_opaque*>(P->opaque)->moll);
+ proj_destroy (static_cast<struct pj_opaque*>(P->opaque)->sinu);
+ proj_destroy (static_cast<struct pj_opaque*>(P->opaque)->moll);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(goode) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/gstmerc.cpp b/src/projections/gstmerc.cpp
index 808d9ef7..b21f6ffd 100644
--- a/src/projections/gstmerc.cpp
+++ b/src/projections/gstmerc.cpp
@@ -28,9 +28,9 @@ static PJ_XY gstmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forw
double L, Ls, sinLs1, Ls1;
L = Q->n1*lp.lam;
- Ls = Q->c + Q->n1 * log(pj_tsfn(-1.0 * lp.phi, -1.0 * sin(lp.phi), P->e));
+ Ls = Q->c + Q->n1 * log(pj_tsfn(-lp.phi, -sin(lp.phi), P->e));
sinLs1 = sin(L) / cosh(Ls);
- Ls1 = log(pj_tsfn(-1.0 * asin(sinLs1), 0.0, 0.0));
+ Ls1 = log(pj_tsfn(-asin(sinLs1), -sinLs1, 0.0));
xy.x = (Q->XS + Q->n2*Ls1) * P->ra;
xy.y = (Q->YS + Q->n2*atan(sinh(Ls) / cos(L))) * P->ra;
@@ -45,28 +45,28 @@ static PJ_LP gstmerc_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inve
L = atan(sinh((xy.x * P->a - Q->XS) / Q->n2) / cos((xy.y * P->a - Q->YS) / Q->n2));
sinC = sin((xy.y * P->a - Q->YS) / Q->n2) / cosh((xy.x * P->a - Q->XS) / Q->n2);
- LC = log(pj_tsfn(-1.0 * asin(sinC), 0.0, 0.0));
+ LC = log(pj_tsfn(-asin(sinC), -sinC, 0.0));
lp.lam = L / Q->n1;
- lp.phi = -1.0 * pj_phi2(P->ctx, exp((LC - Q->c) / Q->n1), P->e);
+ lp.phi = -pj_phi2(P->ctx, exp((LC - Q->c) / Q->n1), P->e);
return lp;
}
PJ *PROJECTION(gstmerc) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->lamc = P->lam0;
- Q->n1 = sqrt(1.0 + P->es * pow(cos(P->phi0), 4.0) / (1.0 - P->es));
+ Q->n1 = sqrt(1 + P->es * pow(cos(P->phi0), 4.0) / (1 - P->es));
Q->phic = asin(sin(P->phi0) / Q->n1);
- Q->c = log(pj_tsfn(-1.0 * Q->phic, 0.0, 0.0))
- - Q->n1 * log(pj_tsfn(-1.0 * P->phi0, -1.0 * sin(P->phi0), P->e));
- Q->n2 = P->k0 * P->a * sqrt(1.0 - P->es) / (1.0 - P->es * sin(P->phi0) * sin(P->phi0));
+ Q->c = log(pj_tsfn(-Q->phic, -sin(P->phi0) / Q->n1, 0.0))
+ - Q->n1 * log(pj_tsfn(-P->phi0, -sin(P->phi0), P->e));
+ Q->n2 = P->k0 * P->a * sqrt(1 - P->es) / (1 - P->es * sin(P->phi0) * sin(P->phi0));
Q->XS = 0;
- Q->YS = -1.0 * Q->n2 * Q->phic;
+ Q->YS = -Q->n2 * Q->phic;
P->inv = gstmerc_s_inverse;
P->fwd = gstmerc_s_forward;
diff --git a/src/projections/hammer.cpp b/src/projections/hammer.cpp
index 8d6d9408..d9bcafc7 100644
--- a/src/projections/hammer.cpp
+++ b/src/projections/hammer.cpp
@@ -57,7 +57,7 @@ static PJ_LP hammer_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
PJ *PROJECTION(hammer) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/healpix.cpp b/src/projections/healpix.cpp
index aab5c41e..c778f28f 100644
--- a/src/projections/healpix.cpp
+++ b/src/projections/healpix.cpp
@@ -524,7 +524,7 @@ static PJ_LP s_healpix_inverse(PJ_XY xy, PJ *P) { /* sphere */
PJ_LP lp;
lp.lam = HUGE_VAL;
lp.phi = HUGE_VAL;
- pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
+ proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
return healpix_spherhealpix_e_inverse(xy);
@@ -540,7 +540,7 @@ static PJ_LP e_healpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */
if (in_image(xy.x, xy.y, 0, 0, 0) == 0) {
lp.lam = HUGE_VAL;
lp.phi = HUGE_VAL;
- pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
+ proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
lp = healpix_spherhealpix_e_inverse(xy);
@@ -574,7 +574,7 @@ static PJ_LP s_rhealpix_inverse(PJ_XY xy, PJ *P) { /* sphere */
PJ_LP lp;
lp.lam = HUGE_VAL;
lp.phi = HUGE_VAL;
- pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
+ proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1);
@@ -590,7 +590,7 @@ static PJ_LP e_rhealpix_inverse(PJ_XY xy, PJ *P) { /* ellipsoid */
if (in_image(xy.x, xy.y, 1, Q->north_square, Q->south_square) == 0) {
lp.lam = HUGE_VAL;
lp.phi = HUGE_VAL;
- pj_ctx_set_errno(P->ctx, PJD_ERR_INVALID_X_OR_Y);
+ proj_context_errno_set(P->ctx, PJD_ERR_INVALID_X_OR_Y);
return lp;
}
xy = combine_caps(xy.x, xy.y, Q->north_square, Q->south_square, 1);
@@ -607,13 +607,13 @@ static PJ *destructor (PJ *P, int errlev) { /* Destructor
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->apa);
+ free (static_cast<struct pj_opaque*>(P->opaque)->apa);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(healpix) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -641,7 +641,7 @@ PJ *PROJECTION(healpix) {
PJ *PROJECTION(rhealpix) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/igh.cpp b/src/projections/igh.cpp
index 2be94889..8aaaaba1 100644
--- a/src/projections/igh.cpp
+++ b/src/projections/igh.cpp
@@ -208,7 +208,7 @@ static bool setup_zone(PJ *P, struct pj_opaque *Q, int n,
PJ *PROJECTION(igh) {
PJ_XY xy1, xy3;
PJ_LP lp = { 0, phi_boundary };
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/igh_o.cpp b/src/projections/igh_o.cpp
index b14d79a5..80874845 100644
--- a/src/projections/igh_o.cpp
+++ b/src/projections/igh_o.cpp
@@ -222,7 +222,7 @@ static bool setup_zone(PJ *P, struct pj_opaque *Q, int n,
PJ *PROJECTION(igh_o) {
PJ_XY xy1, xy4;
PJ_LP lp = { 0, phi_boundary };
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/imw_p.cpp b/src/projections/imw_p.cpp
index ee206091..6e82d287 100644
--- a/src/projections/imw_p.cpp
+++ b/src/projections/imw_p.cpp
@@ -160,7 +160,7 @@ static PJ *destructor (PJ *P, int errlev) {
return pj_default_destructor (P, errlev);
if( static_cast<struct pj_opaque*>(P->opaque)->en )
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor(P, errlev);
}
@@ -169,7 +169,7 @@ static PJ *destructor (PJ *P, int errlev) {
PJ *PROJECTION(imw_p) {
double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2;
int err;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/isea.cpp b/src/projections/isea.cpp
index dd1d48ff..77a5689b 100644
--- a/src/projections/isea.cpp
+++ b/src/projections/isea.cpp
@@ -1039,7 +1039,7 @@ static PJ_XY isea_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward
PJ *PROJECTION(isea) {
char *opt;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/krovak.cpp b/src/projections/krovak.cpp
index aef44d42..adc039fe 100644
--- a/src/projections/krovak.cpp
+++ b/src/projections/krovak.cpp
@@ -181,7 +181,7 @@ static PJ_LP krovak_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal,
fi1 = lp.phi;
}
if( i == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.lam -= P->lam0;
@@ -191,7 +191,7 @@ static PJ_LP krovak_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal,
PJ *PROJECTION(krovak) {
double u0, n0, g;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/labrd.cpp b/src/projections/labrd.cpp
index c9dfdfc6..4fbcf460 100644
--- a/src/projections/labrd.cpp
+++ b/src/projections/labrd.cpp
@@ -105,7 +105,7 @@ static PJ_LP labrd_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, invers
PJ *PROJECTION(labrd) {
double Az, sinp, R, N, t;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/laea.cpp b/src/projections/laea.cpp
index 3d135864..2d19cab1 100644
--- a/src/projections/laea.cpp
+++ b/src/projections/laea.cpp
@@ -234,7 +234,7 @@ static PJ *destructor (PJ *P, int errlev) {
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->apa);
+ free (static_cast<struct pj_opaque*>(P->opaque)->apa);
return pj_default_destructor(P, errlev);
}
@@ -242,7 +242,7 @@ static PJ *destructor (PJ *P, int errlev) {
PJ *PROJECTION(laea) {
double t;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/lagrng.cpp b/src/projections/lagrng.cpp
index d37a00e6..1029bf8d 100644
--- a/src/projections/lagrng.cpp
+++ b/src/projections/lagrng.cpp
@@ -71,7 +71,7 @@ static PJ_LP lagrng_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
PJ *PROJECTION(lagrng) {
double sin_phi1;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/lcc.cpp b/src/projections/lcc.cpp
index 91ffc511..525281f4 100644
--- a/src/projections/lcc.cpp
+++ b/src/projections/lcc.cpp
@@ -80,7 +80,7 @@ static PJ_LP lcc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse
PJ *PROJECTION(lcc) {
double cosphi, sinphi;
int secant;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc(1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc(1, sizeof (struct pj_opaque)));
if (nullptr == Q)
return pj_default_destructor(P, ENOMEM);
@@ -106,10 +106,10 @@ PJ *PROJECTION(lcc) {
double ml1, m1;
m1 = pj_msfn(sinphi, cosphi, P->es);
- ml1 = pj_tsfn(Q->phi1, sinphi, P->e);
- if( ml1 == 0 ) {
+ if( fabs(Q->phi1) == M_HALFPI ) {
return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
}
+ ml1 = pj_tsfn(Q->phi1, sinphi, P->e);
if (secant) { /* secant cone */
sinphi = sin(Q->phi2);
Q->n = log(m1 / pj_msfn(sinphi, cos(Q->phi2), P->es));
@@ -117,10 +117,10 @@ PJ *PROJECTION(lcc) {
// Not quite, but es is very close to 1...
return pj_default_destructor(P, PJD_ERR_INVALID_ECCENTRICITY);
}
- const double ml2 = pj_tsfn(Q->phi2, sinphi, P->e);
- if( ml2 == 0 ) {
- return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+ if( fabs(Q->phi2) == M_HALFPI ) {
+ return pj_default_destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
}
+ const double ml2 = pj_tsfn(Q->phi2, sinphi, P->e);
const double denom = log(ml1 / ml2);
if( denom == 0 ) {
// Not quite, but es is very close to 1...
diff --git a/src/projections/lcca.cpp b/src/projections/lcca.cpp
index 51dd28aa..53646fc6 100644
--- a/src/projections/lcca.cpp
+++ b/src/projections/lcca.cpp
@@ -128,14 +128,14 @@ static PJ *destructor (PJ *P, int errlev) {
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(lcca) {
double s2p0, N0, R0, tan0;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/loxim.cpp b/src/projections/loxim.cpp
index 2ee88037..64124bdd 100644
--- a/src/projections/loxim.cpp
+++ b/src/projections/loxim.cpp
@@ -56,7 +56,7 @@ static PJ_LP loxim_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(loxim) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/lsat.cpp b/src/projections/lsat.cpp
index f6114485..a811a3a6 100644
--- a/src/projections/lsat.cpp
+++ b/src/projections/lsat.cpp
@@ -158,7 +158,7 @@ static PJ_LP lsat_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse
PJ *PROJECTION(lsat) {
int land, path;
double lam, alf, esc, ess;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/merc.cpp b/src/projections/merc.cpp
index a77d7517..3a0ed7b4 100644
--- a/src/projections/merc.cpp
+++ b/src/projections/merc.cpp
@@ -10,45 +10,29 @@
PROJ_HEAD(merc, "Mercator") "\n\tCyl, Sph&Ell\n\tlat_ts=";
PROJ_HEAD(webmerc, "Web Mercator / Pseudo Mercator") "\n\tCyl, Ell\n\t";
-#define EPS10 1.e-10
-static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */
- if (fabs(x) <= DBL_EPSILON) {
- /* tan(M_FORTPI + .5 * x) can be approximated by 1.0 + x */
- return log1p(x);
- }
- return log(tan(M_FORTPI + .5 * x));
-}
-
static PJ_XY merc_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forward */
PJ_XY xy = {0.0,0.0};
- if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) {
- proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
- return xy;
- }
xy.x = P->k0 * lp.lam;
- xy.y = - P->k0 * log(pj_tsfn(lp.phi, sin(lp.phi), P->e));
+ // Instead of calling tan and sin, call sin and cos which the compiler
+ // optimizes to a single call to sincos.
+ double sphi = sin(lp.phi);
+ double cphi = cos(lp.phi);
+ xy.y = P->k0 * (asinh(sphi/cphi) - P->e * atanh(P->e * sphi));
return xy;
}
static PJ_XY merc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0,0.0};
- if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) {
- proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
- return xy;
-}
xy.x = P->k0 * lp.lam;
- xy.y = P->k0 * logtanpfpim1(lp.phi);
+ xy.y = P->k0 * asinh(tan(lp.phi));
return xy;
}
static PJ_LP merc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse */
PJ_LP lp = {0.0,0.0};
- if ((lp.phi = pj_phi2(P->ctx, exp(- xy.y / P->k0), P->e)) == HUGE_VAL) {
- proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
- return lp;
-}
+ lp.phi = atan(pj_sinhpsi2tanphi(P->ctx, sinh(xy.y / P->k0), P->e));
lp.lam = xy.x / P->k0;
return lp;
}
diff --git a/src/projections/misrsom.cpp b/src/projections/misrsom.cpp
index 71116e1e..d7e199f2 100644
--- a/src/projections/misrsom.cpp
+++ b/src/projections/misrsom.cpp
@@ -178,7 +178,7 @@ PJ *PROJECTION(misrsom) {
int path;
double lam, alf, esc, ess;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/mod_ster.cpp b/src/projections/mod_ster.cpp
index c7a8e899..0c30b7b6 100644
--- a/src/projections/mod_ster.cpp
+++ b/src/projections/mod_ster.cpp
@@ -134,7 +134,7 @@ PJ *PROJECTION(mil_os) {
{0.019430, 0.}
};
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -157,7 +157,7 @@ PJ *PROJECTION(lee_os) {
{-0.0088162, -0.00617325}
};
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -182,7 +182,7 @@ PJ *PROJECTION(gs48) {
{0.075528, 0.}
};
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -217,7 +217,7 @@ PJ *PROJECTION(alsk) {
{ .3660976, -.2937382}
};
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -265,7 +265,7 @@ PJ *PROJECTION(gs50) {
{-.0225161, .0853673}
};
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/moll.cpp b/src/projections/moll.cpp
index 5d4f7825..4864c8e1 100644
--- a/src/projections/moll.cpp
+++ b/src/projections/moll.cpp
@@ -77,7 +77,7 @@ static PJ * setup(PJ *P, double p) {
PJ *PROJECTION(moll) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -87,7 +87,7 @@ PJ *PROJECTION(moll) {
PJ *PROJECTION(wag4) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -96,7 +96,7 @@ PJ *PROJECTION(wag4) {
}
PJ *PROJECTION(wag5) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/natearth.cpp b/src/projections/natearth.cpp
index 5c096605..e1f71089 100644
--- a/src/projections/natearth.cpp
+++ b/src/projections/natearth.cpp
@@ -82,7 +82,7 @@ static PJ_LP natearth_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inv
}
}
if( i == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.phi = yc;
/* longitude */
diff --git a/src/projections/natearth2.cpp b/src/projections/natearth2.cpp
index d149ca85..e4516a0a 100644
--- a/src/projections/natearth2.cpp
+++ b/src/projections/natearth2.cpp
@@ -76,7 +76,7 @@ static PJ_LP natearth2_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, in
}
}
if( i == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.phi = yc;
/* longitude */
diff --git a/src/projections/nsper.cpp b/src/projections/nsper.cpp
index 903946b9..951111ac 100644
--- a/src/projections/nsper.cpp
+++ b/src/projections/nsper.cpp
@@ -180,7 +180,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(nsper) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -194,7 +194,7 @@ PJ *PROJECTION(nsper) {
PJ *PROJECTION(tpers) {
double omega, gamma;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/ob_tran.cpp b/src/projections/ob_tran.cpp
index 7cf1cf98..86798e0a 100644
--- a/src/projections/ob_tran.cpp
+++ b/src/projections/ob_tran.cpp
@@ -141,14 +141,15 @@ static ARGS ob_tran_target_params (paralist *params) {
if (argc < 2)
return args;
- /* all args except the proj_ob_tran */
- args.argv = static_cast<char**>(pj_calloc (argc - 1, sizeof (char *)));
+ /* all args except the proj=ob_tran */
+ args.argv = static_cast<char**>(calloc (argc - 1, sizeof (char *)));
if (nullptr==args.argv)
return args;
- /* Copy all args *except* the proj=ob_tran arg to the argv array */
+ /* Copy all args *except* the proj=ob_tran or inv arg to the argv array */
for (i = 0; params != nullptr; params = params->next) {
- if (0==strcmp (params->param, "proj=ob_tran"))
+ if (0==strcmp (params->param, "proj=ob_tran") ||
+ 0==strcmp (params->param, "inv") )
continue;
args.argv[i++] = params->param;
}
@@ -160,7 +161,7 @@ static ARGS ob_tran_target_params (paralist *params) {
continue;
args.argv[i] += 2;
if (strcmp(args.argv[i], "proj=ob_tran") == 0 ) {
- pj_dealloc (args.argv);
+ free (args.argv);
args.argc = 0;
args.argv = nullptr;
}
@@ -177,7 +178,7 @@ PJ *PROJECTION(ob_tran) {
ARGS args;
PJ *R; /* projection to rotate */
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return destructor(P, ENOMEM);
@@ -194,8 +195,8 @@ PJ *PROJECTION(ob_tran) {
if (args.argv == nullptr ) {
return destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
}
- R = pj_init_ctx (pj_get_ctx(P), args.argc, args.argv);
- pj_dealloc (args.argv);
+ R = proj_create_argv (P->ctx, args.argc, args.argv);
+ free (args.argv);
if (nullptr==R)
return destructor (P, PJD_ERR_UNKNOWN_PROJECTION_ID);
diff --git a/src/projections/ocea.cpp b/src/projections/ocea.cpp
index de9838cb..c78e1ebc 100644
--- a/src/projections/ocea.cpp
+++ b/src/projections/ocea.cpp
@@ -52,7 +52,7 @@ static PJ_LP ocea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(ocea) {
double phi_1, phi_2, lam_1, lam_2, lonz, alpha;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/oea.cpp b/src/projections/oea.cpp
index 61fb0647..46c00d16 100644
--- a/src/projections/oea.cpp
+++ b/src/projections/oea.cpp
@@ -58,7 +58,7 @@ static PJ_LP oea_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(oea) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/omerc.cpp b/src/projections/omerc.cpp
index e9f3b833..90067cc3 100644
--- a/src/projections/omerc.cpp
+++ b/src/projections/omerc.cpp
@@ -126,7 +126,7 @@ PJ *PROJECTION(omerc) {
gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0;
int alp, gam, no_off = 0;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/ortho.cpp b/src/projections/ortho.cpp
index 8dcfb53c..4417dac7 100644
--- a/src/projections/ortho.cpp
+++ b/src/projections/ortho.cpp
@@ -273,13 +273,13 @@ static PJ_LP ortho_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inver
return lp;
}
}
- pj_ctx_set_errno(P->ctx, PJD_ERR_NON_CONVERGENT);
+ proj_context_errno_set(P->ctx, PJD_ERR_NON_CONVERGENT);
return lp;
}
PJ *PROJECTION(ortho) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/patterson.cpp b/src/projections/patterson.cpp
index 71099cdb..32544580 100644
--- a/src/projections/patterson.cpp
+++ b/src/projections/patterson.cpp
@@ -100,7 +100,7 @@ static PJ_LP patterson_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, in
}
}
if( i == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.phi = yc;
/* longitude */
diff --git a/src/projections/poly.cpp b/src/projections/poly.cpp
index 10d93ed2..4ea95cc7 100644
--- a/src/projections/poly.cpp
+++ b/src/projections/poly.cpp
@@ -147,14 +147,14 @@ static PJ *destructor(PJ *P, int errlev) {
return pj_default_destructor (P, errlev);
if (static_cast<struct pj_opaque*>(P->opaque)->en)
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor(P, errlev);
}
PJ *PROJECTION(poly) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
diff --git a/src/projections/putp3.cpp b/src/projections/putp3.cpp
index c2df20e8..09763851 100644
--- a/src/projections/putp3.cpp
+++ b/src/projections/putp3.cpp
@@ -38,7 +38,7 @@ static PJ_LP putp3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(putp3) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -53,7 +53,7 @@ PJ *PROJECTION(putp3) {
}
PJ *PROJECTION(putp3p) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/putp4p.cpp b/src/projections/putp4p.cpp
index 365f7c1b..8df18972 100644
--- a/src/projections/putp4p.cpp
+++ b/src/projections/putp4p.cpp
@@ -45,7 +45,7 @@ static PJ_LP putp4p_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inver
PJ *PROJECTION(putp4p) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -62,7 +62,7 @@ PJ *PROJECTION(putp4p) {
PJ *PROJECTION(weren) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/putp5.cpp b/src/projections/putp5.cpp
index 1847e7a9..5e70382d 100644
--- a/src/projections/putp5.cpp
+++ b/src/projections/putp5.cpp
@@ -43,7 +43,7 @@ static PJ_LP putp5_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(putp5) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -60,7 +60,7 @@ PJ *PROJECTION(putp5) {
PJ *PROJECTION(putp5p) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/putp6.cpp b/src/projections/putp6.cpp
index db334ff9..da8c0a7c 100644
--- a/src/projections/putp6.cpp
+++ b/src/projections/putp6.cpp
@@ -59,7 +59,7 @@ static PJ_LP putp6_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(putp6) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -79,7 +79,7 @@ PJ *PROJECTION(putp6) {
PJ *PROJECTION(putp6p) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/qsc.cpp b/src/projections/qsc.cpp
index 98e3755e..dd9ce965 100644
--- a/src/projections/qsc.cpp
+++ b/src/projections/qsc.cpp
@@ -377,7 +377,7 @@ static PJ_LP qsc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inverse
PJ *PROJECTION(qsc) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/robin.cpp b/src/projections/robin.cpp
index 8b646502..6a1405b6 100644
--- a/src/projections/robin.cpp
+++ b/src/projections/robin.cpp
@@ -138,7 +138,7 @@ static PJ_LP robin_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
break;
}
if( iters == 0 )
- pj_ctx_set_errno( P->ctx, PJD_ERR_NON_CONVERGENT );
+ proj_context_errno_set( P->ctx, PJD_ERR_NON_CONVERGENT );
lp.phi = (5 * i + t) * DEG_TO_RAD;
if (xy.y < 0.) lp.phi = -lp.phi;
lp.lam /= V(X[i], t);
diff --git a/src/projections/rouss.cpp b/src/projections/rouss.cpp
index f5a8f12f..2eb13b3d 100644
--- a/src/projections/rouss.cpp
+++ b/src/projections/rouss.cpp
@@ -93,7 +93,7 @@ static PJ *destructor (PJ *P, int errlev) {
return pj_default_destructor (P, errlev);
if (static_cast<struct pj_opaque*>(P->opaque)->en)
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, ENOMEM);
}
@@ -102,7 +102,7 @@ static PJ *destructor (PJ *P, int errlev) {
PJ *PROJECTION(rouss) {
double N0, es2, t, t2, R_R0_2, R_R0_4;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/rpoly.cpp b/src/projections/rpoly.cpp
index b065861f..e3f09c59 100644
--- a/src/projections/rpoly.cpp
+++ b/src/projections/rpoly.cpp
@@ -44,7 +44,7 @@ static PJ_XY rpoly_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwar
PJ *PROJECTION(rpoly) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/sch.cpp b/src/projections/sch.cpp
index 7548039d..359e8efc 100644
--- a/src/projections/sch.cpp
+++ b/src/projections/sch.cpp
@@ -184,7 +184,7 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(sch) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/sconics.cpp b/src/projections/sconics.cpp
index f305e291..c12b05a2 100644
--- a/src/projections/sconics.cpp
+++ b/src/projections/sconics.cpp
@@ -117,7 +117,7 @@ static PJ_LP sconics_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, (and ellipsoi
static PJ *setup(PJ *P, enum Type type) {
double del, cs;
int err;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/somerc.cpp b/src/projections/somerc.cpp
index fe6477fa..a184500c 100644
--- a/src/projections/somerc.cpp
+++ b/src/projections/somerc.cpp
@@ -71,7 +71,7 @@ static PJ_LP somerc_e_inverse (PJ_XY xy, PJ *P) { /* Ellipsoidal, inver
PJ *PROJECTION(somerc) {
double cp, phip0, sp;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/stere.cpp b/src/projections/stere.cpp
index abc4aa13..ad1caae2 100644
--- a/src/projections/stere.cpp
+++ b/src/projections/stere.cpp
@@ -86,7 +86,10 @@ static PJ_XY stere_e_forward (PJ_LP lp, PJ *P) { /* Ellipsoidal, forwar
sinphi = -sinphi;
/*-fallthrough*/
case N_POLE:
- xy.x = Q->akm1 * pj_tsfn (lp.phi, sinphi, P->e);
+ if( fabs(lp.phi - M_HALFPI) < 1e-15 )
+ xy.x = 0;
+ else
+ xy.x = Q->akm1 * pj_tsfn (lp.phi, sinphi, P->e);
xy.y = - xy.x * coslam;
break;
}
@@ -299,7 +302,7 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(stere) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -312,7 +315,7 @@ PJ *PROJECTION(stere) {
PJ *PROJECTION(ups) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/sterea.cpp b/src/projections/sterea.cpp
index 55404c86..4dd22d2f 100644
--- a/src/projections/sterea.cpp
+++ b/src/projections/sterea.cpp
@@ -93,14 +93,14 @@ static PJ *destructor (PJ *P, int errlev) {
if (nullptr==P->opaque)
return pj_default_destructor (P, errlev);
- pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->en);
+ free (static_cast<struct pj_opaque*>(P->opaque)->en);
return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(sterea) {
double R;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
diff --git a/src/projections/sts.cpp b/src/projections/sts.cpp
index cbc36b7d..75190e85 100644
--- a/src/projections/sts.cpp
+++ b/src/projections/sts.cpp
@@ -70,7 +70,7 @@ static PJ *setup(PJ *P, double p, double q, int mode) {
PJ *PROJECTION(fouc) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -80,7 +80,7 @@ PJ *PROJECTION(fouc) {
PJ *PROJECTION(kav5) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -91,7 +91,7 @@ PJ *PROJECTION(kav5) {
PJ *PROJECTION(qua_aut) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -101,7 +101,7 @@ PJ *PROJECTION(qua_aut) {
PJ *PROJECTION(mbt_s) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/tmerc.cpp b/src/projections/tmerc.cpp
index 69f4d352..8f897061 100644
--- a/src/projections/tmerc.cpp
+++ b/src/projections/tmerc.cpp
@@ -89,7 +89,7 @@ static PJ_XY approx_e_fwd (PJ_LP lp, PJ *P)
if( lp.lam < -M_HALFPI || lp.lam > M_HALFPI ) {
xy.x = HUGE_VAL;
xy.y = HUGE_VAL;
- pj_ctx_set_errno( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT );
+ proj_context_errno_set( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT );
return xy;
}
@@ -115,25 +115,11 @@ static PJ_XY approx_e_fwd (PJ_LP lp, PJ *P)
return (xy);
}
-static PJ_XY approx_s_fwd (PJ_LP lp, PJ *P) {
+static PJ_XY tmerc_spherical_fwd (PJ_LP lp, PJ *P) {
PJ_XY xy = {0.0,0.0};
double b, cosphi;
const auto *Q = &(static_cast<struct tmerc_data*>(P->opaque)->approx);
- /*
- * Fail if our longitude is more than 90 degrees from the
- * central meridian since the results are essentially garbage.
- * Is error -20 really an appropriate return value?
- *
- * http://trac.osgeo.org/proj/ticket/5
- */
- if( lp.lam < -M_HALFPI || lp.lam > M_HALFPI ) {
- xy.x = HUGE_VAL;
- xy.y = HUGE_VAL;
- pj_ctx_set_errno( P->ctx, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT );
- return xy;
- }
-
cosphi = cos(lp.phi);
b = cosphi * sin (lp.lam);
if (fabs (fabs (b) - 1.) <= EPS10) {
@@ -145,7 +131,12 @@ static PJ_XY approx_s_fwd (PJ_LP lp, PJ *P) {
xy.y = cosphi * cos (lp.lam) / sqrt (1. - b * b);
b = fabs ( xy.y );
- if (b >= 1.) {
+ if (cosphi == 1 && (lp.lam < -M_HALFPI || lp.lam > M_HALFPI) ) {
+ /* Helps to be able to roundtrip |longitudes| > 90 at lat=0 */
+ /* We could also map to -M_PI ... */
+ xy.y = M_PI;
+ }
+ else if (b >= 1.) {
if ((b - 1.) > EPS10) {
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
return xy;
@@ -192,7 +183,7 @@ static PJ_LP approx_e_inv (PJ_XY xy, PJ *P) {
return lp;
}
-static PJ_LP approx_s_inv (PJ_XY xy, PJ *P) {
+static PJ_LP tmerc_spherical_inv (PJ_XY xy, PJ *P) {
PJ_LP lp = {0.0, 0.0};
double h, g;
const auto *Q = &(static_cast<struct tmerc_data*>(P->opaque)->approx);
@@ -203,11 +194,13 @@ static PJ_LP approx_s_inv (PJ_XY xy, PJ *P) {
return proj_coord_error().lp;
}
g = .5 * (h - 1. / h);
- h = cos (P->phi0 + xy.y / Q->esp);
+ /* D, as in equation 8-8 of USGS "Map Projections - A Working Manual" */
+ const double D = P->phi0 + xy.y / Q->esp;
+ h = cos (D);
lp.phi = asin(sqrt((1. - h * h) / (1. + g * g)));
/* Make sure that phi is on the correct hemisphere when false northing is used */
- if (xy.y < 0. && -lp.phi+P->phi0 < 0.0) lp.phi = -lp.phi;
+ lp.phi = copysign(lp.phi, D);
lp.lam = (g != 0.0 || h != 0.0) ? atan2 (g, h) : 0.;
return lp;
@@ -221,7 +214,7 @@ static PJ *destructor(PJ *P, int errlev) {
if (nullptr==P->opaque)
return pj_default_destructor(P, errlev);
- pj_dealloc (static_cast<struct tmerc_data*>(P->opaque)->approx.en);
+ free (static_cast<struct tmerc_data*>(P->opaque)->approx.en);
return pj_default_destructor(P, errlev);
}
@@ -592,7 +585,7 @@ static PJ_LP auto_e_inv (PJ_XY xy, PJ *P) {
static PJ *setup(PJ *P, TMercAlgo eAlg) {
- struct tmerc_data *Q = static_cast<struct tmerc_data*>(pj_calloc (1, sizeof (struct tmerc_data)));
+ struct tmerc_data *Q = static_cast<struct tmerc_data*>(calloc (1, sizeof (struct tmerc_data)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -609,8 +602,8 @@ static PJ *setup(PJ *P, TMercAlgo eAlg) {
return nullptr;
if( P->es == 0 )
{
- P->inv = approx_s_inv;
- P->fwd = approx_s_fwd;
+ P->inv = tmerc_spherical_inv;
+ P->fwd = tmerc_spherical_fwd;
}
else
{
@@ -679,7 +672,7 @@ static bool getAlgoFromParams(PJ* P, TMercAlgo& algo)
else
{
pj_load_ini(P->ctx); // if not already done
- pj_ctx_set_errno(P->ctx, 0); // reset error in case proj.ini couldn't be found
+ proj_context_errno_set(P->ctx, 0); // reset error in case proj.ini couldn't be found
algo = P->ctx->defaultTmercAlgo;
}
diff --git a/src/projections/tobmerc.cpp b/src/projections/tobmerc.cpp
index a1616036..f05a9b6b 100644
--- a/src/projections/tobmerc.cpp
+++ b/src/projections/tobmerc.cpp
@@ -9,27 +9,24 @@
PROJ_HEAD(tobmerc, "Tobler-Mercator") "\n\tCyl, Sph";
-#define EPS10 1.e-10
-static double logtanpfpim1(double x) { /* log(tan(x/2 + M_FORTPI)) */
- if (fabs(x) <= DBL_EPSILON) {
- /* tan(M_FORTPI + .5 * x) can be approximated by 1.0 + x */
- return log1p(x);
- }
- return log(tan(M_FORTPI + .5 * x));
-}
-
static PJ_XY tobmerc_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward */
PJ_XY xy = {0.0, 0.0};
double cosphi;
- if (fabs(fabs(lp.phi) - M_HALFPI) <= EPS10) {
+ if (fabs(lp.phi) >= M_HALFPI) {
+ // builtins.gie tests "Test expected failure at the poles:". However
+ // given that M_HALFPI is strictly less than pi/2 in double precision,
+ // it's not clear why shouldn't just return a large result for xy.y (and
+ // it's not even that large, merely 38.025...). Even if the logic was
+ // such that phi was strictly equal to pi/2, allowing xy.y = inf would be
+ // a reasonable result.
proj_errno_set(P, PJD_ERR_TOLERANCE_CONDITION);
return xy;
}
cosphi = cos(lp.phi);
xy.x = P->k0 * lp.lam * cosphi * cosphi;
- xy.y = P->k0 * logtanpfpim1(lp.phi);
+ xy.y = P->k0 * asinh(tan(lp.phi));
return xy;
}
diff --git a/src/projections/tpeqd.cpp b/src/projections/tpeqd.cpp
index 58aeb8e1..90efb395 100644
--- a/src/projections/tpeqd.cpp
+++ b/src/projections/tpeqd.cpp
@@ -64,7 +64,7 @@ static PJ_LP tpeqd_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(tpeqd) {
double lam_1, lam_2, phi_1, phi_2, A12;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/urm5.cpp b/src/projections/urm5.cpp
index 499644d2..c3021841 100644
--- a/src/projections/urm5.cpp
+++ b/src/projections/urm5.cpp
@@ -30,7 +30,7 @@ static PJ_XY urm5_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forward
PJ *PROJECTION(urm5) {
double alpha, t;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/urmfps.cpp b/src/projections/urmfps.cpp
index 3f9fdf23..5d689f9f 100644
--- a/src/projections/urmfps.cpp
+++ b/src/projections/urmfps.cpp
@@ -47,7 +47,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(urmfps) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
@@ -66,7 +66,7 @@ PJ *PROJECTION(urmfps) {
PJ *PROJECTION(wag1) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/vandg2.cpp b/src/projections/vandg2.cpp
index 223620d6..cd7e7b6c 100644
--- a/src/projections/vandg2.cpp
+++ b/src/projections/vandg2.cpp
@@ -53,7 +53,7 @@ static PJ_XY vandg2_s_forward (PJ_LP lp, PJ *P) { /* Spheroidal, forwa
PJ *PROJECTION(vandg2) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -65,7 +65,7 @@ PJ *PROJECTION(vandg2) {
}
PJ *PROJECTION(vandg3) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/wag3.cpp b/src/projections/wag3.cpp
index 33313cdb..ed3250ef 100644
--- a/src/projections/wag3.cpp
+++ b/src/projections/wag3.cpp
@@ -35,7 +35,7 @@ static PJ_LP wag3_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, inverse
PJ *PROJECTION(wag3) {
double ts;
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
diff --git a/src/projections/wink1.cpp b/src/projections/wink1.cpp
index d097978f..f4ffafe3 100644
--- a/src/projections/wink1.cpp
+++ b/src/projections/wink1.cpp
@@ -33,7 +33,7 @@ static PJ_LP wink1_s_inverse (PJ_XY xy, PJ *P) { /* Spheroidal, invers
PJ *PROJECTION(wink1) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/projections/wink2.cpp b/src/projections/wink2.cpp
index d457f842..b5b1e812 100644
--- a/src/projections/wink2.cpp
+++ b/src/projections/wink2.cpp
@@ -53,7 +53,7 @@ static PJ_LP wink2_s_inverse(PJ_XY xy, PJ *P)
PJ *PROJECTION(wink2) {
- struct pj_opaque *Q = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof (struct pj_opaque)));
+ struct pj_opaque *Q = static_cast<struct pj_opaque*>(calloc (1, sizeof (struct pj_opaque)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
diff --git a/src/strerrno.cpp b/src/strerrno.cpp
index 5ae0d7e1..3d0131c6 100644
--- a/src/strerrno.cpp
+++ b/src/strerrno.cpp
@@ -1,4 +1,4 @@
-/* list of projection system pj_errno values */
+/* list of projection system errno values */
#include <stddef.h>
#include <stdio.h>
@@ -27,7 +27,7 @@ pj_err_list[] = {
"invalid x or y", /* -15 */
"improperly formed DMS value", /* -16 */
"non-convergent inverse meridional dist", /* -17 */
- "non-convergent inverse phi2", /* -18 */
+ "non-convergent sinh(psi) to tan(phi)", /* -18 */
"acos/asin: |arg| >1.+1e-14", /* -19 */
"tolerance condition error", /* -20 */
"conic lat_1 = -lat_2", /* -21 */
@@ -74,10 +74,11 @@ pj_err_list[] = {
"network error", /* -62 */
/* When adding error messages, remember to update ID defines in
- projects.h, and transient_error array in pj_transform */
+ src/proj_internal.h and src/apps/gie.cpp */
};
-char *pj_strerrno(int err) {
+
+const char* proj_errno_string(int err) {
const int max_error = 9999;
static char note[50];
size_t adjusted_err;
@@ -98,7 +99,7 @@ char *pj_strerrno(int err) {
#endif
}
- /* PROJ.4 error codes are negative: -1 to -9999 */
+ /* PROJ error codes are negative: -1 to -9999 */
adjusted_err = err < -max_error ? max_error : -err - 1;
if (adjusted_err < (sizeof(pj_err_list) / sizeof(char *)))
return (char *)pj_err_list[adjusted_err];
@@ -107,7 +108,3 @@ char *pj_strerrno(int err) {
(err > -max_error) ? err: -max_error);
return note;
}
-
-const char* proj_errno_string(int err) {
- return pj_strerrno(err);
-}
diff --git a/src/tests/multistresstest.cpp b/src/tests/multistresstest.cpp
index 33d2d738..6b7099ce 100644
--- a/src/tests/multistresstest.cpp
+++ b/src/tests/multistresstest.cpp
@@ -30,11 +30,7 @@
#include <stdlib.h>
#include <string.h>
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-
-#include "proj_api.h"
+#include "proj.h"
#ifdef _WIN32
#include <windows.h>
@@ -51,8 +47,8 @@ typedef struct {
const char *src_def;
const char *dst_def;
- double src_x, src_y, src_z;
- double dst_x, dst_y, dst_z;
+ PJ_COORD src;
+ PJ_COORD dst;
int dst_error;
int skip;
@@ -62,125 +58,120 @@ static TestItem test_list[] = {
{
"+proj=utm +zone=11 +datum=WGS84",
"+proj=latlong +datum=WGS84",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=utm +zone=11 +datum=NAD83",
"+proj=latlong +datum=NAD27",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=utm +zone=11 +datum=NAD83",
"+proj=latlong +nadgrids=@null +ellps=WGS84",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=utm +zone=11 +datum=WGS84",
"+proj=merc +datum=potsdam",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=latlong +nadgrids=nzgd2kgrid0005.gsb",
"+proj=latlong +datum=WGS84",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=latlong +nadgrids=nzgd2kgrid0005.gsb",
"+proj=latlong +datum=WGS84",
- 170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(170, -40, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=latlong +ellps=GRS80 +towgs84=2,3,5",
"+proj=latlong +ellps=intl +towgs84=10,12,15",
- 170 * DEG_TO_RAD, -40 * DEG_TO_RAD, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(170, -40, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=eqc +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
"+proj=stere +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=cea +lat_ts=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=merc +lon_0=12 +k=0.999 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=bonne +lat_1=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=cass +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=nzmg +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=gnom +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=ortho +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=laea +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=aeqd +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=eqdc +lat_1=20 +lat_2=5 +lat_0=11 +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+proj=mill +lat_0=11 +lon_0=12 +y_0=200000 +datum=WGS84 ",
"+proj=moll +lon_0=12 +x_0=100000 +y_0=200000 +datum=WGS84 ",
- 150000.0, 250000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 250000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
"+init=epsg:3309",
"+init=epsg:4326",
- 150000.0, 30000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 30000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
},
{
/* Bad projection (invalid ellipsoid parameter +R_A=0) */
"+proj=utm +zone=11 +datum=WGS84",
"+proj=merc +datum=potsdam +R_A=0",
- 150000.0, 3000000.0, 0.0,
- 0.0, 0.0, 0.0,
+ proj_coord(150000.0, 3000000.0, 0.0, 0.0),
+ proj_coord(0.0, 0.0, 0.0, 0.0),
0, 0
}
};
static volatile int active_thread_count = 0;
-static projPJ custom_pj_init_plus_ctx(projCtx ctx, const char* def)
-{
- return pj_init_plus_ctx(ctx, def);
-}
-
/************************************************************************/
/* TestThread() */
/************************************************************************/
@@ -195,11 +186,10 @@ static void TestThread()
/* -------------------------------------------------------------------- */
/* Initialize coordinate system definitions. */
/* -------------------------------------------------------------------- */
- projPJ *src_pj_list, *dst_pj_list;
- projCtx ctx = pj_ctx_alloc();
+ PJ **pj_list;
+ PJ_CONTEXT *ctx = proj_context_create();
- src_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ));
- dst_pj_list = (projPJ *) calloc(test_count,sizeof(projPJ));
+ pj_list = (PJ **) calloc(test_count,sizeof(PJ*));
if(!reinit_every_iteration)
{
@@ -207,8 +197,9 @@ static void TestThread()
{
TestItem *test = test_list + i;
- src_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->src_def );
- dst_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->dst_def );
+ pj_list[i] = proj_create_crs_to_crs(
+ ctx, test->src_def, test->dst_def, nullptr
+ );
}
}
@@ -221,28 +212,23 @@ static void TestThread()
for( i = 0; i < test_count; i++ )
{
TestItem *test = test_list + i;
- double x, y, z;
- int error;
-
- x = test->src_x;
- y = test->src_y;
- z = test->src_z;
if( reinit_every_iteration )
{
- src_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->src_def );
- dst_pj_list[i] = custom_pj_init_plus_ctx( ctx, test->dst_def );
+ proj_context_use_proj4_init_rules(nullptr, true);
+ pj_list[i] = proj_create_crs_to_crs(
+ ctx, test->src_def, test->dst_def, nullptr
+ );
{
- int skipTest = (src_pj_list[i] == nullptr || dst_pj_list[i] == nullptr);
+ int skipTest = (pj_list[i] == nullptr);
if ( skipTest != test->skip )
fprintf( stderr, "Threaded projection initialization does not match unthreaded initialization\n" );
if (skipTest)
{
- pj_free( src_pj_list[i] );
- pj_free( dst_pj_list[i] );
+ proj_destroy( pj_list[i] );
continue;
}
}
@@ -251,31 +237,32 @@ static void TestThread()
if ( test->skip )
continue;
- error = pj_transform( src_pj_list[i], dst_pj_list[i], 1, 0,
- &x, &y, &z );
+ PJ_COORD out = proj_trans(pj_list[i], PJ_FWD, test->src);
+ int error = proj_errno(pj_list[i]);
if( error != test->dst_error )
{
fprintf( stderr, "Got error %d, expected %d\n",
error, test->dst_error );
}
+ proj_errno_reset(pj_list[i]);
- if( x != test->dst_x || y != test->dst_y || z != test->dst_z )
+ if ( out.xyz.x != test->dst.xyz.x || out.xyz.y != test->dst.xyz.y || out.xyz.z != test->dst.xyz.z)
+ //if( x != test->dst_x || y != test->dst_y || z != test->dst_z )
{
fprintf( stderr,
"Got %.15g,%.15g,%.15g\n"
"Expected %.15g,%.15g,%.15g\n"
"Diff %.15g,%.15g,%.15g\n",
- x, y, z,
- test->dst_x, test->dst_y, test->dst_z,
- x-test->dst_x, y-test->dst_y, z-test->dst_z);
+ out.xyz.x, out.xyz.y, out.xyz.z,
+ test->dst.xyz.x, test->dst.xyz.y, test->dst.xyz.z,
+ out.xyz.x-test->dst.xyz.x, out.xyz.y-test->dst.xyz.y, out.xyz.z-test->dst.xyz.z);
}
if( reinit_every_iteration )
{
- pj_free( src_pj_list[i] );
- pj_free( dst_pj_list[i] );
+ proj_destroy( pj_list[i] );
}
}
}
@@ -287,15 +274,13 @@ static void TestThread()
{
for( i = 0; i < test_count; i++ )
{
- pj_free( src_pj_list[i] );
- pj_free( dst_pj_list[i] );
+ proj_destroy( pj_list[i] );
}
}
- free( src_pj_list );
- free( dst_pj_list );
+ free( pj_list );
- pj_ctx_free( ctx );
+ proj_context_destroy( ctx );
printf( "%d iterations of the %d tests complete in thread X\n",
repeat_count, test_count );
@@ -349,43 +334,32 @@ static int do_main(void)
{
TestItem *test = test_list + i;
- projPJ src_pj, dst_pj;
+ PJ *pj;
- src_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->src_def );
- dst_pj = custom_pj_init_plus_ctx( pj_get_default_ctx(), test->dst_def );
-
- if( src_pj == nullptr )
- {
- printf( "Unable to translate:\n%s\n", test->src_def );
- test->skip = 1;
- pj_free (dst_pj);
- continue;
- }
+ proj_context_use_proj4_init_rules(nullptr, true);
+ pj = proj_create_crs_to_crs(
+ nullptr, test->src_def, test->dst_def, nullptr
+ );
- if( dst_pj == nullptr )
+ if( pj == nullptr )
{
- printf( "Unable to translate:\n%s\n", test->dst_def );
+ printf( "Unable to translate:\n%s\n or\n%s\n", test->src_def, test->dst_def );
test->skip = 1;
- pj_free (src_pj);
+ proj_destroy(pj);
continue;
}
- test->dst_x = test->src_x;
- test->dst_y = test->src_y;
- test->dst_z = test->src_z;
- test->dst_error = pj_transform( src_pj, dst_pj, 1, 0,
- &(test->dst_x),
- &(test->dst_y),
- &(test->dst_z) );
+ PJ_COORD out = proj_trans(pj, PJ_FWD, test->src);
+ test->dst = out;
+ test->dst_error = proj_errno(pj);
- pj_free( src_pj );
- pj_free( dst_pj );
+ proj_destroy(pj);
test->skip = 0;
-#ifdef notdef
- printf( "Test %d - output %.14g,%.14g,%g\n", i, test->dst_x, test->dst_y, test->dst_z );
+#ifdef nodef
+ printf( "Test %d - output %.14g,%.14g,%g\n", i, test->dst.xyz.x, test->dst.xyz.y, test->dst.xyz.z );
#endif
}
diff --git a/src/tests/test228.cpp b/src/tests/test228.cpp
deleted file mode 100644
index 8ae17c87..00000000
--- a/src/tests/test228.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-/******************************************************************************
- *
- * Project: PROJ
- * Purpose: Test
- * Author: Even Rouault <even dot rouault at spatialys dot com>
- *
- ******************************************************************************
- * Copyright (c) 2014, 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.
- ****************************************************************************/
-
-#ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#endif
-
-#include "proj_api.h"
-#include <stdio.h> /* for printf declaration */
-
-
-#ifdef _WIN32
-
-int main(int argc, char* argv[])
-{
- printf("Test not yet ported on Win32\n");
- return 0;
-}
-
-#else
-
-#include <pthread.h>
-#include <stdio.h>
-#include <assert.h>
-#include <unistd.h>
-
-static volatile int run = 0;
-static volatile int started = 0;
-
-static void* thread_main(void* unused)
-{
- projCtx p_proj_ctxt;
- projPJ p_WGS84_proj;
- projPJ p_OSGB36_proj;
- (void)unused;
-
- __sync_add_and_fetch(&started, 1);
- while(run == 0);
-
- p_proj_ctxt=pj_ctx_alloc();
- p_WGS84_proj=pj_init_plus_ctx(p_proj_ctxt,"+proj=longlat "
- "+ellps=WGS84 +datum=WGS84");
- p_OSGB36_proj=pj_init_plus_ctx(p_proj_ctxt,
- "+proj=longlat +ellps=airy +datum=OSGB36 +nadgrids=OSTN15_NTv2_OSGBtoETRS.gsb");
-
- while(run)
- {
- double x, y;
- int proj_ret;
-
- x = -5.2*DEG_TO_RAD;
- y = 50*DEG_TO_RAD;
- proj_ret = pj_transform(p_WGS84_proj,
- p_OSGB36_proj, 1, 1, &x, &y, nullptr );
- x *= RAD_TO_DEG;
- y *= RAD_TO_DEG;
- /*printf("%.18f %.18f\n", x, y); */
- assert(proj_ret == 0);
- assert(fabs(x - -5.198965207267856492) < 1e-15);
- assert(fabs(y - 49.999396074140378232) < 1e-15);
- }
-
- pj_free (p_OSGB36_proj);
- pj_free (p_WGS84_proj);
- return nullptr;
-}
-
-int main()
-{
- int i;
-
- pthread_t tid1, tid2;
- pthread_attr_t attr1, attr2;
-
- pthread_attr_init(&attr1);
- pthread_attr_init(&attr2);
-
- pthread_create(&tid1, &attr1, thread_main, nullptr);
- pthread_create(&tid2, &attr2, thread_main, nullptr);
- while(started != 2);
- run = 1;
- for(i=0;i<2;i++)
- sleep(1);
- run = 0;
- return 0;
-}
-
-#endif /* _WIN32 */
diff --git a/src/transform.cpp b/src/transform.cpp
deleted file mode 100644
index cff89232..00000000
--- a/src/transform.cpp
+++ /dev/null
@@ -1,1850 +0,0 @@
-/******************************************************************************
- * Project: PROJ.4
- * Purpose: Perform overall coordinate system to coordinate system
- * transformations (pj_transform() function) including reprojection
- * and datum shifting.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2000, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-#include <errno.h>
-#include <math.h>
-#include <string.h>
-
-#include "proj.h"
-#include "proj_internal.h"
-#include "grids.hpp"
-
-using namespace NS_PROJ;
-
-
-///////////////////////////////////////////////////////////////////////////////
-/// From older geocent.h
-///////////////////////////////////////////////////////////////////////////////
-
-
-/***************************************************************************/
-/* RSC IDENTIFIER: GEOCENTRIC
- *
- * ABSTRACT
- *
- * This component provides conversions between Geodetic coordinates (latitude,
- * longitude in radians and height in meters) and Geocentric coordinates
- * (X, Y, Z) in meters.
- *
- * ERROR HANDLING
- *
- * This component checks parameters for valid values. If an invalid value
- * is found, the error code is combined with the current error code using
- * the bitwise or. This combining allows multiple error codes to be
- * returned. The possible error codes are:
- *
- * GEOCENT_NO_ERROR : No errors occurred in function
- * GEOCENT_LAT_ERROR : Latitude out of valid range
- * (-90 to 90 degrees)
- * GEOCENT_LON_ERROR : Longitude out of valid range
- * (-180 to 360 degrees)
- * GEOCENT_A_ERROR : Semi-major axis less than or equal to zero
- * GEOCENT_B_ERROR : Semi-minor axis less than or equal to zero
- * GEOCENT_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis
- *
- *
- * REUSE NOTES
- *
- * GEOCENTRIC is intended for reuse by any application that performs
- * coordinate conversions between geodetic coordinates and geocentric
- * coordinates.
- *
- *
- * REFERENCES
- *
- * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion,
- * Ralph Toms, February 1996 UCRL-JC-123138.
- *
- * Further information on GEOCENTRIC can be found in the Reuse Manual.
- *
- * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center
- * Geospatial Information Division
- * 7701 Telegraph Road
- * Alexandria, VA 22310-3864
- *
- * LICENSES
- *
- * None apply to this component.
- *
- * RESTRICTIONS
- *
- * GEOCENTRIC has no restrictions.
- *
- * ENVIRONMENT
- *
- * GEOCENTRIC was tested and certified in the following environments:
- *
- * 1. Solaris 2.5 with GCC version 2.8.1
- * 2. Windows 95 with MS Visual C++ version 6
- *
- * MODIFICATIONS
- *
- * Date Description
- * ---- -----------
- *
- *
- */
-
-
-/***************************************************************************/
-/*
- * DEFINES
- */
-#define GEOCENT_NO_ERROR 0x0000
-#define GEOCENT_LAT_ERROR 0x0001
-#define GEOCENT_LON_ERROR 0x0002
-#define GEOCENT_A_ERROR 0x0004
-#define GEOCENT_B_ERROR 0x0008
-#define GEOCENT_A_LESS_B_ERROR 0x0010
-
-
-/***************************************************************************/
-/*
- * FUNCTION PROTOTYPES
- */
-
-/* ensure proper linkage to c++ programs */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct
-{
- double Geocent_a; /* Semi-major axis of ellipsoid in meters */
- double Geocent_b; /* Semi-minor axis of ellipsoid */
- double Geocent_a2; /* Square of semi-major axis */
- double Geocent_b2; /* Square of semi-minor axis */
- double Geocent_e2; /* Eccentricity squared */
- double Geocent_ep2; /* 2nd eccentricity squared */
-} GeocentricInfo;
-
-void pj_Init_Geocentric( GeocentricInfo *gi );
-long pj_Set_Geocentric_Parameters( GeocentricInfo *gi,
- double a,
- double b);
-
-/*
- * The function Set_Geocentric_Parameters receives the ellipsoid parameters
- * as inputs and sets the corresponding state variables.
- *
- * a : Semi-major axis, in meters. (input)
- * b : Semi-minor axis, in meters. (input)
- */
-
-
-void pj_Get_Geocentric_Parameters ( GeocentricInfo *gi,
- double *a,
- double *b);
-
-/*
- * The function Get_Geocentric_Parameters returns the ellipsoid parameters
- * to be used in geocentric coordinate conversions.
- *
- * a : Semi-major axis, in meters. (output)
- * b : Semi-minor axis, in meters. (output)
- */
-
-
-long pj_Convert_Geodetic_To_Geocentric ( GeocentricInfo *gi,
- double Latitude,
- double Longitude,
- double Height,
- double *X,
- double *Y,
- double *Z);
-/*
- * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
- * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
- * according to the current ellipsoid parameters.
- *
- * Latitude : Geodetic latitude in radians (input)
- * Longitude : Geodetic longitude in radians (input)
- * Height : Geodetic height, in meters (input)
- * X : Calculated Geocentric X coordinate, in meters. (output)
- * Y : Calculated Geocentric Y coordinate, in meters. (output)
- * Z : Calculated Geocentric Z coordinate, in meters. (output)
- *
- */
-
-
-void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo *gi,
- double X,
- double Y,
- double Z,
- double *Latitude,
- double *Longitude,
- double *Height);
-/*
- * The function Convert_Geocentric_To_Geodetic converts geocentric
- * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude,
- * and height), according to the current ellipsoid parameters.
- *
- * X : Geocentric X coordinate, in meters. (input)
- * Y : Geocentric Y coordinate, in meters. (input)
- * Z : Geocentric Z coordinate, in meters. (input)
- * Latitude : Calculated latitude value in radians. (output)
- * Longitude : Calculated longitude value in radians. (output)
- * Height : Calculated height value, in meters. (output)
- */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-
-///////////////////////////////////////////////////////////////////////////////
-/// From older geocent.cpp
-///////////////////////////////////////////////////////////////////////////////
-
-
-/***************************************************************************/
-/* RSC IDENTIFIER: GEOCENTRIC
- *
- * ABSTRACT
- *
- * This component provides conversions between Geodetic coordinates (latitude,
- * longitude in radians and height in meters) and Geocentric coordinates
- * (X, Y, Z) in meters.
- *
- * ERROR HANDLING
- *
- * This component checks parameters for valid values. If an invalid value
- * is found, the error code is combined with the current error code using
- * the bitwise or. This combining allows multiple error codes to be
- * returned. The possible error codes are:
- *
- * GEOCENT_NO_ERROR : No errors occurred in function
- * GEOCENT_LAT_ERROR : Latitude out of valid range
- * (-90 to 90 degrees)
- * GEOCENT_LON_ERROR : Longitude out of valid range
- * (-180 to 360 degrees)
- * GEOCENT_A_ERROR : Semi-major axis lessthan or equal to zero
- * GEOCENT_B_ERROR : Semi-minor axis lessthan or equal to zero
- * GEOCENT_A_LESS_B_ERROR : Semi-major axis less than semi-minor axis
- *
- *
- * REUSE NOTES
- *
- * GEOCENTRIC is intended for reuse by any application that performs
- * coordinate conversions between geodetic coordinates and geocentric
- * coordinates.
- *
- *
- * REFERENCES
- *
- * An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion,
- * Ralph Toms, February 1996 UCRL-JC-123138.
- *
- * Further information on GEOCENTRIC can be found in the Reuse Manual.
- *
- * GEOCENTRIC originated from : U.S. Army Topographic Engineering Center
- * Geospatial Information Division
- * 7701 Telegraph Road
- * Alexandria, VA 22310-3864
- *
- * LICENSES
- *
- * None apply to this component.
- *
- * RESTRICTIONS
- *
- * GEOCENTRIC has no restrictions.
- *
- * ENVIRONMENT
- *
- * GEOCENTRIC was tested and certified in the following environments:
- *
- * 1. Solaris 2.5 with GCC version 2.8.1
- * 2. Windows 95 with MS Visual C++ version 6
- *
- * MODIFICATIONS
- *
- * Date Description
- * ---- -----------
- * 25-02-97 Original Code
- *
- */
-
-
-/***************************************************************************/
-/*
- * INCLUDES
- */
-#include <math.h>
-//#include "geocent.h"
-/*
- * math.h - is needed for calls to sin, cos, tan and sqrt.
- * geocent.h - is needed for Error codes and prototype error checking.
- */
-
-
-/***************************************************************************/
-/*
- * DEFINES
- */
-#define PI 3.14159265358979323e0
-#define PI_OVER_2 (PI / 2.0e0)
-#define FALSE 0
-#define TRUE 1
-#define COS_67P5 0.38268343236508977 /* cosine of 67.5 degrees */
-#define AD_C 1.0026000 /* Toms region 1 constant */
-
-
-/***************************************************************************/
-/*
- * FUNCTIONS
- */
-
-
-long pj_Set_Geocentric_Parameters (GeocentricInfo *gi, double a, double b)
-
-{ /* BEGIN Set_Geocentric_Parameters */
-/*
- * The function Set_Geocentric_Parameters receives the ellipsoid parameters
- * as inputs and sets the corresponding state variables.
- *
- * a : Semi-major axis, in meters. (input)
- * b : Semi-minor axis, in meters. (input)
- */
- long Error_Code = GEOCENT_NO_ERROR;
-
- if (a <= 0.0)
- Error_Code |= GEOCENT_A_ERROR;
- if (b <= 0.0)
- Error_Code |= GEOCENT_B_ERROR;
- if (a < b)
- Error_Code |= GEOCENT_A_LESS_B_ERROR;
- if (!Error_Code)
- {
- gi->Geocent_a = a;
- gi->Geocent_b = b;
- gi->Geocent_a2 = a * a;
- gi->Geocent_b2 = b * b;
- gi->Geocent_e2 = (gi->Geocent_a2 - gi->Geocent_b2) / gi->Geocent_a2;
- gi->Geocent_ep2 = (gi->Geocent_a2 - gi->Geocent_b2) / gi->Geocent_b2;
- }
- return (Error_Code);
-} /* END OF Set_Geocentric_Parameters */
-
-
-void pj_Get_Geocentric_Parameters (GeocentricInfo *gi,
- double *a,
- double *b)
-{ /* BEGIN Get_Geocentric_Parameters */
-/*
- * The function Get_Geocentric_Parameters returns the ellipsoid parameters
- * to be used in geocentric coordinate conversions.
- *
- * a : Semi-major axis, in meters. (output)
- * b : Semi-minor axis, in meters. (output)
- */
-
- *a = gi->Geocent_a;
- *b = gi->Geocent_b;
-} /* END OF Get_Geocentric_Parameters */
-
-
-long pj_Convert_Geodetic_To_Geocentric (GeocentricInfo *gi,
- double Latitude,
- double Longitude,
- double Height,
- double *X,
- double *Y,
- double *Z)
-{ /* BEGIN Convert_Geodetic_To_Geocentric */
-/*
- * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates
- * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z),
- * according to the current ellipsoid parameters.
- *
- * Latitude : Geodetic latitude in radians (input)
- * Longitude : Geodetic longitude in radians (input)
- * Height : Geodetic height, in meters (input)
- * X : Calculated Geocentric X coordinate, in meters (output)
- * Y : Calculated Geocentric Y coordinate, in meters (output)
- * Z : Calculated Geocentric Z coordinate, in meters (output)
- *
- */
- long Error_Code = GEOCENT_NO_ERROR;
- double Rn; /* Earth radius at location */
- double Sin_Lat; /* sin(Latitude) */
- double Sin2_Lat; /* Square of sin(Latitude) */
- double Cos_Lat; /* cos(Latitude) */
-
- /*
- ** Don't blow up if Latitude is just a little out of the value
- ** range as it may just be a rounding issue. Also removed longitude
- ** test, it should be wrapped by cos() and sin(). NFW for PROJ.4, Sep/2001.
- */
- if( Latitude < -PI_OVER_2 && Latitude > -1.001 * PI_OVER_2 )
- Latitude = -PI_OVER_2;
- else if( Latitude > PI_OVER_2 && Latitude < 1.001 * PI_OVER_2 )
- Latitude = PI_OVER_2;
- else if ((Latitude < -PI_OVER_2) || (Latitude > PI_OVER_2))
- { /* Latitude out of range */
- Error_Code |= GEOCENT_LAT_ERROR;
- }
-
- if (!Error_Code)
- { /* no errors */
- if (Longitude > PI)
- Longitude -= (2*PI);
- Sin_Lat = sin(Latitude);
- Cos_Lat = cos(Latitude);
- Sin2_Lat = Sin_Lat * Sin_Lat;
- Rn = gi->Geocent_a / (sqrt(1.0e0 - gi->Geocent_e2 * Sin2_Lat));
- *X = (Rn + Height) * Cos_Lat * cos(Longitude);
- *Y = (Rn + Height) * Cos_Lat * sin(Longitude);
- *Z = ((Rn * (1 - gi->Geocent_e2)) + Height) * Sin_Lat;
-
- }
- return (Error_Code);
-} /* END OF Convert_Geodetic_To_Geocentric */
-
-/*
- * The function Convert_Geocentric_To_Geodetic converts geocentric
- * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude,
- * and height), according to the current ellipsoid parameters.
- *
- * X : Geocentric X coordinate, in meters. (input)
- * Y : Geocentric Y coordinate, in meters. (input)
- * Z : Geocentric Z coordinate, in meters. (input)
- * Latitude : Calculated latitude value in radians. (output)
- * Longitude : Calculated longitude value in radians. (output)
- * Height : Calculated height value, in meters. (output)
- */
-
-#define USE_ITERATIVE_METHOD
-
-void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo *gi,
- double X,
- double Y,
- double Z,
- double *Latitude,
- double *Longitude,
- double *Height)
-{ /* BEGIN Convert_Geocentric_To_Geodetic */
-#if !defined(USE_ITERATIVE_METHOD)
-/*
- * The method used here is derived from 'An Improved Algorithm for
- * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996
- */
-
-/* Note: Variable names follow the notation used in Toms, Feb 1996 */
-
- double W; /* distance from Z axis */
- double W2; /* square of distance from Z axis */
- double T0; /* initial estimate of vertical component */
- double T1; /* corrected estimate of vertical component */
- double S0; /* initial estimate of horizontal component */
- double S1; /* corrected estimate of horizontal component */
- double Sin_B0; /* sin(B0), B0 is estimate of Bowring aux variable */
- double Sin3_B0; /* cube of sin(B0) */
- double Cos_B0; /* cos(B0) */
- double Sin_p1; /* sin(phi1), phi1 is estimated latitude */
- double Cos_p1; /* cos(phi1) */
- double Rn; /* Earth radius at location */
- double Sum; /* numerator of cos(phi1) */
- int At_Pole; /* indicates location is in polar region */
-
- At_Pole = FALSE;
- if (X != 0.0)
- {
- *Longitude = atan2(Y,X);
- }
- else
- {
- if (Y > 0)
- {
- *Longitude = PI_OVER_2;
- }
- else if (Y < 0)
- {
- *Longitude = -PI_OVER_2;
- }
- else
- {
- At_Pole = TRUE;
- *Longitude = 0.0;
- if (Z > 0.0)
- { /* north pole */
- *Latitude = PI_OVER_2;
- }
- else if (Z < 0.0)
- { /* south pole */
- *Latitude = -PI_OVER_2;
- }
- else
- { /* center of earth */
- *Latitude = PI_OVER_2;
- *Height = -Geocent_b;
- return;
- }
- }
- }
- W2 = X*X + Y*Y;
- W = sqrt(W2);
- T0 = Z * AD_C;
- S0 = sqrt(T0 * T0 + W2);
- Sin_B0 = T0 / S0;
- Cos_B0 = W / S0;
- Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
- T1 = Z + gi->Geocent_b * gi->Geocent_ep2 * Sin3_B0;
- Sum = W - gi->Geocent_a * gi->Geocent_e2 * Cos_B0 * Cos_B0 * Cos_B0;
- S1 = sqrt(T1*T1 + Sum * Sum);
- Sin_p1 = T1 / S1;
- Cos_p1 = Sum / S1;
- Rn = gi->Geocent_a / sqrt(1.0 - gi->Geocent_e2 * Sin_p1 * Sin_p1);
- if (Cos_p1 >= COS_67P5)
- {
- *Height = W / Cos_p1 - Rn;
- }
- else if (Cos_p1 <= -COS_67P5)
- {
- *Height = W / -Cos_p1 - Rn;
- }
- else
- {
- *Height = Z / Sin_p1 + Rn * (gi->Geocent_e2 - 1.0);
- }
- if (At_Pole == FALSE)
- {
- *Latitude = atan(Sin_p1 / Cos_p1);
- }
-#else /* defined(USE_ITERATIVE_METHOD) */
-/*
-* Reference...
-* ============
-* Wenzel, H.-G.(1985): Hochauflösende Kugelfunktionsmodelle für
-* das Gravitationspotential der Erde. Wiss. Arb. Univ. Hannover
-* Nr. 137, p. 130-131.
-
-* Programmed by GGA- Leibniz-Institute of Applied Geophysics
-* Stilleweg 2
-* D-30655 Hannover
-* Federal Republic of Germany
-* Internet: www.gga-hannover.de
-*
-* Hannover, March 1999, April 2004.
-* see also: comments in statements
-* remarks:
-* Mathematically exact and because of symmetry of rotation-ellipsoid,
-* each point (X,Y,Z) has at least two solutions (Latitude1,Longitude1,Height1) and
-* (Latitude2,Longitude2,Height2). Is point=(0.,0.,Z) (P=0.), so you get even
-* four solutions, every two symmetrical to the semi-minor axis.
-* Here Height1 and Height2 have at least a difference in order of
-* radius of curvature (e.g. (0,0,b)=> (90.,0.,0.) or (-90.,0.,-2b);
-* (a+100.)*(sqrt(2.)/2.,sqrt(2.)/2.,0.) => (0.,45.,100.) or
-* (0.,225.,-(2a+100.))).
-* The algorithm always computes (Latitude,Longitude) with smallest |Height|.
-* For normal computations, that means |Height|<10000.m, algorithm normally
-* converges after to 2-3 steps!!!
-* But if |Height| has the amount of length of ellipsoid's axis
-* (e.g. -6300000.m), algorithm needs about 15 steps.
-*/
-
-/* local definitions and variables */
-/* end-criterium of loop, accuracy of sin(Latitude) */
-#define genau 1.E-12
-#define genau2 (genau*genau)
-#define maxiter 30
-
- double P; /* distance between semi-minor axis and location */
- double RR; /* distance between center and location */
- double CT; /* sin of geocentric latitude */
- double ST; /* cos of geocentric latitude */
- double RX;
- double RK;
- double RN; /* Earth radius at location */
- double CPHI0; /* cos of start or old geodetic latitude in iterations */
- double SPHI0; /* sin of start or old geodetic latitude in iterations */
- double CPHI; /* cos of searched geodetic latitude */
- double SPHI; /* sin of searched geodetic latitude */
- double SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */
- int iter; /* # of continuous iteration, max. 30 is always enough (s.a.) */
-
- P = sqrt(X*X+Y*Y);
- RR = sqrt(X*X+Y*Y+Z*Z);
-
-/* special cases for latitude and longitude */
- if (P/gi->Geocent_a < genau) {
-
-/* special case, if P=0. (X=0., Y=0.) */
- *Longitude = 0.;
-
-/* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis
- * of ellipsoid (=center of mass), Latitude becomes PI/2 */
- if (RR/gi->Geocent_a < genau) {
- *Latitude = PI_OVER_2;
- *Height = -gi->Geocent_b;
- return ;
-
- }
- }
- else {
-/* ellipsoidal (geodetic) longitude
- * interval: -PI < Longitude <= +PI */
- *Longitude=atan2(Y,X);
- }
-
-/* --------------------------------------------------------------
- * Following iterative algorithm was developed by
- * "Institut für Erdmessung", University of Hannover, July 1988.
- * Internet: www.ife.uni-hannover.de
- * Iterative computation of CPHI,SPHI and Height.
- * Iteration of CPHI and SPHI to 10**-12 radian resp.
- * 2*10**-7 arcsec.
- * --------------------------------------------------------------
- */
- CT = Z/RR;
- ST = P/RR;
- {
- const double denominator = 1.0-gi->Geocent_e2*(2.0-gi->Geocent_e2)*ST*ST;
- if( denominator == 0 )
- {
- *Latitude = HUGE_VAL;
- *Longitude = HUGE_VAL;
- *Height = HUGE_VAL;
- return;
- }
- RX = 1.0/sqrt(denominator);
- }
- CPHI0 = ST*(1.0-gi->Geocent_e2)*RX;
- SPHI0 = CT*RX;
- iter = 0;
-
-/* loop to find sin(Latitude) resp. Latitude
- * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */
- do
- {
- iter++;
- RN = gi->Geocent_a/sqrt(1.0-gi->Geocent_e2*SPHI0*SPHI0);
-
-/* ellipsoidal (geodetic) height */
- *Height = P*CPHI0+Z*SPHI0-RN*(1.0-gi->Geocent_e2*SPHI0*SPHI0);
-
- /* avoid zero division */
- if (RN+*Height==0.0) {
- *Latitude = 0.0;
- return;
- }
- RK = gi->Geocent_e2*RN/(RN+*Height);
- {
- const double denominator = 1.0-RK*(2.0-RK)*ST*ST;
- if( denominator == 0 )
- {
- *Latitude = HUGE_VAL;
- *Longitude = HUGE_VAL;
- *Height = HUGE_VAL;
- return;
- }
- RX = 1.0/sqrt(denominator);
- }
- CPHI = ST*(1.0-RK)*RX;
- SPHI = CT*RX;
- SDPHI = SPHI*CPHI0-CPHI*SPHI0;
- CPHI0 = CPHI;
- SPHI0 = SPHI;
- }
- while (SDPHI*SDPHI > genau2 && iter < maxiter);
-
-/* ellipsoidal (geodetic) latitude */
- *Latitude=atan2(SPHI, fabs(CPHI));
-
-#endif /* defined(USE_ITERATIVE_METHOD) */
-} /* END OF Convert_Geocentric_To_Geodetic */
-
-
-///////////////////////////////////////////////////////////////////////////////
-/// Main of transform.cpp
-///////////////////////////////////////////////////////////////////////////////
-
-
-static int adjust_axis( projCtx ctx, const char *axis, int denormalize_flag,
- long point_count, int point_offset,
- double *x, double *y, double *z );
-
-#ifndef SRS_WGS84_SEMIMAJOR
-#define SRS_WGS84_SEMIMAJOR 6378137.0
-#endif
-
-#ifndef SRS_WGS84_ESQUARED
-#define SRS_WGS84_ESQUARED 0.0066943799901413165
-#endif
-
-#define Dx_BF (defn->datum_params[0])
-#define Dy_BF (defn->datum_params[1])
-#define Dz_BF (defn->datum_params[2])
-#define Rx_BF (defn->datum_params[3])
-#define Ry_BF (defn->datum_params[4])
-#define Rz_BF (defn->datum_params[5])
-#define M_BF (defn->datum_params[6])
-
-/*
-** This table is intended to indicate for any given error code
-** whether that error will occur for all locations (ie.
-** it is a problem with the coordinate system as a whole) in which case the
-** value would be 0, or if the problem is with the point being transformed
-** in which case the value is 1.
-**
-** At some point we might want to move this array in with the error message
-** list or something, but while experimenting with it this should be fine.
-**
-**
-** NOTE (2017-10-01): Non-transient errors really should have resulted in a
-** PJ==0 during initialization, and hence should be handled at the level
-** before calling pj_transform. The only obvious example of the contrary
-** appears to be the PJD_ERR_GRID_AREA case, which may also be taken to
-** mean "no grids available"
-**
-**
-*/
-
-static const int transient_error[70] = {
- /* 0 1 2 3 4 5 6 7 8 9 */
- /* 0 to 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 10 to 19 */ 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
- /* 20 to 29 */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0,
- /* 30 to 39 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 40 to 49 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- /* 50 to 59 */ 1, 0, 1, 0, 1, 1, 1, 1, 0, 0,
- /* 60 to 69 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
-
-
-/* -------------------------------------------------------------------- */
-/* Read transient_error[] in a safe way. */
-/* -------------------------------------------------------------------- */
-static int get_transient_error_value(int pos_index)
-{
- const int array_size =
- (int)(sizeof(transient_error) / sizeof(transient_error[0]));
- if( pos_index < 0 || pos_index >= array_size ) {
- return 0;
- }
- return transient_error[pos_index];
-}
-
-
-/* -------------------------------------------------------------------- */
-/* Transform unusual input coordinate axis orientation to */
-/* standard form if needed. */
-/* -------------------------------------------------------------------- */
-static int adjust_axes (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) {
- /* Nothing to do? */
- if (0==strcmp(P->axis,"enu"))
- return 0;
-
- return adjust_axis( P->ctx, P->axis,
- dir==PJ_FWD ? 1: 0, n, dist, x, y, z );
-}
-
-
-
-/* ----------------------------------------------------------------------- */
-/* Transform geographic (lat/long) source coordinates to */
-/* cartesian ("geocentric"), if needed */
-/* ----------------------------------------------------------------------- */
-static int geographic_to_cartesian (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) {
- int res;
- long i;
- double fac = P->to_meter;
-
- /* Nothing to do? */
- if (!P->is_geocent)
- return 0;
-
- if ( z == nullptr ) {
- pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC);
- return PJD_ERR_GEOCENTRIC;
- }
-
- if (PJ_FWD==dir) {
- fac = P->fr_meter;
- res = pj_geodetic_to_geocentric( P->a_orig, P->es_orig, n, dist, x, y, z );
- if (res)
- return res;
- }
-
- if (fac != 1.0) {
- for( i = 0; i < n; i++ ) {
- if( x[dist*i] != HUGE_VAL ) {
- x[dist*i] *= fac;
- y[dist*i] *= fac;
- z[dist*i] *= fac;
- }
- }
- }
-
- if (PJ_FWD==dir)
- return 0;
- return pj_geocentric_to_geodetic(
- P->a_orig, P->es_orig,
- n, dist,
- x, y, z
- );
-}
-
-
-
-
-
-
-
-
-
-
-/* -------------------------------------------------------------------- */
-/* Transform destination points to projection coordinates, if */
-/* desired. */
-/* */
-/* Ought to fold this into projected_to_geographic */
-/* -------------------------------------------------------------------- */
-static int geographic_to_projected (PJ *P, long n, int dist, double *x, double *y, double *z) {
- long i;
-
- /* Nothing to do? */
- if (P->is_latlong && !P->geoc && P->vto_meter == 1.0)
- return 0;
- if (P->is_geocent)
- return 0;
-
- if(P->fwd3d != nullptr && !(z == nullptr && P->is_latlong))
- {
- /* Three dimensions must be defined */
- if ( z == nullptr)
- {
- pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC);
- return PJD_ERR_GEOCENTRIC;
- }
-
- for( i = 0; i < n; i++ )
- {
- PJ_XYZ projected_loc;
- PJ_LPZ geodetic_loc;
-
- geodetic_loc.lam = x[dist*i];
- geodetic_loc.phi = y[dist*i];
- geodetic_loc.z = z[dist*i];
-
- if (geodetic_loc.lam == HUGE_VAL)
- continue;
-
- proj_errno_reset( P );
- projected_loc = pj_fwd3d( geodetic_loc, P);
- if( P->ctx->last_errno != 0 )
- {
- if( (P->ctx->last_errno != EDOM
- && P->ctx->last_errno != ERANGE)
- && (P->ctx->last_errno > 0
- || P->ctx->last_errno < -44 || n == 1
- || get_transient_error_value(-P->ctx->last_errno) == 0 ) )
- {
- return P->ctx->last_errno;
- }
- else
- {
- projected_loc.x = HUGE_VAL;
- projected_loc.y = HUGE_VAL;
- projected_loc.z = HUGE_VAL;
- }
- }
-
- x[dist*i] = projected_loc.x;
- y[dist*i] = projected_loc.y;
- z[dist*i] = projected_loc.z;
- }
- return 0;
- }
-
- // Ugly hack. See https://github.com/OSGeo/PROJ/issues/1782
- if( P->right == PJ_IO_UNITS_WHATEVER && P->descr &&
- strncmp(P->descr, "General Oblique Transformation",
- strlen("General Oblique Transformation")) == 0 )
- {
- P->right = PJ_IO_UNITS_PROJECTED;
- }
-
- for( i = 0; i <n; i++ )
- {
- PJ_XY projected_loc;
- PJ_LP geodetic_loc;
-
- geodetic_loc.lam = x[dist*i];
- geodetic_loc.phi = y[dist*i];
-
- if( geodetic_loc.lam == HUGE_VAL )
- continue;
-
- proj_errno_reset( P );
- projected_loc = pj_fwd( geodetic_loc, P );
- if( P->ctx->last_errno != 0 )
- {
- if( (P->ctx->last_errno != EDOM
- && P->ctx->last_errno != ERANGE)
- && (P->ctx->last_errno > 0
- || P->ctx->last_errno < -44 || n == 1
- || get_transient_error_value(-P->ctx->last_errno) == 0 ) )
- {
- return P->ctx->last_errno;
- }
- else
- {
- projected_loc.x = HUGE_VAL;
- projected_loc.y = HUGE_VAL;
- }
- }
-
- x[dist*i] = projected_loc.x;
- y[dist*i] = projected_loc.y;
- }
- return 0;
-}
-
-
-
-
-
-/* ----------------------------------------------------------------------- */
-/* Transform projected source coordinates to lat/long, if needed */
-/* ----------------------------------------------------------------------- */
-static int projected_to_geographic (PJ *P, long n, int dist, double *x, double *y, double *z) {
- long i;
-
- /* Nothing to do? */
- if (P->is_latlong && !P->geoc && P->vto_meter == 1.0)
- return 0;
- if (P->is_geocent)
- return 0;
-
- /* Check first if projection is invertible. */
- if( (P->inv3d == nullptr) && (P->inv == nullptr))
- {
- pj_ctx_set_errno(pj_get_ctx(P), PJD_ERR_NON_CONV_INV_MERI_DIST);
- pj_log( pj_get_ctx(P), PJ_LOG_ERROR,
- "pj_transform(): source projection not invertable" );
- return PJD_ERR_NON_CONV_INV_MERI_DIST;
- }
-
- /* If invertible - First try inv3d if defined */
- if (P->inv3d != nullptr && !(z == nullptr && P->is_latlong))
- {
- /* Three dimensions must be defined */
- if ( z == nullptr)
- {
- pj_ctx_set_errno( pj_get_ctx(P), PJD_ERR_GEOCENTRIC);
- return PJD_ERR_GEOCENTRIC;
- }
-
- for (i=0; i < n; i++)
- {
- PJ_XYZ projected_loc;
- PJ_LPZ geodetic_loc;
-
- projected_loc.x = x[dist*i];
- projected_loc.y = y[dist*i];
- projected_loc.z = z[dist*i];
-
- if (projected_loc.x == HUGE_VAL)
- continue;
-
- proj_errno_reset( P );
- geodetic_loc = pj_inv3d(projected_loc, P);
- if( P->ctx->last_errno != 0 )
- {
- if( (P->ctx->last_errno != EDOM
- && P->ctx->last_errno != ERANGE)
- && (P->ctx->last_errno > 0
- || P->ctx->last_errno < -44 || n == 1
- || get_transient_error_value(-P->ctx->last_errno) == 0 ) )
- {
- return P->ctx->last_errno;
- }
- else
- {
- geodetic_loc.lam = HUGE_VAL;
- geodetic_loc.phi = HUGE_VAL;
- geodetic_loc.z = HUGE_VAL;
- }
- }
-
- x[dist*i] = geodetic_loc.lam;
- y[dist*i] = geodetic_loc.phi;
- z[dist*i] = geodetic_loc.z;
-
- }
- return 0;
- }
-
- // Ugly hack. See https://github.com/OSGeo/PROJ/issues/1782
- if( P->right == PJ_IO_UNITS_WHATEVER && P->descr &&
- strncmp(P->descr, "General Oblique Transformation",
- strlen("General Oblique Transformation")) == 0 )
- {
- P->right = PJ_IO_UNITS_PROJECTED;
- }
-
- /* Fallback to the original PROJ.4 API 2d inversion - inv */
- for( i = 0; i < n; i++ ) {
- PJ_XY projected_loc;
- PJ_LP geodetic_loc;
-
- projected_loc.x = x[dist*i];
- projected_loc.y = y[dist*i];
-
- if( projected_loc.x == HUGE_VAL )
- continue;
-
- proj_errno_reset( P );
- geodetic_loc = pj_inv( projected_loc, P );
- if( P->ctx->last_errno != 0 )
- {
- if( (P->ctx->last_errno != EDOM
- && P->ctx->last_errno != ERANGE)
- && (P->ctx->last_errno > 0
- || P->ctx->last_errno < -44 || n == 1
- || get_transient_error_value(-P->ctx->last_errno) == 0 ) )
- {
- return P->ctx->last_errno;
- }
- else
- {
- geodetic_loc.lam = HUGE_VAL;
- geodetic_loc.phi = HUGE_VAL;
- }
- }
-
- x[dist*i] = geodetic_loc.lam;
- y[dist*i] = geodetic_loc.phi;
- }
- return 0;
-}
-
-
-
-/* -------------------------------------------------------------------- */
-/* Adjust for the prime meridian if needed. */
-/* -------------------------------------------------------------------- */
-static int prime_meridian (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x) {
- int i;
- double pm = P->from_greenwich;
-
- /* Nothing to do? */
- if (pm==0.0)
- return 0;
- if (!(P->is_geocent || P->is_latlong))
- return 0;
-
- if (dir==PJ_FWD)
- pm = -pm;
-
- for (i = 0; i < n; i++)
- if (x[dist*i] != HUGE_VAL)
- x[dist*i] += pm;
-
- return 0;
-}
-
-
-
-/* -------------------------------------------------------------------- */
-/* Adjust for vertical scale factor if needed */
-/* -------------------------------------------------------------------- */
-static int height_unit (PJ *P, PJ_DIRECTION dir, long n, int dist, double *z) {
- int i;
- double fac = P->vto_meter;
-
- if (PJ_FWD==dir)
- fac = P->vfr_meter;
-
- /* Nothing to do? */
- if (fac==1.0)
- return 0;
- if (nullptr==z)
- return 0;
- if (P->is_latlong)
- return 0; /* done in pj_inv3d() / pj_fwd3d() */
-
- for (i = 0; i < n; i++)
- if (z[dist*i] != HUGE_VAL )
- z[dist*i] *= fac;
-
- return 0;
-}
-
-
-/************************************************************************/
-/* pj_apply_vgridshift() */
-/* */
-/* This implementation takes uses the gridlist from a coordinate */
-/* system definition. If the gridlist has not yet been */
-/* populated in the coordinate system definition we set it up */
-/* now. */
-/************************************************************************/
-static int pj_apply_vgridshift( PJ *defn,
- int inverse,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- if( defn->vgrids_legacy == nullptr )
- {
- defn->vgrids_legacy = new ListOfVGrids;
- auto vgrids = pj_vgrid_init(defn, "geoidgrids");
- if( vgrids.empty() )
- return 0;
- *static_cast<ListOfVGrids*>(defn->vgrids_legacy) = std::move(vgrids);
- }
- if( static_cast<ListOfVGrids*>(defn->vgrids_legacy)->empty() )
- {
- return 0;
- }
-
- for( int i = 0; i < point_count; i++ )
- {
- double value;
- long io = i * point_offset;
- PJ_LP input;
-
- input.phi = y[io];
- input.lam = x[io];
-
- value = pj_vgrid_value(defn, *static_cast<ListOfVGrids*>(defn->vgrids_legacy), input, 1.0);
-
- if( inverse )
- z[io] -= value;
- else
- z[io] += value;
-
- if( value == HUGE_VAL )
- {
- std::string gridlist;
-
- proj_log_debug(defn,
- "pj_apply_vgridshift(): failed to find a grid shift table for\n"
- " location (%.7fdW,%.7fdN)",
- x[io] * RAD_TO_DEG,
- y[io] * RAD_TO_DEG );
-
- for( const auto& gridset: *static_cast<ListOfVGrids*>(defn->vgrids_legacy) )
- {
- if( gridlist.empty() )
- gridlist += " tried: ";
- else
- gridlist += ',';
- gridlist += gridset->name();
- }
-
- proj_log_debug(defn, "%s", gridlist.c_str());
- pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA );
-
- return PJD_ERR_GRID_AREA;
- }
- }
-
- return 0;
-}
-
-
-/* -------------------------------------------------------------------- */
-/* Transform to ellipsoidal heights if needed */
-/* -------------------------------------------------------------------- */
-static int geometric_to_orthometric (PJ *P, PJ_DIRECTION dir, long n, int dist, double *x, double *y, double *z) {
- int err;
- if (0==P->has_geoid_vgrids)
- return 0;
- if (z==nullptr)
- return PJD_ERR_GEOCENTRIC;
- err = pj_apply_vgridshift (P, dir==PJ_FWD ? 1 : 0, n, dist, x, y, z );
- if (err)
- return pj_ctx_get_errno(P->ctx);
- return 0;
-}
-
-
-
-/* -------------------------------------------------------------------- */
-/* Convert datums if needed, and possible. */
-/* -------------------------------------------------------------------- */
-static int datum_transform (PJ *P, PJ *Q, long n, int dist, double *x, double *y, double *z) {
- if (0==pj_datum_transform (P, Q, n, dist, x, y, z))
- return 0;
- if (P->ctx->last_errno)
- return P->ctx->last_errno;
- return Q->ctx->last_errno;
-}
-
-
-
-
-
-/* -------------------------------------------------------------------- */
-/* If a wrapping center other than 0 is provided, rewrap around */
-/* the suggested center (for latlong coordinate systems only). */
-/* -------------------------------------------------------------------- */
-static int long_wrap (PJ *P, long n, int dist, double *x) {
- long i;
-
- /* Nothing to do? */
- if (P->is_geocent)
- return 0;
- if (!P->is_long_wrap_set)
- return 0;
- if (!P->is_latlong)
- return 0;
-
- for (i = 0; i < n; i++ ) {
- double val = x[dist*i];
- if (val == HUGE_VAL)
- continue;
-
- /* Get fast in ] -2 PI, 2 PI [ range */
- val = fmod(val, M_TWOPI);
- while( val < P->long_wrap_center - M_PI )
- val += M_TWOPI;
- while( val > P->long_wrap_center + M_PI )
- val -= M_TWOPI;
- x[dist*i] = val;
- }
- return 0;
-}
-
-
-
-/************************************************************************/
-/* pj_transform() */
-/* */
-/* Currently this function doesn't recognise if two projections */
-/* are identical (to short circuit reprojection) because it is */
-/* difficult to compare PJ structures (since there are some */
-/* projection specific components). */
-/************************************************************************/
-
-int pj_transform(
- PJ *src, PJ *dst,
- long point_count, int point_offset,
- double *x, double *y, double *z
-){
- int err;
-
- src->ctx->last_errno = 0;
- dst->ctx->last_errno = 0;
-
- if( point_offset == 0 )
- point_offset = 1;
-
- /* Bring input to "normal form": longitude, latitude, ellipsoidal height */
-
- err = adjust_axes (src, PJ_INV, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = geographic_to_cartesian (src, PJ_INV, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = projected_to_geographic (src, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = prime_meridian (src, PJ_INV, point_count, point_offset, x);
- if (err)
- return err;
- err = height_unit (src, PJ_INV, point_count, point_offset, z);
- if (err)
- return err;
- err = geometric_to_orthometric (src, PJ_INV, point_count, point_offset, x, y, z);
- if (err)
- return err;
-
- /* At the center of the process we do the datum shift (if needed) */
-
- err = datum_transform(src, dst, point_count, point_offset, x, y, z );
- if (err)
- return err;
-
- /* Now get out on the other side: Bring "normal form" to output form */
-
- err = geometric_to_orthometric (dst, PJ_FWD, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = height_unit (dst, PJ_FWD, point_count, point_offset, z);
- if (err)
- return err;
- err = prime_meridian (dst, PJ_FWD, point_count, point_offset, x);
- if (err)
- return err;
- err = geographic_to_cartesian (dst, PJ_FWD, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = geographic_to_projected (dst, point_count, point_offset, x, y, z);
- if (err)
- return err;
- err = long_wrap (dst, point_count, point_offset, x);
- if (err)
- return err;
- err = adjust_axes (dst, PJ_FWD, point_count, point_offset, x, y, z);
- if (err)
- return err;
-
- return 0;
-}
-
-
-
-/************************************************************************/
-/* pj_geodetic_to_geocentric() */
-/************************************************************************/
-
-int pj_geodetic_to_geocentric( double a, double es,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- double b;
- int i;
- GeocentricInfo gi;
- int ret_errno = 0;
-
- if( es == 0.0 )
- b = a;
- else
- b = a * sqrt(1-es);
-
- if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 )
- {
- return PJD_ERR_GEOCENTRIC;
- }
-
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- if( pj_Convert_Geodetic_To_Geocentric( &gi, y[io], x[io], z[io],
- x+io, y+io, z+io ) != 0 )
- {
- ret_errno = PJD_ERR_LAT_OR_LON_EXCEED_LIMIT;
- x[io] = y[io] = HUGE_VAL;
- /* but keep processing points! */
- }
- }
-
- return ret_errno;
-}
-
-/************************************************************************/
-/* pj_geocentric_to_geodetic() */
-/************************************************************************/
-
-int pj_geocentric_to_geodetic( double a, double es,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- double b;
- int i;
- GeocentricInfo gi;
-
- if( es == 0.0 )
- b = a;
- else
- b = a * sqrt(1-es);
-
- if( pj_Set_Geocentric_Parameters( &gi, a, b ) != 0 )
- {
- return PJD_ERR_GEOCENTRIC;
- }
-
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- pj_Convert_Geocentric_To_Geodetic( &gi, x[io], y[io], z[io],
- y+io, x+io, z+io );
- }
-
- return 0;
-}
-
-/************************************************************************/
-/* pj_compare_datums() */
-/* */
-/* Returns TRUE if the two datums are identical, otherwise */
-/* FALSE. */
-/************************************************************************/
-
-int pj_compare_datums( PJ *srcdefn, PJ *dstdefn )
-
-{
- if( srcdefn->datum_type != dstdefn->datum_type )
- {
- return 0;
- }
- else if( srcdefn->a_orig != dstdefn->a_orig
- || ABS(srcdefn->es_orig - dstdefn->es_orig) > 0.000000000050 )
- {
- /* the tolerance for es is to ensure that GRS80 and WGS84 are
- considered identical */
- return 0;
- }
- else if( srcdefn->datum_type == PJD_3PARAM )
- {
- return (srcdefn->datum_params[0] == dstdefn->datum_params[0]
- && srcdefn->datum_params[1] == dstdefn->datum_params[1]
- && srcdefn->datum_params[2] == dstdefn->datum_params[2]);
- }
- else if( srcdefn->datum_type == PJD_7PARAM )
- {
- return (srcdefn->datum_params[0] == dstdefn->datum_params[0]
- && srcdefn->datum_params[1] == dstdefn->datum_params[1]
- && srcdefn->datum_params[2] == dstdefn->datum_params[2]
- && srcdefn->datum_params[3] == dstdefn->datum_params[3]
- && srcdefn->datum_params[4] == dstdefn->datum_params[4]
- && srcdefn->datum_params[5] == dstdefn->datum_params[5]
- && srcdefn->datum_params[6] == dstdefn->datum_params[6]);
- }
- else if( srcdefn->datum_type == PJD_GRIDSHIFT )
- {
- const char* srcnadgrids =
- pj_param(srcdefn->ctx, srcdefn->params,"snadgrids").s;
- const char* dstnadgrids =
- pj_param(dstdefn->ctx, dstdefn->params,"snadgrids").s;
- return srcnadgrids != nullptr && dstnadgrids != nullptr &&
- strcmp( srcnadgrids, dstnadgrids ) == 0;
- }
- else
- return 1;
-}
-
-/************************************************************************/
-/* pj_geocentic_to_wgs84() */
-/************************************************************************/
-
-static
-int pj_geocentric_to_wgs84( PJ *defn,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- int i;
-
- if( defn->datum_type == PJD_3PARAM )
- {
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- x[io] = x[io] + Dx_BF;
- y[io] = y[io] + Dy_BF;
- z[io] = z[io] + Dz_BF;
- }
- }
- else if( defn->datum_type == PJD_7PARAM )
- {
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
- double x_out, y_out, z_out;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- x_out = M_BF*( x[io] - Rz_BF*y[io] + Ry_BF*z[io]) + Dx_BF;
- y_out = M_BF*( Rz_BF*x[io] + y[io] - Rx_BF*z[io]) + Dy_BF;
- z_out = M_BF*(-Ry_BF*x[io] + Rx_BF*y[io] + z[io]) + Dz_BF;
-
- x[io] = x_out;
- y[io] = y_out;
- z[io] = z_out;
- }
- }
-
- return 0;
-}
-
-/************************************************************************/
-/* pj_geocentic_from_wgs84() */
-/************************************************************************/
-
-static
-int pj_geocentric_from_wgs84( PJ *defn,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- int i;
-
- if( defn->datum_type == PJD_3PARAM )
- {
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- x[io] = x[io] - Dx_BF;
- y[io] = y[io] - Dy_BF;
- z[io] = z[io] - Dz_BF;
- }
- }
- else if( defn->datum_type == PJD_7PARAM )
- {
- for( i = 0; i < point_count; i++ )
- {
- long io = i * point_offset;
- double x_tmp, y_tmp, z_tmp;
-
- if( x[io] == HUGE_VAL )
- continue;
-
- x_tmp = (x[io] - Dx_BF) / M_BF;
- y_tmp = (y[io] - Dy_BF) / M_BF;
- z_tmp = (z[io] - Dz_BF) / M_BF;
-
- x[io] = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp;
- y[io] = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp;
- z[io] = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp;
- }
- }
-
- return 0;
-}
-
-
-/************************************************************************/
-/* pj_apply_gridshift_2() */
-/* */
-/* This implementation uses the gridlist from a coordinate */
-/* system definition. If the gridlist has not yet been */
-/* populated in the coordinate system definition we set it up */
-/* now. */
-/************************************************************************/
-static
-int pj_apply_gridshift_2( PJ *defn, int inverse,
- long point_count, int point_offset,
- double *x, double *y, double * /*z*/ )
-
-{
- if( defn->hgrids_legacy == nullptr )
- {
- defn->hgrids_legacy = new ListOfHGrids;
- auto hgrids = pj_hgrid_init(defn, "nadgrids");
- if( hgrids.empty() )
- return 0;
- *static_cast<ListOfHGrids*>(defn->hgrids_legacy) = std::move(hgrids);
- }
- if( static_cast<ListOfHGrids*>(defn->hgrids_legacy)->empty() )
- {
- return 0;
- }
-
- for( long i = 0; i < point_count; i++ )
- {
- PJ_LP input;
-
- long io = i * point_offset;
- input.phi = y[io];
- input.lam = x[io];
-
- auto output = pj_hgrid_apply(defn->ctx, *static_cast<ListOfHGrids*>(defn->hgrids_legacy), input, inverse ? PJ_INV : PJ_FWD);
-
- if ( output.lam != HUGE_VAL )
- {
- y[io] = output.phi;
- x[io] = output.lam;
- }
- else
- {
- if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
- {
- pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
- "pj_apply_gridshift(): failed to find a grid shift table for\n"
- " location (%.7fdW,%.7fdN)",
- x[io] * RAD_TO_DEG,
- y[io] * RAD_TO_DEG );
- }
- }
- }
-
- return 0;
-}
-
-
-/************************************************************************/
-/* pj_datum_transform() */
-/* */
-/* The input should be long/lat/z coordinates in radians in the */
-/* source datum, and the output should be long/lat/z */
-/* coordinates in radians in the destination datum. */
-/************************************************************************/
-
-int pj_datum_transform( PJ *src, PJ *dst,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- double src_a, src_es, dst_a, dst_es;
- int z_is_temp = FALSE;
-
-/* -------------------------------------------------------------------- */
-/* We cannot do any meaningful datum transformation if either */
-/* the source or destination are of an unknown datum type */
-/* (ie. only a +ellps declaration, no +datum). This is new */
-/* behavior for PROJ 4.6.0. */
-/* -------------------------------------------------------------------- */
- if( src->datum_type == PJD_UNKNOWN
- || dst->datum_type == PJD_UNKNOWN )
- return 0;
-
-/* -------------------------------------------------------------------- */
-/* Short cut if the datums are identical. */
-/* -------------------------------------------------------------------- */
- if( pj_compare_datums( src, dst ) )
- return 0;
-
- src_a = src->a_orig;
- src_es = src->es_orig;
-
- dst_a = dst->a_orig;
- dst_es = dst->es_orig;
-
-/* -------------------------------------------------------------------- */
-/* Create a temporary Z array if one is not provided. */
-/* -------------------------------------------------------------------- */
- if( z == nullptr )
- {
- size_t bytes = sizeof(double) * point_count * point_offset;
- z = (double *) pj_malloc(bytes);
- memset( z, 0, bytes );
- z_is_temp = TRUE;
- }
-
-#define CHECK_RETURN(defn) {if( defn->ctx->last_errno != 0 && (defn->ctx->last_errno > 0 || get_transient_error_value(-defn->ctx->last_errno) == 0) ) { if( z_is_temp ) pj_dalloc(z); return defn->ctx->last_errno; }}
-
-/* -------------------------------------------------------------------- */
-/* If this datum requires grid shifts, then apply it to geodetic */
-/* coordinates. */
-/* -------------------------------------------------------------------- */
- if( src->datum_type == PJD_GRIDSHIFT )
- {
- pj_apply_gridshift_2( src, 0, point_count, point_offset, x, y, z );
- CHECK_RETURN(src);
-
- src_a = SRS_WGS84_SEMIMAJOR;
- src_es = SRS_WGS84_ESQUARED;
- }
-
- if( dst->datum_type == PJD_GRIDSHIFT )
- {
- dst_a = SRS_WGS84_SEMIMAJOR;
- dst_es = SRS_WGS84_ESQUARED;
- }
-
-/* ==================================================================== */
-/* Do we need to go through geocentric coordinates? */
-/* ==================================================================== */
- if( src_es != dst_es || src_a != dst_a
- || src->datum_type == PJD_3PARAM
- || src->datum_type == PJD_7PARAM
- || dst->datum_type == PJD_3PARAM
- || dst->datum_type == PJD_7PARAM)
- {
-/* -------------------------------------------------------------------- */
-/* Convert to geocentric coordinates. */
-/* -------------------------------------------------------------------- */
- src->ctx->last_errno =
- pj_geodetic_to_geocentric( src_a, src_es,
- point_count, point_offset, x, y, z );
- CHECK_RETURN(src);
-
-/* -------------------------------------------------------------------- */
-/* Convert between datums. */
-/* -------------------------------------------------------------------- */
- if( src->datum_type == PJD_3PARAM
- || src->datum_type == PJD_7PARAM )
- {
- pj_geocentric_to_wgs84( src, point_count, point_offset,x,y,z);
- CHECK_RETURN(src);
- }
-
- if( dst->datum_type == PJD_3PARAM
- || dst->datum_type == PJD_7PARAM )
- {
- pj_geocentric_from_wgs84( dst, point_count,point_offset,x,y,z);
- CHECK_RETURN(dst);
- }
-
-/* -------------------------------------------------------------------- */
-/* Convert back to geodetic coordinates. */
-/* -------------------------------------------------------------------- */
- dst->ctx->last_errno =
- pj_geocentric_to_geodetic( dst_a, dst_es,
- point_count, point_offset, x, y, z );
- CHECK_RETURN(dst);
- }
-
-/* -------------------------------------------------------------------- */
-/* Apply grid shift to destination if required. */
-/* -------------------------------------------------------------------- */
- if( dst->datum_type == PJD_GRIDSHIFT )
- {
- pj_apply_gridshift_2( dst, 1, point_count, point_offset, x, y, z );
- CHECK_RETURN(dst);
- }
-
- if( z_is_temp )
- pj_dalloc( z );
-
- return 0;
-}
-
-/************************************************************************/
-/* adjust_axis() */
-/* */
-/* Normalize or de-normalized the x/y/z axes. The normal form */
-/* is "enu" (easting, northing, up). */
-/************************************************************************/
-static int adjust_axis( projCtx ctx,
- const char *axis, int denormalize_flag,
- long point_count, int point_offset,
- double *x, double *y, double *z )
-
-{
- double x_in, y_in, z_in = 0.0;
- int i, i_axis;
-
- if( !denormalize_flag )
- {
- for( i = 0; i < point_count; i++ )
- {
- x_in = x[point_offset*i];
- y_in = y[point_offset*i];
- if( z )
- z_in = z[point_offset*i];
-
- for( i_axis = 0; i_axis < 3; i_axis++ )
- {
- double value;
-
- if( i_axis == 0 )
- value = x_in;
- else if( i_axis == 1 )
- value = y_in;
- else
- value = z_in;
-
- switch( axis[i_axis] )
- {
- case 'e':
- x[point_offset*i] = value;
- break;
- case 'w':
- x[point_offset*i] = -value;
- break;
- case 'n':
- y[point_offset*i] = value;
- break;
- case 's':
- y[point_offset*i] = -value;
- break;
- case 'u':
- if( z )
- z[point_offset*i] = value;
- break;
- case 'd':
- if( z )
- z[point_offset*i] = -value;
- break;
- default:
- pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
- return PJD_ERR_AXIS;
- }
- } /* i_axis */
- } /* i (point) */
- }
-
- else /* denormalize */
- {
- for( i = 0; i < point_count; i++ )
- {
- x_in = x[point_offset*i];
- y_in = y[point_offset*i];
- if( z )
- z_in = z[point_offset*i];
-
- for( i_axis = 0; i_axis < 3; i_axis++ )
- {
- double *target;
-
- if( i_axis == 2 && z == nullptr )
- continue;
-
- if( i_axis == 0 )
- target = x;
- else if( i_axis == 1 )
- target = y;
- else
- target = z;
-
- switch( axis[i_axis] )
- {
- case 'e':
- target[point_offset*i] = x_in; break;
- case 'w':
- target[point_offset*i] = -x_in; break;
- case 'n':
- target[point_offset*i] = y_in; break;
- case 's':
- target[point_offset*i] = -y_in; break;
- case 'u':
- target[point_offset*i] = z_in; break;
- case 'd':
- target[point_offset*i] = -z_in; break;
- default:
- pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
- return PJD_ERR_AXIS;
- }
- } /* i_axis */
- } /* i (point) */
- }
-
- return 0;
-}
-// ---------------------------------------------------------------------------
-
-void pj_deallocate_grids()
-{
-}
diff --git a/src/transformations/affine.cpp b/src/transformations/affine.cpp
index 28f73b9a..43fd8642 100644
--- a/src/transformations/affine.cpp
+++ b/src/transformations/affine.cpp
@@ -110,7 +110,7 @@ static PJ_LP reverse_2d(PJ_XY xy, PJ *P) {
}
static struct pj_opaque_affine * initQ() {
- struct pj_opaque_affine *Q = static_cast<struct pj_opaque_affine *>(pj_calloc(1, sizeof(struct pj_opaque_affine)));
+ struct pj_opaque_affine *Q = static_cast<struct pj_opaque_affine *>(calloc(1, sizeof(struct pj_opaque_affine)));
if (nullptr==Q)
return nullptr;
diff --git a/src/transformations/helmert.cpp b/src/transformations/helmert.cpp
index d3857d89..99aa74a4 100644
--- a/src/transformations/helmert.cpp
+++ b/src/transformations/helmert.cpp
@@ -476,7 +476,7 @@ static PJ_COORD helmert_reverse_4d (PJ_COORD point, PJ *P) {
static PJ* init_helmert_six_parameters(PJ* P) {
- struct pj_opaque_helmert *Q = static_cast<struct pj_opaque_helmert*>(pj_calloc (1, sizeof (struct pj_opaque_helmert)));
+ struct pj_opaque_helmert *Q = static_cast<struct pj_opaque_helmert*>(calloc (1, sizeof (struct pj_opaque_helmert)));
if (nullptr==Q)
return pj_default_destructor (P, ENOMEM);
P->opaque = (void *) Q;
diff --git a/src/transformations/horner.cpp b/src/transformations/horner.cpp
index a6638773..2c049186 100644
--- a/src/transformations/horner.cpp
+++ b/src/transformations/horner.cpp
@@ -89,8 +89,8 @@
PROJ_HEAD(horner, "Horner polynomial evaluation");
/* make horner.h interface with proj's memory management */
-#define horner_dealloc(x) pj_dealloc(x)
-#define horner_calloc(n,x) pj_calloc(n,x)
+#define horner_dealloc(x) free(x)
+#define horner_calloc(n,x) calloc(n,x)
namespace { // anonymous namespace
struct horner {
@@ -412,7 +412,7 @@ static int parse_coefs (PJ *P, double *coefs, const char *param, int ncoefs) {
char *buf, *init, *next = nullptr;
int i;
- buf = static_cast<char*>(pj_calloc (strlen (param) + 2, sizeof(char)));
+ buf = static_cast<char*>(calloc (strlen (param) + 2, sizeof(char)));
if (nullptr==buf) {
proj_log_error (P, "Horner: No memory left");
return 0;
@@ -420,12 +420,12 @@ static int parse_coefs (PJ *P, double *coefs, const char *param, int ncoefs) {
sprintf (buf, "t%s", param);
if (0==pj_param (P->ctx, P->params, buf).i) {
- pj_dealloc (buf);
+ free (buf);
return 0;
}
sprintf (buf, "s%s", param);
init = pj_param(P->ctx, P->params, buf).s;
- pj_dealloc (buf);
+ free (buf);
for (i = 0; i < ncoefs; i++) {
if (i > 0) {
diff --git a/src/transformations/molodensky.cpp b/src/transformations/molodensky.cpp
index 7d17f64c..bf5960d2 100644
--- a/src/transformations/molodensky.cpp
+++ b/src/transformations/molodensky.cpp
@@ -298,7 +298,7 @@ static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) {
PJ *TRANSFORMATION(molodensky,1) {
int count_required_params = 0;
- struct pj_opaque_molodensky *Q = static_cast<struct pj_opaque_molodensky*>(pj_calloc(1, sizeof(struct pj_opaque_molodensky)));
+ struct pj_opaque_molodensky *Q = static_cast<struct pj_opaque_molodensky*>(calloc(1, sizeof(struct pj_opaque_molodensky)));
if (nullptr==Q)
return pj_default_destructor(P, ENOMEM);
P->opaque = (void *) Q;
diff --git a/src/tsfn.cpp b/src/tsfn.cpp
index 32da09f2..8ed258d6 100644
--- a/src/tsfn.cpp
+++ b/src/tsfn.cpp
@@ -4,14 +4,28 @@
#include "proj_internal.h"
double pj_tsfn(double phi, double sinphi, double e) {
- double denominator;
- sinphi *= e;
+ /****************************************************************************
+ * Determine function ts(phi) defined in Snyder (1987), Eq. (7-10)
+ * Inputs:
+ * phi = geographic latitude (radians)
+ * e = eccentricity of the ellipsoid (dimensionless)
+ * Output:
+ * ts = exp(-psi) where psi is the isometric latitude (dimensionless)
+ * = 1 / (tan(chi) + sec(chi))
+ * Here isometric latitude is defined by
+ * psi = log( tan(pi/4 + phi/2) *
+ * ( (1 - e*sin(phi)) / (1 + e*sin(phi)) )^(e/2) )
+ * = asinh(tan(phi)) - e * atanh(e * sin(phi))
+ * = asinh(tan(chi))
+ * chi = conformal latitude
+ ***************************************************************************/
- /* avoid zero division, fail gracefully */
- denominator = 1.0 + sinphi;
- if (denominator == 0.0)
- return HUGE_VAL;
-
- return (tan (.5 * (M_HALFPI - phi)) /
- pow((1. - sinphi) / (denominator), .5 * e));
+ double cosphi = cos(phi);
+ // exp(-asinh(tan(phi))) = 1 / (tan(phi) + sec(phi))
+ // = cos(phi) / (1 + sin(phi)) good for phi > 0
+ // = (1 - sin(phi)) / cos(phi) good for phi < 0
+ return exp(e * atanh(e * sinphi)) *
+ ( sinphi > 0 ?
+ cosphi / (1 + sinphi) :
+ (1 - sinphi) / cosphi );
}
diff --git a/src/utils.cpp b/src/utils.cpp
deleted file mode 100644
index 9cb13f44..00000000
--- a/src/utils.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/******************************************************************************
- * Project: PROJ.4
- * Purpose: Some utility functions we don't want to bother putting in
- * their own source files.
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2001, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-#define PJ_LIB__
-
-#include <stdio.h>
-#include <string.h>
-
-#include "proj.h"
-#include "proj_internal.h"
-
-/************************************************************************/
-/* pj_is_latlong() */
-/* */
-/* Returns TRUE if this coordinate system object is */
-/* geographic. */
-/************************************************************************/
-
-int pj_is_latlong( PJ *pj )
-
-{
- return pj == nullptr || pj->is_latlong;
-}
-
-/************************************************************************/
-/* pj_is_geocent() */
-/* */
-/* Returns TRUE if this coordinate system object is geocentric. */
-/************************************************************************/
-
-int pj_is_geocent( PJ *pj )
-
-{
- return pj != nullptr && pj->is_geocent;
-}
-
-/************************************************************************/
-/* pj_latlong_from_proj() */
-/* */
-/* Return a PJ* definition defining the lat/long coordinate */
-/* system on which a projection is based. If the coordinate */
-/* system passed in is latlong, a clone of the same will be */
-/* returned. */
-/************************************************************************/
-
-PJ *pj_latlong_from_proj( PJ *pj_in )
-
-{
- char defn[512];
- int got_datum = FALSE;
-
- pj_errno = 0;
- strcpy( defn, "+proj=latlong" );
-
- if( pj_param(pj_in->ctx, pj_in->params, "tdatum").i )
- {
- got_datum = TRUE;
- sprintf( defn+strlen(defn), " +datum=%s",
- pj_param(pj_in->ctx, pj_in->params,"sdatum").s );
- }
- else if( pj_param(pj_in->ctx, pj_in->params, "tellps").i )
- {
- sprintf( defn+strlen(defn), " +ellps=%s",
- pj_param(pj_in->ctx, pj_in->params,"sellps").s );
- }
- else if( pj_param(pj_in->ctx,pj_in->params, "ta").i )
- {
- sprintf( defn+strlen(defn), " +a=%s",
- pj_param(pj_in->ctx,pj_in->params,"sa").s );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tb").i )
- sprintf( defn+strlen(defn), " +b=%s",
- pj_param(pj_in->ctx,pj_in->params,"sb").s );
- else if( pj_param(pj_in->ctx,pj_in->params, "tes").i )
- sprintf( defn+strlen(defn), " +es=%s",
- pj_param(pj_in->ctx,pj_in->params,"ses").s );
- else if( pj_param(pj_in->ctx,pj_in->params, "tf").i )
- sprintf( defn+strlen(defn), " +f=%s",
- pj_param(pj_in->ctx,pj_in->params,"sf").s );
- else
- {
- char* ptr = defn+strlen(defn);
- sprintf( ptr, " +es=%.16g", pj_in->es );
- /* TODO later: use C++ ostringstream with imbue(std::locale::classic()) */
- /* to be locale unaware */
- for(; *ptr; ptr++)
- {
- if( *ptr == ',' )
- *ptr = '.';
- }
- }
- }
- else
- {
- pj_ctx_set_errno( pj_in->ctx, PJD_ERR_MAJOR_AXIS_NOT_GIVEN );
-
- return nullptr;
- }
-
- if( !got_datum )
- {
- if( pj_param(pj_in->ctx,pj_in->params, "ttowgs84").i )
- sprintf( defn+strlen(defn), " +towgs84=%s",
- pj_param(pj_in->ctx,pj_in->params,"stowgs84").s );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tnadgrids").i )
- sprintf( defn+strlen(defn), " +nadgrids=%s",
- pj_param(pj_in->ctx,pj_in->params,"snadgrids").s );
- }
-
- /* copy over some other information related to ellipsoid */
- if( pj_param(pj_in->ctx,pj_in->params, "tR").i )
- sprintf( defn+strlen(defn), " +R=%s",
- pj_param(pj_in->ctx,pj_in->params,"sR").s );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tR_A").i )
- sprintf( defn+strlen(defn), " +R_A" );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tR_V").i )
- sprintf( defn+strlen(defn), " +R_V" );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tR_a").i )
- sprintf( defn+strlen(defn), " +R_a" );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_a").i )
- sprintf( defn+strlen(defn), " +R_lat_a=%s",
- pj_param(pj_in->ctx,pj_in->params,"sR_lat_a").s );
-
- if( pj_param(pj_in->ctx,pj_in->params, "tR_lat_g").i )
- sprintf( defn+strlen(defn), " +R_lat_g=%s",
- pj_param(pj_in->ctx,pj_in->params,"sR_lat_g").s );
-
- /* copy over prime meridian */
- if( pj_param(pj_in->ctx,pj_in->params, "tpm").i )
- sprintf( defn+strlen(defn), " +pm=%s",
- pj_param(pj_in->ctx,pj_in->params,"spm").s );
-
- return pj_init_plus_ctx( pj_in->ctx, defn );
-}
-
-/************************************************************************/
-/* pj_get_spheroid_defn() */
-/* */
-/* Fetch the internal definition of the spheroid. Note that */
-/* you can compute "b" from eccentricity_squared as: */
-/* */
-/* b = a * sqrt(1 - es) */
-/************************************************************************/
-
-void pj_get_spheroid_defn(projPJ defn, double *major_axis, double *eccentricity_squared)
-{
- if ( major_axis )
- *major_axis = defn->a;
-
- if ( eccentricity_squared )
- *eccentricity_squared = defn->es;
-}
diff --git a/src/wkt2_generated_parser.c b/src/wkt2_generated_parser.c
index feb2cc6b..f7bb5798 100644
--- a/src/wkt2_generated_parser.c
+++ b/src/wkt2_generated_parser.c
@@ -542,16 +542,16 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 106
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 3132
+#define YYLAST 3219
/* YYNTOKENS -- Number of terminals. */
#define YYNTOKENS 164
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 353
/* YYNRULES -- Number of rules. */
-#define YYNRULES 694
+#define YYNRULES 695
/* YYNSTATES -- Number of states. */
-#define YYNSTATES 1427
+#define YYNSTATES 1429
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
@@ -658,30 +658,30 @@ static const yytype_uint16 yyrline[] =
997, 1003, 1003, 1007, 1007, 1008, 1008, 1010, 1015, 1016,
1017, 1018, 1019, 1021, 1027, 1032, 1038, 1040, 1042, 1044,
1048, 1054, 1055, 1056, 1058, 1060, 1062, 1066, 1066, 1068,
- 1070, 1075, 1076, 1078, 1080, 1082, 1084, 1088, 1088, 1090,
- 1096, 1103, 1103, 1106, 1113, 1114, 1115, 1116, 1117, 1119,
- 1123, 1125, 1127, 1127, 1131, 1136, 1136, 1136, 1140, 1145,
- 1145, 1147, 1151, 1151, 1155, 1160, 1162, 1166, 1166, 1170,
- 1175, 1177, 1181, 1182, 1183, 1184, 1185, 1187, 1187, 1189,
- 1192, 1194, 1194, 1196, 1198, 1200, 1204, 1210, 1211, 1212,
- 1213, 1215, 1217, 1221, 1226, 1228, 1231, 1236, 1240, 1246,
- 1246, 1246, 1246, 1246, 1246, 1250, 1255, 1257, 1262, 1262,
- 1263, 1265, 1265, 1267, 1274, 1274, 1276, 1283, 1283, 1285,
- 1292, 1299, 1304, 1305, 1306, 1308, 1314, 1319, 1327, 1333,
- 1335, 1337, 1343, 1345, 1345, 1346, 1346, 1350, 1356, 1356,
- 1358, 1363, 1369, 1374, 1380, 1385, 1390, 1396, 1401, 1406,
- 1412, 1417, 1422, 1428, 1428, 1429, 1429, 1430, 1430, 1431,
- 1431, 1432, 1432, 1433, 1433, 1436, 1436, 1438, 1439, 1440,
- 1442, 1444, 1448, 1451, 1451, 1454, 1455, 1456, 1458, 1462,
- 1463, 1465, 1467, 1467, 1468, 1468, 1469, 1469, 1469, 1470,
- 1471, 1471, 1472, 1472, 1473, 1473, 1475, 1475, 1476, 1476,
- 1477, 1478, 1478, 1482, 1486, 1487, 1490, 1495, 1496, 1497,
- 1498, 1499, 1500, 1501, 1503, 1505, 1507, 1510, 1512, 1514,
- 1516, 1518, 1520, 1522, 1524, 1526, 1528, 1533, 1537, 1538,
- 1541, 1546, 1547, 1548, 1549, 1550, 1552, 1557, 1562, 1563,
- 1566, 1572, 1572, 1572, 1572, 1574, 1575, 1576, 1577, 1579,
- 1581, 1586, 1592, 1594, 1599, 1600, 1603, 1609, 1609, 1611,
- 1612, 1613, 1614, 1616, 1618
+ 1070, 1075, 1076, 1077, 1079, 1081, 1083, 1085, 1089, 1089,
+ 1091, 1097, 1104, 1104, 1107, 1114, 1115, 1116, 1117, 1118,
+ 1120, 1124, 1126, 1128, 1128, 1132, 1137, 1137, 1137, 1141,
+ 1146, 1146, 1148, 1152, 1152, 1156, 1161, 1163, 1167, 1167,
+ 1171, 1176, 1178, 1182, 1183, 1184, 1185, 1186, 1188, 1188,
+ 1190, 1193, 1195, 1195, 1197, 1199, 1201, 1205, 1211, 1212,
+ 1213, 1214, 1216, 1218, 1222, 1227, 1229, 1232, 1237, 1241,
+ 1247, 1247, 1247, 1247, 1247, 1247, 1251, 1256, 1258, 1263,
+ 1263, 1264, 1266, 1266, 1268, 1275, 1275, 1277, 1284, 1284,
+ 1286, 1293, 1300, 1305, 1306, 1307, 1309, 1315, 1320, 1328,
+ 1334, 1336, 1338, 1344, 1346, 1346, 1347, 1347, 1351, 1357,
+ 1357, 1359, 1364, 1370, 1375, 1381, 1386, 1391, 1397, 1402,
+ 1407, 1413, 1418, 1423, 1429, 1429, 1430, 1430, 1431, 1431,
+ 1432, 1432, 1433, 1433, 1434, 1434, 1437, 1437, 1439, 1440,
+ 1441, 1443, 1445, 1449, 1452, 1452, 1455, 1456, 1457, 1459,
+ 1463, 1464, 1466, 1468, 1468, 1469, 1469, 1470, 1470, 1470,
+ 1471, 1472, 1472, 1473, 1473, 1474, 1474, 1476, 1476, 1477,
+ 1477, 1478, 1479, 1479, 1483, 1487, 1488, 1491, 1496, 1497,
+ 1498, 1499, 1500, 1501, 1502, 1504, 1506, 1508, 1511, 1513,
+ 1515, 1517, 1519, 1521, 1523, 1525, 1527, 1529, 1534, 1538,
+ 1539, 1542, 1547, 1548, 1549, 1550, 1551, 1553, 1558, 1563,
+ 1564, 1567, 1573, 1573, 1573, 1573, 1575, 1576, 1577, 1578,
+ 1580, 1582, 1587, 1593, 1595, 1600, 1601, 1604, 1610, 1610,
+ 1612, 1613, 1614, 1615, 1617, 1619
};
#endif
@@ -933,7 +933,7 @@ static const yytype_uint16 yytoknum[] =
#define yypact_value_is_default(Yystate) \
(!!((Yystate) == (-1232)))
-#define YYTABLE_NINF -633
+#define YYTABLE_NINF -634
#define yytable_value_is_error(Yytable_value) \
0
@@ -942,149 +942,149 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int16 yypact[] =
{
- 2573, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
+ 1574, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
-1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
-1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -1232, -1232, -1232, 114, -1232, -1232,
- -1232, 231, -1232, -1232, -1232, 231, -1232, -1232, -1232, -1232,
- -1232, -1232, 231, 231, -1232, 231, -1232, -75, 231, -1232,
- 231, -1232, 231, -1232, -1232, -1232, 231, -1232, 231, -1232,
- 231, -1232, 231, -1232, 231, -1232, 231, -1232, 231, -1232,
- 231, -1232, -1232, -1232, -1232, -1232, -1232, -1232, 231, -1232,
- -1232, -1232, -1232, -1232, -1232, 231, -1232, 231, -1232, 231,
- -1232, 231, -1232, 231, -1232, 231, -1232, -1232, -1232, 33,
- 33, 33, 33, 33, -1232, 81, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 33, 33, 879,
- 33, 33, 33, 117, -1232, -1232, -75, -1232, -75, -1232,
- -75, -75, -1232, -75, -1232, -1232, -1232, 231, -1232, -75,
- -75, -1232, -75, -75, -75, -75, -75, -75, -75, -75,
- -75, -1232, -75, -1232, -75, -1232, -1232, -1232, -1232, 28,
- -1232, -1232, -1232, -1232, -1232, 97, 168, 186, -1232, -1232,
- -1232, -1232, 284, -1232, -75, -1232, -75, -75, -75, -1232,
- -75, 231, 1038, 176, 66, 66, 713, 33, 287, 179,
- 157, 766, 290, 284, 244, 284, 413, 284, 105, 286,
- 284, 297, 1406, -1232, -1232, -1232, 428, 101, -1232, -1232,
- 101, -1232, -1232, 101, -1232, -1232, 331, 879, -1232, -1232,
- -1232, -1232, -1232, -1232, -1232, 728, -1232, -1232, -1232, -1232,
- 265, 278, 293, 713, -1232, -75, -1232, -75, 231, -1232,
- -1232, -1232, -1232, 231, -75, 231, -75, -1232, 231, 231,
- -75, -75, -1232, -1232, -1232, -1232, -75, -75, -75, -75,
- -1232, -75, -1232, -75, -75, -75, -1232, -1232, -1232, -1232,
- 231, 231, -1232, -1232, -75, 231, -1232, -1232, 231, -75,
- -75, -1232, -75, -1232, -1232, 231, -1232, -75, -75, 231,
- -1232, -1232, -75, -75, 231, -1232, -1232, -75, -75, 231,
- -1232, -1232, -75, -75, 231, -1232, -1232, -75, -75, 231,
- -75, 231, -1232, -1232, -75, 231, -1232, -75, -1232, -1232,
- -1232, -1232, 231, -1232, -75, 231, -75, -75, -75, -75,
- -75, -1232, -75, 231, 284, -1232, 476, 728, -1232, -1232,
- 387, 284, 283, 284, 284, 33, 33, 59, 404, 258,
- 33, 33, 441, 441, 59, 258, 441, 441, 713, 476,
- 284, 452, 33, 33, 349, 284, 33, 33, 88, 477,
- 441, 33, 479, -1232, 479, 33, 477, 441, 33, 477,
- 441, 33, 477, 441, 33, -1232, -1232, 682, 74, -1232,
- 33, 441, 33, 1406, 728, 117, -1232, 33, 331, 117,
- -1232, 487, 117, -1232, 331, 469, 879, -1232, 728, -1232,
- -1232, -1232, -1232, -1232, -1232, -1232, -1232, -75, -75, 231,
- -1232, 231, -1232, -1232, -75, -75, 231, -75, -1232, -1232,
- -1232, -75, -75, -75, -1232, -75, 231, -1232, -1232, -1232,
- -1232, -1232, -1232, 231, 284, -75, -1232, -75, -75, -1232,
- -75, 231, -75, -75, 284, -75, -75, -1232, -75, -75,
- 713, 284, -1232, -75, -75, -75, -1232, -75, -75, 231,
- -1232, -1232, -75, -75, -75, 231, 284, -75, -75, -75,
- -75, -1232, 284, 284, -75, -75, 284, -75, -75, 284,
- -75, -75, -1232, -1232, 116, -1232, 284, -75, -1232, 284,
- -75, -75, -75, 293, 284, -1232, 284, -75, -1232, -75,
- 231, -75, -1232, -75, 231, 284, -1232, 488, 511, 33,
- 33, -1232, -1232, 479, -1232, 1192, 486, 479, 284, 176,
- 258, 614, 284, 728, 1482, -1232, 477, 56, 56, 477,
- 33, 477, 258, -1232, 477, 477, 148, 284, 345, -1232,
- -1232, -1232, 477, 56, 56, -1232, -1232, 33, 284, 176,
- 477, 1503, -1232, 477, 277, -1232, -1232, -1232, -1232, 477,
- -1, -1232, 477, -2, -1232, 477, 22, -1232, -1232, 728,
- -1232, -1232, 728, -1232, -1232, -1232, 477, 179, 1669, 284,
- 728, -1232, -1232, 487, 1210, 284, 33, 523, 1412, 284,
- 33, -1232, -75, -1232, -1232, 284, -1232, 284, -1232, -75,
- -1232, 284, -75, -1232, -75, -1232, -75, 284, -1232, -1232,
- -1232, 231, -1232, 293, 284, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -75, -1232, -1232, -1232, -1232, -75,
- -75, -75, -1232, -75, -75, -75, -75, 284, -1232, -75,
- 284, 284, 284, 284, -1232, -1232, -75, -75, 231, -1232,
- -1232, -1232, -75, 231, 284, -75, -75, -75, -75, -1232,
- -75, -1232, -75, 284, -75, 284, -75, -75, 284, -75,
- 284, -75, 284, -75, 159, 401, -1232, 767, 284, -1232,
- -1232, -1232, -1232, -75, -1232, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -1232, -75, 231, -75, 231, -1232,
- -75, 231, -75, 231, -75, 231, -75, 231, -75, -1232,
- 231, -75, -1232, -1232, -75, -1232, -1232, -1232, 231, -75,
- -75, 231, -75, 231, -1232, -1232, -75, -1232, 231, -1232,
- -1232, -75, 511, -1232, -1232, -1232, -1232, -1232, -1232, 257,
- -1232, 33, 728, -1232, 586, 586, 586, 586, 59, 196,
- 284, 59, 284, -1232, 487, -1232, -1232, -1232, -1232, -1232,
- -1232, 33, -1232, 33, -1232, 59, 141, 284, 59, 284,
- 476, 631, -1232, 586, -1232, 88, 284, -1232, 284, -1232,
- 284, -1232, 284, -1232, 728, -1232, -1232, 728, 728, -1232,
- 415, -1232, -1232, -1232, -1232, 452, 145, 548, 528, -1232,
- 33, 547, -1232, 33, 322, -1232, 1192, 325, -1232, 1192,
- 267, -1232, 682, -1232, 439, -1232, 980, 284, 33, -1232,
- -1232, 33, -1232, 1192, 479, 284, 282, 42, -1232, -1232,
- -1232, -75, -1232, -75, -1232, -1232, -1232, -1232, -75, -75,
- -75, -75, -75, -75, -75, -1232, -75, -1232, -75, -1232,
- -75, -75, -75, -75, -1232, -75, -75, -1232, -75, -1232,
- -1232, -75, -75, -75, -75, -1232, -1232, -1232, -1232, -1232,
- 433, 415, -1232, 767, 728, -1232, -75, -1232, -75, -1232,
- -75, -1232, -75, -1232, -1232, 284, -75, -75, -75, -1232,
- 284, -75, -75, -1232, -75, -75, -1232, -75, -1232, -1232,
- -75, -1232, 284, -1232, -1232, -75, -75, -75, 231, -75,
- -1232, -75, -75, 284, -1232, -1232, -1232, -1232, -1232, -1232,
- 284, -75, -75, 284, 284, 284, 284, 284, 284, -1232,
- -1232, 284, 259, 284, 713, 713, 284, -1232, 345, -1232,
- -1232, 284, 456, 284, 284, 284, -1232, -1232, 728, -1232,
- -1232, -1232, 284, -1232, 212, -1232, -1232, 322, -1232, 325,
- -1232, -1232, -1232, 325, -1232, -1232, 1192, -1232, 1192, 682,
- -1232, -1232, -1232, 1052, -1232, 879, -1232, 476, 33, -1232,
- -75, 167, 487, -1232, -1232, -75, -75, -75, -75, -1232,
- -1232, -75, -75, -75, -1232, -1232, -75, -75, -1232, -75,
- -1232, -1232, -1232, -1232, -1232, -1232, 231, -75, -1232, -75,
- -1232, -1232, -1232, 1008, -1232, 284, -75, -75, -75, -1232,
- -75, -75, -75, -75, -1232, -75, -1232, -75, -1232, -1232,
- 284, -75, 284, -75, -1232, -75, 523, 231, -1232, -75,
- -1232, 595, 595, 595, 595, -1232, -1232, -1232, 284, 284,
- -1232, 33, -1232, 595, 1080, -1232, -1232, 315, 622, 553,
- 325, -1232, -1232, -1232, -1232, 1192, 376, 284, -1232, -1232,
- -1232, 775, 284, 231, 33, 1141, 284, -1232, -75, 231,
- -75, 231, -75, -75, 231, -1232, -1232, -75, -75, 525,
- 1080, -1232, -75, -75, -1232, -75, -1232, -1232, -75, -1232,
- -75, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -75,
- -1232, 231, -1232, 282, -75, -1232, -75, -75, -1232, 696,
- -1232, 33, 688, -1232, 33, -1232, 974, -1232, 33, 713,
- 1086, -1232, -1232, 622, 553, 553, -1232, 1192, 284, 33,
- 284, 476, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -1232, 231, -1232, 231, -75, -1232,
- -75, -1232, -75, -75, -75, -1232, -75, -75, -75, -1232,
- -1232, -75, -75, 231, -75, -1232, -1232, -1232, -1232, 284,
- -1232, -75, -75, -75, 33, 33, 1412, 2101, -1232, -1232,
- 2559, -1232, 2630, 284, 478, -1232, -1232, 33, 553, -1232,
- 713, 284, 1469, 284, 284, -75, -75, -1232, -1232, -1232,
+ -1232, -1232, -1232, -1232, -1232, -1232, -1232, 62, -1232, -1232,
+ -1232, 98, -1232, -1232, -1232, 98, -1232, -1232, -1232, -1232,
+ -1232, -1232, 98, 98, -1232, 98, -1232, -87, 98, -1232,
+ 98, -1232, 98, -1232, -1232, -1232, 98, -1232, 98, -1232,
+ 98, -1232, 98, -1232, 98, -1232, 98, -1232, 98, -1232,
+ 98, -1232, -1232, -1232, -1232, -1232, -1232, -1232, 98, -1232,
+ -1232, -1232, -1232, -1232, -1232, 98, -1232, 98, -1232, 98,
+ -1232, 98, -1232, 98, -1232, 98, -1232, -1232, -1232, -24,
+ -24, -24, -24, -24, -1232, 83, -24, -24, -24, -24,
+ -24, -24, -24, -24, -24, -24, -24, -24, -24, 810,
+ -24, -24, -24, 113, -1232, -1232, -87, -1232, -87, -1232,
+ -87, -87, -1232, -87, -1232, -1232, -1232, 98, -1232, -87,
+ -87, -1232, -87, -87, -87, -87, -87, -87, -87, -87,
+ -87, -1232, -87, -1232, -87, -1232, -1232, -1232, -1232, 26,
+ -1232, -1232, -1232, -1232, -1232, 37, 52, 179, -1232, -1232,
+ -1232, -1232, 360, -1232, -87, -1232, -87, -87, -87, -1232,
+ -87, 98, 1048, 212, 59, 59, 761, -24, 256, 138,
+ 156, 467, 304, 360, 203, 360, 322, 360, 217, 314,
+ 360, 275, 1439, -1232, -1232, -1232, 483, 69, -1232, -1232,
+ 69, -1232, -1232, 69, -1232, -1232, 335, 810, -1232, -1232,
+ -1232, -1232, -1232, -1232, -1232, 462, -1232, -1232, -1232, -1232,
+ 252, 265, 287, 761, -1232, -87, -1232, -87, 98, -1232,
+ -1232, -1232, -1232, 98, -87, 98, -87, -1232, 98, 98,
+ -87, -87, -1232, -1232, -1232, -1232, -87, -87, -87, -87,
+ -1232, -87, -1232, -87, -87, -87, -1232, -1232, -1232, -1232,
+ 98, 98, -1232, -1232, -87, 98, -1232, -1232, 98, -87,
+ -87, -1232, -87, -1232, -1232, 98, -1232, -87, -87, 98,
+ -1232, -1232, -87, -87, 98, -1232, -1232, -87, -87, 98,
+ -1232, -1232, -87, -87, 98, -1232, -1232, -87, -87, 98,
+ -87, 98, -1232, -1232, -87, 98, -1232, -87, -1232, -1232,
+ -1232, -1232, 98, -1232, -87, 98, -87, -87, -87, -87,
+ -87, -1232, -87, 98, 360, -1232, 416, 462, -1232, -1232,
+ 558, 360, 75, 360, 360, -24, -24, 78, 390, 102,
+ -24, -24, 413, 413, 78, 102, 413, 413, 761, 416,
+ 360, 466, -24, -24, 364, 360, -24, -24, 89, 477,
+ 413, -24, 488, -1232, 488, -24, 477, 413, -24, 477,
+ 413, -24, 477, 413, -24, -1232, -1232, 387, 104, -1232,
+ -24, 413, -24, 1439, 462, 113, -1232, -24, 335, 113,
+ -1232, 499, 113, -1232, 335, 461, 810, -1232, 462, -1232,
+ -1232, -1232, -1232, -1232, -1232, -1232, -1232, -87, -87, 98,
+ -1232, 98, -1232, -1232, -87, -87, 98, -87, -1232, -1232,
+ -1232, -87, -87, -87, -1232, -87, 98, -1232, -1232, -1232,
+ -1232, -1232, -1232, 98, 360, -87, -1232, -87, -87, -1232,
+ -87, 98, -87, -87, 360, -87, -87, -1232, -87, -87,
+ 761, 360, -1232, -87, -87, -87, -1232, -87, -87, 98,
+ -1232, -1232, -87, -87, -87, 98, 360, -87, -87, -87,
+ -87, -1232, 360, 360, -87, -87, 360, -87, -87, 360,
+ -87, -87, -1232, -1232, 159, -1232, 360, -87, -1232, 360,
+ -87, -87, -87, 287, 360, -1232, 360, -87, -1232, -87,
+ 98, -87, -1232, -87, 98, 360, -1232, 481, 486, -24,
+ -24, -1232, -1232, 488, -1232, 823, 479, 488, 360, 212,
+ 102, 517, 360, 462, 1699, -1232, 477, 112, 112, 477,
+ -24, 477, 102, -1232, 477, 477, 329, 360, 306, -1232,
+ -1232, -1232, 477, 112, 112, -1232, -1232, -24, 360, 212,
+ 477, 940, -1232, 477, 243, -1232, -1232, -1232, -1232, 477,
+ 108, -1232, 477, 192, -1232, 477, 25, -1232, -1232, 462,
+ -1232, -1232, 462, -1232, -1232, -1232, 477, 138, 1409, 360,
+ 462, -1232, -1232, 499, 1212, 360, -24, 498, 1047, 360,
+ -24, -1232, -87, -1232, -1232, 360, -1232, 360, -1232, -87,
+ -1232, 360, -87, -1232, -87, -1232, -87, 360, -1232, -1232,
+ -1232, 98, -1232, 287, 360, -1232, -1232, -1232, -1232, -1232,
+ -1232, -1232, -1232, -1232, -87, -1232, -1232, -1232, -1232, -87,
+ -87, -87, -1232, -87, -87, -87, -87, 360, -1232, -87,
+ 360, 360, 360, 360, -1232, -1232, -87, -87, 98, -1232,
+ -1232, -1232, -87, 98, 360, -87, -87, -87, -87, -1232,
+ -87, -1232, -87, 360, -87, 360, -87, -87, 360, -87,
+ 360, -87, 360, -87, 205, 427, -1232, 497, 360, -1232,
+ -1232, -1232, -1232, -87, -1232, -1232, -1232, -1232, -1232, -1232,
+ -1232, -1232, -1232, -1232, -1232, -87, 98, -87, 98, -1232,
+ -87, 98, -87, 98, -87, 98, -87, 98, -87, -1232,
+ 98, -87, -1232, -1232, -87, -1232, -1232, -1232, 98, -87,
+ -87, 98, -87, 98, -1232, -1232, -87, -1232, 98, -1232,
+ -1232, -87, 486, -1232, -1232, -1232, -1232, -1232, -1232, 117,
+ -1232, -24, 462, -1232, 398, 398, 398, 398, 78, 100,
+ 360, 78, 360, -1232, 499, -1232, -1232, -1232, -1232, -1232,
+ -1232, -24, -1232, -24, -1232, 78, 58, 360, 78, 360,
+ 416, 518, -1232, 398, -1232, 89, 360, -1232, 360, -1232,
+ 360, -1232, 360, -1232, 462, -1232, -1232, 462, 462, -1232,
+ 430, -1232, -1232, -1232, -1232, 466, 176, 566, 530, -1232,
+ -24, 547, -1232, -24, 425, -1232, 823, 281, -1232, 823,
+ 333, -1232, 387, -1232, 469, -1232, 1134, 360, -24, -1232,
+ -1232, -24, -1232, 823, 488, 360, 267, 47, -1232, -1232,
+ -1232, -87, -1232, -87, -1232, -1232, -1232, -1232, -87, -87,
+ -87, -87, -87, -87, -87, -1232, -87, -1232, -87, -1232,
+ -87, -87, -87, -87, -1232, -87, -87, -1232, -87, -1232,
+ -1232, -87, -87, -87, -87, -1232, -1232, -1232, -1232, -1232,
+ 465, 430, -1232, 497, 462, -1232, -87, -1232, -87, -1232,
+ -87, -1232, -87, -1232, -1232, 360, -87, -87, -87, -1232,
+ 360, -87, -87, -1232, -87, -87, -1232, -87, -1232, -1232,
+ -87, -1232, 360, -1232, -1232, -87, -87, -87, 98, -87,
+ -1232, -87, -87, 360, -1232, -1232, -1232, -1232, -1232, -1232,
+ 360, -87, -87, 360, 360, 360, 360, 360, 360, -1232,
+ -1232, 360, 103, 360, 761, 761, 360, -1232, 306, -1232,
+ -1232, 360, 746, 360, 360, 360, -1232, -1232, 462, -1232,
+ -1232, -1232, 360, -1232, 338, -1232, -1232, 425, -1232, 281,
+ -1232, -1232, -1232, 281, -1232, -1232, 823, -1232, 823, 387,
+ -1232, -1232, -1232, 1054, -1232, 810, -1232, 416, -24, -1232,
+ -87, 168, 499, -1232, -1232, -87, -87, -87, -87, -1232,
+ -1232, -87, -87, -87, -1232, -1232, -87, -87, -1232, -87,
+ -1232, -1232, -1232, -1232, -1232, -87, -1232, 98, -87, -1232,
+ -87, -1232, -1232, -1232, 681, -1232, 360, -87, -87, -87,
+ -1232, -87, -87, -87, -87, -1232, -87, -1232, -87, -1232,
+ -1232, 360, -87, 360, -87, -1232, -87, 498, 98, -1232,
+ -87, -1232, 623, 623, 623, 623, -1232, -1232, -1232, 360,
+ 360, -1232, -1232, -24, -1232, 623, 811, -1232, -1232, 199,
+ 535, 579, 281, -1232, -1232, -1232, -1232, 823, 372, 360,
+ -1232, -1232, -1232, 297, 360, 98, -24, 1415, 360, -1232,
+ -87, 98, -87, 98, -87, -87, 98, -1232, -1232, -87,
+ -87, 370, 811, -1232, -87, -87, -1232, -87, -1232, -1232,
+ -87, -1232, -87, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
+ -1232, -87, -1232, 98, -1232, 267, -87, -1232, -87, -87,
+ -1232, 1348, -1232, -24, 1001, -1232, -24, -1232, 711, -1232,
+ -24, 761, 1104, -1232, -1232, 535, 579, 579, -1232, 823,
+ 360, -24, 360, 416, -1232, -1232, -1232, -1232, -1232, -1232,
+ -1232, -1232, -1232, -1232, -1232, -1232, -1232, 98, -1232, 98,
+ -87, -1232, -87, -1232, -87, -87, -87, -1232, -87, -87,
+ -87, -1232, -1232, -87, -87, 98, -87, -1232, -1232, -1232,
+ -1232, 360, -1232, -87, -87, -87, -24, -24, 1047, 2503,
+ -1232, -1232, 2115, -1232, 2716, 360, 1527, -1232, -1232, -24,
+ 579, -1232, 761, 360, 1340, 360, 360, -87, -87, -1232,
-1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
-1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
-1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -75, -75, -75, -75, -75, 284,
- -1232, -75, -75, -75, -75, -75, 284, -1232, -75, -1232,
- -75, -1232, -75, -1232, -75, -1232, -1232, -75, 231, -1232,
- -1232, 713, 284, 55, 284, 563, 563, 723, 723, -1232,
- 741, 457, 563, 593, 593, -1232, 530, -1232, 284, -1232,
- -1232, 282, -75, -1232, -1232, -75, -75, -1232, -75, 231,
- -1232, -1232, -75, -75, -1232, -75, 231, -75, -1232, -1232,
- -75, -75, -1232, -75, 231, -75, -1232, -75, -75, -1232,
- -75, -75, -1232, -75, -75, -1232, -75, -1232, -75, -75,
- -1232, -75, -1232, -75, -1232, 284, 284, -1232, -1232, 92,
- -1232, 728, -1232, -1232, 741, -1232, 1192, 763, -1232, -1232,
- -1232, 741, -1232, 1192, 763, -1232, -1232, -1232, 763, -1232,
- -1232, 530, -1232, -1232, -1232, 530, -1232, -1232, -1232, -1232,
- -75, -1232, -75, 284, -75, -75, -75, -75, -75, -75,
- 284, -75, -75, -75, -75, -1232, -1232, -1232, -1232, 763,
- -1232, 577, -1232, -1232, 763, -1232, -1232, -1232, -1232, -1232,
- -1232, -75, 284, -75, -1232, -1232, -1232
+ -1232, -1232, -1232, -1232, -1232, -1232, -87, -87, -87, -87,
+ -87, 360, -1232, -87, -87, -87, -87, -87, 360, -1232,
+ -87, -1232, -87, -1232, -87, -1232, -87, -1232, -1232, -87,
+ 98, -1232, -1232, 761, 360, 272, 360, 679, 679, 710,
+ 710, -1232, 870, 412, 679, 494, 494, -1232, 336, -1232,
+ 360, -1232, -1232, 267, -87, -1232, -1232, -87, -87, -1232,
+ -87, 98, -1232, -1232, -87, -87, -1232, -87, 98, -87,
+ -1232, -1232, -87, -87, -1232, -87, 98, -87, -1232, -87,
+ -87, -1232, -87, -87, -1232, -87, -87, -1232, -87, -1232,
+ -87, -87, -1232, -87, -1232, -87, -1232, 360, 360, -1232,
+ -1232, 74, -1232, 462, -1232, -1232, 870, -1232, 823, 475,
+ -1232, -1232, -1232, 870, -1232, 823, 475, -1232, -1232, -1232,
+ 475, -1232, -1232, 336, -1232, -1232, -1232, 336, -1232, -1232,
+ -1232, -1232, -87, -1232, -87, 360, -87, -87, -87, -87,
+ -87, -87, 360, -87, -87, -87, -87, -1232, -1232, -1232,
+ -1232, 475, -1232, 438, -1232, -1232, 475, -1232, -1232, -1232,
+ -1232, -1232, -1232, -87, 360, -87, -1232, -1232, -1232
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -1092,190 +1092,190 @@ static const yytype_int16 yypact[] =
means the default is an error. */
static const yytype_uint16 yydefact[] =
{
- 0, 419, 406, 395, 405, 161, 431, 454, 397, 482,
- 485, 600, 644, 679, 682, 507, 500, 356, 559, 492,
- 489, 497, 495, 611, 666, 396, 421, 432, 398, 420,
- 483, 487, 486, 508, 493, 490, 498, 0, 4, 5,
- 2, 0, 13, 346, 347, 0, 583, 385, 383, 384,
- 386, 387, 0, 0, 3, 0, 12, 416, 0, 585,
- 0, 11, 0, 587, 467, 468, 0, 14, 0, 589,
- 0, 15, 0, 591, 0, 16, 0, 593, 0, 17,
- 0, 584, 540, 538, 539, 541, 542, 586, 0, 588,
- 590, 592, 594, 19, 18, 0, 7, 0, 8, 0,
+ 0, 419, 406, 395, 405, 161, 431, 454, 397, 483,
+ 486, 601, 645, 680, 683, 508, 501, 356, 560, 493,
+ 490, 498, 496, 612, 667, 396, 421, 432, 398, 420,
+ 484, 488, 487, 509, 494, 491, 499, 0, 4, 5,
+ 2, 0, 13, 346, 347, 0, 584, 385, 383, 384,
+ 386, 387, 0, 0, 3, 0, 12, 416, 0, 586,
+ 0, 11, 0, 588, 468, 469, 0, 14, 0, 590,
+ 0, 15, 0, 592, 0, 16, 0, 594, 0, 17,
+ 0, 585, 541, 539, 540, 542, 543, 587, 0, 589,
+ 591, 593, 595, 19, 18, 0, 7, 0, 8, 0,
9, 0, 10, 0, 6, 0, 1, 73, 74, 0,
0, 0, 0, 0, 77, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 78, 162, 0, 357, 0, 394,
0, 0, 407, 0, 411, 412, 417, 0, 422, 0,
0, 455, 0, 0, 423, 0, 423, 0, 423, 0,
- 502, 560, 0, 601, 0, 612, 626, 613, 627, 614,
- 615, 629, 616, 617, 618, 619, 620, 621, 622, 623,
- 624, 625, 0, 609, 0, 645, 0, 0, 0, 650,
+ 503, 561, 0, 602, 0, 613, 627, 614, 628, 615,
+ 616, 630, 617, 618, 619, 620, 621, 622, 623, 624,
+ 625, 626, 0, 610, 0, 646, 0, 0, 0, 651,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 75, 76, 608, 0, 0, 633, 635,
- 0, 657, 659, 0, 667, 669, 0, 0, 40, 20,
+ 0, 0, 0, 75, 76, 609, 0, 0, 634, 636,
+ 0, 658, 660, 0, 668, 670, 0, 0, 40, 20,
37, 38, 39, 41, 42, 0, 163, 21, 22, 26,
0, 25, 35, 0, 164, 154, 361, 0, 0, 446,
447, 369, 400, 0, 0, 0, 0, 399, 0, 0,
- 0, 0, 544, 547, 545, 548, 0, 0, 0, 0,
+ 0, 0, 545, 548, 546, 549, 0, 0, 0, 0,
408, 0, 413, 0, 423, 0, 433, 434, 435, 436,
- 0, 0, 458, 457, 451, 0, 572, 472, 0, 0,
- 0, 471, 0, 568, 569, 0, 428, 190, 424, 0,
- 484, 575, 0, 0, 0, 491, 578, 0, 0, 0,
- 496, 581, 0, 0, 0, 514, 510, 190, 190, 0,
- 190, 0, 501, 562, 0, 0, 595, 0, 596, 603,
- 604, 610, 0, 647, 0, 0, 0, 0, 0, 0,
- 0, 652, 0, 0, 0, 34, 27, 0, 33, 23,
+ 0, 0, 458, 457, 451, 0, 573, 473, 0, 0,
+ 0, 472, 0, 569, 570, 0, 428, 190, 424, 0,
+ 485, 576, 0, 0, 0, 492, 579, 0, 0, 0,
+ 497, 582, 0, 0, 0, 515, 511, 190, 190, 0,
+ 190, 0, 502, 563, 0, 0, 596, 0, 597, 604,
+ 605, 611, 0, 648, 0, 0, 0, 0, 0, 0,
+ 0, 653, 0, 0, 0, 34, 27, 0, 33, 23,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 27,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 425, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 506, 505, 0, 0, 503,
- 0, 0, 0, 0, 0, 0, 634, 0, 0, 0,
- 658, 0, 0, 668, 0, 0, 0, 649, 0, 29,
+ 0, 0, 0, 0, 0, 507, 506, 0, 0, 504,
+ 0, 0, 0, 0, 0, 0, 635, 0, 0, 0,
+ 659, 0, 0, 669, 0, 0, 0, 650, 0, 29,
31, 28, 36, 168, 171, 165, 166, 155, 158, 0,
160, 0, 153, 365, 0, 351, 0, 0, 348, 353,
362, 359, 0, 0, 371, 375, 0, 223, 393, 204,
- 205, 206, 207, 0, 0, 0, 448, 0, 0, 521,
+ 205, 206, 207, 0, 0, 0, 448, 0, 0, 522,
0, 0, 0, 0, 0, 0, 0, 409, 402, 190,
- 0, 0, 418, 0, 0, 0, 463, 190, 451, 0,
+ 0, 0, 418, 0, 0, 0, 464, 190, 451, 0,
450, 459, 190, 0, 0, 0, 0, 0, 0, 190,
190, 429, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 50, 511, 48, 512, 0, 190, 515, 0,
- 0, 0, 597, 605, 0, 648, 0, 0, 524, 661,
- 0, 0, 693, 80, 0, 0, 32, 0, 0, 0,
+ 0, 0, 50, 512, 48, 513, 0, 190, 516, 0,
+ 0, 0, 598, 606, 0, 649, 0, 0, 525, 662,
+ 0, 0, 694, 80, 0, 0, 32, 0, 0, 0,
0, 350, 355, 0, 354, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 388, 0, 0, 0, 0,
0, 0, 0, 390, 0, 0, 0, 0, 0, 415,
24, 410, 0, 0, 0, 452, 453, 0, 0, 0,
- 0, 0, 469, 0, 0, 191, 426, 427, 488, 0,
- 0, 494, 0, 0, 499, 0, 0, 44, 58, 0,
- 45, 49, 0, 509, 504, 513, 0, 0, 0, 0,
- 606, 602, 646, 0, 0, 0, 0, 0, 0, 0,
- 0, 651, 156, 159, 169, 0, 172, 0, 367, 351,
+ 0, 0, 470, 0, 0, 191, 426, 427, 489, 0,
+ 0, 495, 0, 0, 500, 0, 0, 44, 58, 0,
+ 45, 49, 0, 510, 505, 514, 0, 0, 0, 0,
+ 607, 603, 647, 0, 0, 0, 0, 0, 0, 0,
+ 0, 652, 156, 159, 169, 0, 172, 0, 367, 351,
366, 0, 351, 363, 359, 358, 0, 0, 380, 381,
376, 0, 368, 372, 0, 224, 225, 226, 227, 228,
229, 230, 231, 232, 0, 233, 234, 235, 236, 0,
- 0, 0, 392, 0, 552, 0, 552, 0, 522, 0,
+ 0, 0, 392, 0, 553, 0, 553, 0, 523, 0,
0, 0, 0, 0, 199, 198, 190, 190, 0, 401,
- 197, 196, 190, 0, 0, 0, 438, 0, 438, 464,
+ 197, 196, 190, 0, 0, 0, 438, 0, 438, 465,
0, 456, 0, 0, 0, 0, 0, 190, 0, 190,
- 0, 190, 0, 190, 48, 0, 59, 0, 0, 563,
- 564, 565, 566, 0, 174, 100, 133, 136, 144, 148,
- 98, 599, 82, 88, 89, 93, 0, 85, 0, 92,
+ 0, 190, 0, 190, 48, 0, 59, 0, 0, 564,
+ 565, 566, 567, 0, 174, 100, 133, 136, 144, 148,
+ 98, 600, 82, 88, 89, 93, 0, 85, 0, 92,
85, 0, 85, 0, 85, 0, 85, 0, 85, 84,
- 0, 597, 582, 607, 637, 536, 656, 665, 0, 661,
- 661, 0, 80, 0, 660, 525, 378, 680, 0, 81,
- 681, 0, 0, 167, 170, 352, 364, 349, 360, 0,
+ 0, 598, 583, 608, 638, 537, 657, 666, 0, 662,
+ 662, 0, 80, 0, 661, 526, 378, 681, 0, 81,
+ 682, 0, 0, 167, 170, 352, 364, 349, 360, 0,
389, 0, 373, 370, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 543, 0, 546, 391, 549, 550, 404,
+ 0, 0, 0, 544, 0, 547, 391, 550, 551, 404,
403, 0, 414, 0, 430, 0, 0, 0, 0, 0,
- 27, 0, 470, 0, 567, 0, 0, 573, 0, 576,
- 0, 579, 0, 46, 0, 43, 68, 0, 0, 53,
- 71, 55, 66, 67, 558, 0, 0, 0, 0, 91,
+ 27, 0, 471, 0, 568, 0, 0, 574, 0, 577,
+ 0, 580, 0, 46, 0, 43, 68, 0, 0, 53,
+ 71, 55, 66, 67, 559, 0, 0, 0, 0, 91,
0, 0, 117, 0, 0, 118, 0, 0, 119, 0,
- 0, 120, 0, 83, 0, 598, 0, 0, 0, 662,
- 663, 0, 664, 0, 0, 0, 0, 0, 683, 685,
+ 0, 120, 0, 83, 0, 599, 0, 0, 0, 663,
+ 664, 0, 665, 0, 0, 0, 0, 0, 684, 686,
157, 0, 382, 378, 374, 237, 238, 239, 190, 190,
- 190, 190, 552, 190, 190, 551, 552, 556, 517, 202,
+ 190, 190, 553, 190, 190, 552, 553, 557, 518, 202,
0, 0, 438, 190, 449, 190, 190, 437, 438, 444,
- 465, 461, 0, 190, 190, 570, 574, 577, 580, 52,
+ 466, 461, 0, 190, 190, 571, 575, 578, 581, 52,
48, 71, 60, 0, 0, 70, 190, 96, 85, 94,
0, 90, 85, 87, 101, 0, 85, 85, 85, 134,
0, 85, 85, 137, 0, 85, 145, 0, 149, 150,
- 0, 79, 0, 654, 643, 637, 637, 80, 0, 80,
- 636, 0, 0, 0, 379, 523, 673, 674, 671, 672,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 554,
- 553, 0, 0, 0, 0, 0, 0, 442, 0, 439,
+ 0, 79, 0, 655, 644, 638, 638, 80, 0, 80,
+ 637, 0, 0, 0, 379, 524, 674, 675, 672, 673,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 555,
+ 554, 0, 0, 0, 0, 0, 0, 442, 0, 439,
441, 0, 0, 0, 0, 0, 47, 69, 0, 54,
57, 72, 0, 95, 0, 86, 99, 0, 121, 0,
122, 123, 132, 0, 124, 125, 0, 126, 0, 0,
- 173, 638, 639, 0, 640, 0, 642, 27, 0, 655,
- 0, 0, 0, 684, 377, 0, 0, 0, 0, 555,
- 557, 190, 517, 517, 516, 203, 190, 190, 443, 190,
- 445, 188, 186, 185, 187, 466, 0, 190, 460, 0,
- 571, 64, 56, 0, 561, 0, 102, 103, 104, 105,
- 85, 85, 85, 85, 138, 0, 146, 142, 151, 152,
- 0, 80, 0, 0, 537, 378, 0, 0, 688, 689,
- 687, 0, 0, 0, 0, 520, 518, 519, 0, 0,
- 440, 0, 462, 0, 0, 63, 97, 0, 0, 0,
- 0, 127, 128, 129, 130, 0, 0, 0, 147, 641,
- 653, 0, 0, 0, 0, 0, 0, 243, 214, 0,
- 209, 0, 80, 220, 0, 192, 189, 0, 474, 65,
- 0, 61, 106, 107, 108, 109, 110, 111, 85, 139,
- 0, 143, 141, 534, 529, 530, 531, 532, 533, 378,
- 527, 0, 535, 0, 0, 692, 689, 689, 686, 0,
- 213, 0, 0, 208, 0, 218, 0, 219, 0, 0,
- 0, 473, 62, 0, 0, 0, 131, 0, 0, 0,
- 0, 27, 691, 690, 183, 180, 179, 182, 200, 181,
- 201, 217, 345, 175, 177, 0, 176, 0, 215, 244,
- 0, 212, 209, 80, 0, 222, 220, 0, 190, 480,
- 478, 80, 80, 0, 112, 113, 114, 115, 140, 0,
- 526, 194, 675, 190, 0, 0, 0, 0, 211, 210,
- 0, 221, 0, 0, 0, 475, 477, 0, 0, 135,
- 0, 0, 0, 0, 0, 0, 194, 216, 303, 304,
- 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
- 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
- 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
- 335, 336, 337, 338, 297, 246, 248, 250, 252, 0,
- 245, 270, 277, 279, 281, 283, 0, 276, 293, 184,
- 80, 481, 378, 116, 190, 528, 678, 80, 0, 670,
- 694, 0, 0, 0, 0, 0, 0, 0, 0, 240,
- 0, 0, 0, 0, 0, 242, 0, 476, 0, 195,
- 677, 0, 190, 193, 344, 190, 190, 298, 190, 0,
- 241, 340, 190, 190, 247, 190, 0, 190, 249, 342,
- 190, 190, 251, 190, 0, 190, 253, 190, 190, 271,
- 190, 190, 278, 190, 190, 280, 190, 282, 190, 190,
- 284, 190, 294, 190, 479, 0, 0, 299, 302, 0,
- 300, 0, 254, 261, 0, 258, 0, 0, 260, 262,
- 269, 0, 266, 0, 0, 268, 272, 275, 0, 273,
- 285, 0, 287, 288, 289, 0, 291, 292, 295, 296,
- 675, 178, 190, 0, 190, 190, 0, 190, 190, 190,
- 0, 190, 190, 190, 190, 676, 301, 343, 257, 0,
- 255, 0, 259, 265, 0, 263, 341, 267, 274, 286,
- 290, 190, 0, 190, 256, 339, 264
+ 173, 639, 640, 0, 641, 0, 643, 27, 0, 656,
+ 0, 0, 0, 685, 377, 0, 0, 0, 0, 556,
+ 558, 190, 518, 518, 517, 203, 190, 190, 443, 190,
+ 445, 188, 186, 185, 187, 190, 467, 0, 190, 460,
+ 0, 572, 64, 56, 0, 562, 0, 102, 103, 104,
+ 105, 85, 85, 85, 85, 138, 0, 146, 142, 151,
+ 152, 0, 80, 0, 0, 538, 378, 0, 0, 689,
+ 690, 688, 0, 0, 0, 0, 521, 519, 520, 0,
+ 0, 440, 462, 0, 463, 0, 0, 63, 97, 0,
+ 0, 0, 0, 127, 128, 129, 130, 0, 0, 0,
+ 147, 642, 654, 0, 0, 0, 0, 0, 0, 243,
+ 214, 0, 209, 0, 80, 220, 0, 192, 189, 0,
+ 475, 65, 0, 61, 106, 107, 108, 109, 110, 111,
+ 85, 139, 0, 143, 141, 535, 530, 531, 532, 533,
+ 534, 378, 528, 0, 536, 0, 0, 693, 690, 690,
+ 687, 0, 213, 0, 0, 208, 0, 218, 0, 219,
+ 0, 0, 0, 474, 62, 0, 0, 0, 131, 0,
+ 0, 0, 0, 27, 692, 691, 183, 180, 179, 182,
+ 200, 181, 201, 217, 345, 175, 177, 0, 176, 0,
+ 215, 244, 0, 212, 209, 80, 0, 222, 220, 0,
+ 190, 481, 479, 80, 80, 0, 112, 113, 114, 115,
+ 140, 0, 527, 194, 676, 190, 0, 0, 0, 0,
+ 211, 210, 0, 221, 0, 0, 0, 476, 478, 0,
+ 0, 135, 0, 0, 0, 0, 0, 0, 194, 216,
+ 303, 304, 305, 306, 307, 308, 309, 310, 311, 312,
+ 313, 314, 315, 316, 317, 318, 319, 320, 321, 322,
+ 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+ 333, 334, 335, 336, 337, 338, 297, 246, 248, 250,
+ 252, 0, 245, 270, 277, 279, 281, 283, 0, 276,
+ 293, 184, 80, 482, 378, 116, 190, 529, 679, 80,
+ 0, 671, 695, 0, 0, 0, 0, 0, 0, 0,
+ 0, 240, 0, 0, 0, 0, 0, 242, 0, 477,
+ 0, 195, 678, 0, 190, 193, 344, 190, 190, 298,
+ 190, 0, 241, 340, 190, 190, 247, 190, 0, 190,
+ 249, 342, 190, 190, 251, 190, 0, 190, 253, 190,
+ 190, 271, 190, 190, 278, 190, 190, 280, 190, 282,
+ 190, 190, 284, 190, 294, 190, 480, 0, 0, 299,
+ 302, 0, 300, 0, 254, 261, 0, 258, 0, 0,
+ 260, 262, 269, 0, 266, 0, 0, 268, 272, 275,
+ 0, 273, 285, 0, 287, 288, 289, 0, 291, 292,
+ 295, 296, 676, 178, 190, 0, 190, 190, 0, 190,
+ 190, 190, 0, 190, 190, 190, 190, 677, 301, 343,
+ 257, 0, 255, 0, 259, 265, 0, 263, 341, 267,
+ 274, 286, 290, 190, 0, 190, 256, 339, 264
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -1232, -1232, -1232, -222, -226, -189, -1232, 247, -195, 289,
- -1232, -1232, -1232, -1232, -1232, -1232, -196, -342, -662, -56,
- -783, -637, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -569,
- -252, -1232, -1232, -1232, -849, -1232, -1232, -247, 1222, 1220,
- -57, 1263, -1232, -708, -589, -607, -1232, -1232, -169, -1232,
- -1232, -168, -1232, -1232, -1232, -167, -321, -1232, -1232, -791,
- -1232, -1232, -1232, -1232, -1232, -788, -1232, -1232, -1232, -1232,
- -655, -1232, -1232, -1232, 108, -1232, -1232, -1232, -1232, -1232,
- 130, -1232, -1232, -503, -1232, -1232, -489, -1232, -1232, -1222,
- -1232, -1232, -1232, -1232, -552, 1709, -427, -1231, -565, -1232,
- -1232, -1232, -746, -909, -36, -1232, -516, -1232, -1232, -1232,
- -1232, -518, -334, 99, -1232, -1232, -315, -1007, -385, -466,
- -1008, -980, -1232, -942, -614, -1232, -1232, -1232, -1232, -600,
- -1232, -1232, -1232, -1232, -606, -611, -1232, -583, -1232, -776,
- -1232, -761, -1232, 711, -412, -190, 514, -417, 29, -245,
- -310, 107, -1232, -1232, -1232, 193, -1232, -110, -1232, -77,
- -1232, -1232, -1232, -1232, -1232, -1232, -835, -1232, -1232, -1232,
- -1232, 635, 637, 638, 640, -283, 531, -1232, -1232, -91,
- 41, -1232, -1232, -1232, -1232, -1232, -107, -1232, -1232, -1232,
- -1232, 10, -1232, 502, -104, -1232, -1232, -1232, 642, -1232,
- -1232, -1232, -620, -1232, -1232, -1232, 580, 584, 510, -174,
- 2, 312, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -367,
- -798, -966, -1232, -1232, 662, 671, -1232, 232, -1232, -411,
- -1232, -1232, -1232, -182, -1232, 675, -1232, -178, -1232, 677,
- -1232, -186, -1232, 679, -1232, -187, -1232, -1232, 414, -1232,
- -1232, -1232, -1232, -1232, 969, -289, -1232, -1232, -379, -1232,
- -1232, -785, -1232, -1232, -1232, -775, -1232, -1232, 687, -1232,
- -1232, 625, -1232, 628, -1232, -1232, 230, -618, 234, 241,
- 242, 699, -1232, -1232, -1232, -1232, -1232, 717, -1232, -1232,
- -1232, -1232, 718, -1232, -1232, 719, -1232, -1232, 727, -1232,
- -1232, 738, -188, -344, 109, -1232, -1232, -1232, -1232, -1232,
- -1232, -1232, -1232, -1232, -1232, 842, -1232, 539, -179, -1232,
- -119, -209, -1232, -1232, -86, -1232, 115, -1232, -1232, -1232,
- -808, -1232, -1232, -1232, 549, 16, 887, -1232, -1232, 551,
- -1083, -502, -1232, -988, 892, -1232, -1232, -1232, -49, -1232,
- -375, -1232, -200
+ -1232, -1232, -1232, -221, -226, -189, -1232, 266, -194, 293,
+ -1232, -1232, -1232, -1232, -1232, -1232, -196, -341, -654, -53,
+ -782, -642, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -563,
+ -250, -1232, -1232, -1232, -847, -1232, -1232, -237, 1251, 1249,
+ -57, 1948, -1232, -665, -567, -574, -1232, -1232, -157, -1232,
+ -1232, -156, -1232, -1232, -1232, -154, -306, -1232, -1232, -791,
+ -1232, -1232, -1232, -1232, -1232, -783, -1232, -1232, -1232, -1232,
+ -657, -1232, -1232, -1232, 110, -1232, -1232, -1232, -1232, -1232,
+ 143, -1232, -1232, -505, -1232, -1232, -473, -1232, -1232, -1231,
+ -1232, -1232, -1232, -1232, -557, 1794, -410, -1201, -544, -1232,
+ -1232, -1232, -748, -930, -37, -1232, -497, -1232, -1232, -1232,
+ -1232, -500, -334, 124, -1232, -1232, -290, -1018, -364, -446,
+ -1004, -578, -1232, -852, -597, -1232, -1232, -1232, -1232, -602,
+ -1232, -1232, -1232, -1232, -729, -588, -1232, -701, -1232, -556,
+ -1232, -724, -1232, 716, -416, -148, 519, -419, 36, -102,
+ -326, 101, -1232, -1232, -1232, 188, -1232, -117, -1232, -67,
+ -1232, -1232, -1232, -1232, -1232, -1232, -836, -1232, -1232, -1232,
+ -1232, 600, 604, 605, 607, -280, 663, -1232, -1232, -91,
+ 42, -1232, -1232, -1232, -1232, -1232, -107, -1232, -1232, -1232,
+ -1232, 10, -1232, 506, -105, -1232, -1232, -1232, 609, -1232,
+ -1232, -1232, -644, -1232, -1232, -1232, 546, 552, 527, -204,
+ 4, 277, -1232, -1232, -1232, -1232, -1232, -1232, -1232, -367,
+ -794, -938, -1232, -1232, 627, 633, -1232, 197, -1232, -448,
+ -1232, -1232, -1232, -192, -1232, 640, -1232, -185, -1232, 641,
+ -1232, -186, -1232, 644, -1232, -187, -1232, -1232, 378, -1232,
+ -1232, -1232, -1232, -1232, 540, -406, -1232, -1232, -384, -1232,
+ -1232, -781, -1232, -1232, -1232, -796, -1232, -1232, 648, -1232,
+ -1232, 588, -1232, 590, -1232, -1232, 190, -624, 193, 194,
+ 195, 660, -1232, -1232, -1232, -1232, -1232, 671, -1232, -1232,
+ -1232, -1232, 672, -1232, -1232, 673, -1232, -1232, 674, -1232,
+ -1232, 675, -179, -349, 76, -1232, -1232, -1232, -1232, -1232,
+ -1232, -1232, -1232, -1232, -1232, 806, -1232, 478, -253, -1232,
+ -119, -209, -1232, -1232, -109, -1232, 81, -1232, -1232, -1232,
+ -814, -1232, -1232, -1232, 489, -64, 816, -1232, -1232, 484,
+ -1087, -552, -1232, -1001, 842, -1232, -1232, -1232, -96, -1232,
+ -458, -1232, -249
};
/* YYDEFGOTO[NTERM-NUM]. */
@@ -1284,18 +1284,18 @@ static const yytype_int16 yydefgoto[] =
-1, 37, 38, 39, 235, 620, 237, 880, 238, 470,
239, 240, 419, 420, 241, 348, 242, 243, 894, 589,
503, 590, 504, 695, 890, 591, 809, 969, 592, 810,
- 893, 1032, 1033, 1110, 811, 812, 813, 895, 109, 215,
+ 893, 1033, 1034, 1112, 811, 812, 813, 895, 109, 215,
382, 456, 922, 609, 749, 819, 712, 713, 714, 715,
- 716, 717, 718, 905, 1035, 719, 720, 721, 910, 722,
- 723, 914, 1045, 1120, 1199, 724, 1087, 725, 917, 1047,
- 726, 727, 920, 1050, 489, 351, 41, 136, 245, 427,
- 428, 429, 615, 430, 431, 617, 729, 730, 1172, 1173,
- 1174, 1175, 1025, 1026, 874, 383, 667, 1176, 1221, 673,
- 668, 1177, 870, 1016, 448, 449, 1143, 450, 1140, 451,
- 452, 1147, 453, 649, 650, 651, 858, 1100, 1098, 1103,
- 1101, 1180, 1269, 1324, 1332, 1270, 1339, 1276, 1342, 1347,
- 1277, 1352, 1294, 1317, 1264, 1325, 1326, 1333, 1334, 1327,
- 1319, 1178, 42, 252, 353, 534, 44, 354, 253, 138,
+ 716, 717, 718, 905, 1036, 719, 720, 721, 910, 722,
+ 723, 914, 1046, 1122, 1201, 724, 1089, 725, 917, 1048,
+ 726, 727, 920, 1051, 489, 351, 41, 136, 245, 427,
+ 428, 429, 615, 430, 431, 617, 729, 730, 1174, 1175,
+ 1176, 1177, 1026, 1027, 874, 383, 667, 1178, 1223, 673,
+ 668, 1179, 870, 1016, 448, 449, 1145, 450, 1142, 451,
+ 452, 1149, 453, 649, 650, 651, 858, 1102, 1100, 1105,
+ 1103, 1182, 1271, 1326, 1334, 1272, 1341, 1278, 1344, 1349,
+ 1279, 1354, 1296, 1319, 1266, 1327, 1328, 1335, 1336, 1329,
+ 1321, 1180, 42, 252, 353, 534, 44, 354, 253, 138,
247, 538, 248, 441, 624, 435, 436, 621, 619, 254,
255, 445, 446, 634, 542, 630, 845, 631, 853, 46,
47, 48, 49, 50, 51, 454, 140, 52, 53, 256,
@@ -1303,11 +1303,11 @@ static const yytype_int16 yydefgoto[] =
56, 257, 58, 149, 203, 298, 299, 492, 59, 60,
275, 276, 787, 277, 278, 279, 258, 259, 457, 876,
936, 375, 62, 152, 284, 285, 482, 478, 963, 738,
- 680, 881, 1027, 63, 64, 65, 290, 486, 1151, 1192,
- 1193, 1282, 66, 67, 68, 69, 70, 71, 72, 73,
+ 680, 881, 1028, 63, 64, 65, 290, 486, 1153, 1194,
+ 1195, 1284, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 210, 80, 318, 319,
506, 320, 321, 509, 937, 953, 461, 659, 941, 520,
- 746, 739, 1129, 1130, 1131, 740, 741, 1055, 81, 82,
+ 746, 739, 1131, 1132, 1133, 740, 741, 1056, 81, 82,
83, 260, 84, 261, 85, 86, 262, 770, 263, 264,
265, 87, 88, 162, 324, 325, 703, 89, 292, 293,
294, 295, 90, 303, 304, 91, 308, 309, 92, 313,
@@ -1315,8 +1315,8 @@ static const yytype_int16 yydefgoto[] =
96, 182, 97, 183, 184, 938, 218, 219, 837, 99,
186, 334, 335, 516, 336, 191, 342, 343, 927, 928,
742, 743, 100, 221, 222, 605, 939, 102, 224, 225,
- 940, 1223, 103, 748, 328, 105, 523, 848, 849, 1059,
- 1096, 524, 1060
+ 940, 1225, 103, 748, 328, 105, 523, 848, 849, 1060,
+ 1098, 524, 1061
};
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
@@ -1324,638 +1324,654 @@ static const yytype_int16 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int16 yytable[] =
{
- 115, 270, 61, 236, 421, 344, 672, 479, 146, 711,
- 57, 337, 187, 188, 339, 737, 347, 532, 943, 291,
- 307, 312, 531, 697, 326, 613, 302, 421, 929, 45,
- 906, 1053, 519, 907, 842, 808, 911, 871, 772, 345,
- 931, 54, 434, 932, 970, 485, 1017, 190, 349, 918,
- 1160, 925, 205, 1099, 207, 1099, 1104, 803, 789, 512,
- 1, 926, 1316, 1, 19, 21, 1108, 518, 1093, 1168,
- 1, 15, 5, 1323, 1323, 1331, 1331, 1314, 1338, 192,
- 1323, 193, 464, 194, 195, 249, 196, 144, 114, 34,
- 36, 5, 198, 199, 250, 200, 201, 202, 204, 202,
- 206, 202, 208, 209, 267, 211, 1168, 212, 40, 5,
- 33, 442, 251, 822, 106, 825, 17, 828, 266, 831,
- 333, 833, 251, 10, 289, 316, 17, 216, 1392, 217,
- 220, 223, 483, 226, 338, 1182, 26, 340, 1104, 26,
- 29, 189, 1394, 29, 1170, 1397, 26, 144, 670, 1398,
- 29, 422, 1401, 671, 15, 664, 1402, 189, 5, 665,
- 282, 425, 5, 145, 1184, 5, 908, 1012, 1187, 912,
- 370, 704, 915, 467, 31, 32, 476, 1013, 311, 333,
- 134, 1170, 283, 1037, 1075, 1051, 1038, 1421, 350, 1040,
- 352, -628, 1423, 33, 525, 1203, 484, 357, 249, 359,
- 710, 502, 144, 362, 363, 735, 1048, 250, 513, 364,
- 365, 366, 367, 5, 368, 326, 369, 202, 371, 994,
- 1092, 996, 526, 145, 734, 1111, 1058, 374, 1355, 626,
- 288, 968, 378, 379, 1288, 380, 485, 246, 891, 274,
- 1188, 384, 706, 707, 948, 386, 387, 924, 951, 850,
- 389, 390, 956, 966, 731, 392, 393, 627, 961, 682,
- -630, 1152, 2, 398, 144, 708, 709, 401, 476, 661,
- 403, 587, 4, 588, 447, 560, 5, 405, 145, 408,
- 409, 411, 412, 414, 5, 415, 1112, 600, 2, 1113,
- 1115, 973, 2, 704, 1158, 975, 1134, 735, 4, 978,
- 980, 981, 4, 5, 984, 985, 7, 5, 987, 19,
- 297, 1284, 10, 296, -51, 301, 588, 317, 246, 1039,
- 1136, 12, 1041, 338, 1042, 1107, 340, 899, 1043, 903,
- 459, -631, 903, 251, 34, 903, 315, 316, 903, 5,
- 145, 903, 5, 1089, 246, 433, 707, 633, 704, -632,
- 493, 704, 670, 496, 1328, 807, 499, 671, 476, 24,
- 1345, 323, 5, 31, 32, 1194, 5, 443, 708, 709,
- 527, 528, 341, 473, 463, 708, 709, 352, 533, 709,
- 536, 1183, 1312, 664, 537, 539, 540, 665, 541, 1191,
- 107, 108, 687, 694, 1145, 868, 696, 691, 546, 693,
- 547, 548, 689, 549, 733, 551, 552, 762, 554, 555,
- 326, 556, 558, 1201, 1287, 346, 562, 563, 564, 423,
- 424, 374, 1114, 1116, 1117, 1118, 569, 570, -30, 755,
- 573, 574, 757, 1081, 1082, 1083, 1084, 579, 580, 531,
- 582, 583, 229, 585, 586, 213, 214, 1308, 421, 851,
- 859, 860, 861, 596, 597, 598, 654, 656, 1225, 1226,
- 603, 444, 604, 1021, 607, 532, 608, 1022, 1023, 1024,
- 653, 655, 676, 678, 5, 1209, 7, 1321, 883, 1314,
- 21, 882, 477, 1215, 1216, 306, 675, 677, 903, 459,
- 903, 751, 490, 447, 903, 5, 5, 686, 1195, 1196,
- 1197, 696, 329, 330, 704, 36, 1135, 705, 706, 707,
- 652, 1156, 518, 657, 1189, 660, 522, 1318, 662, 663,
- 423, 1335, 1335, 517, 1340, 1344, 674, 1349, 1349, 521,
- 1353, 708, 709, 710, 134, 228, 229, 685, 230, 231,
- 232, 233, 234, 688, 424, 5, 690, 5, 433, 692,
- 1171, 807, 1314, 1181, 704, 752, 587, 1185, 706, 707,
- 698, 1190, 533, 1283, 5, 533, 854, 537, 747, 759,
- 1164, 805, 1307, 704, 1165, 1166, 1167, 705, 707, 1310,
- 5, 708, 709, 1321, 670, 1314, 921, 764, 1395, 671,
- 588, 903, 765, 766, 767, 1399, 768, 769, 771, 769,
- 708, 709, 774, 1097, 1271, 1403, 1278, 709, 889, 1404,
- 5, 696, 892, 884, 1329, 1314, 469, 1227, 785, 786,
- 788, 786, 154, 790, 156, 791, 158, 793, 160, 795,
- 233, 234, 1169, 1286, 1057, 418, 502, 913, 942, 804,
- 916, 618, 971, 141, 967, 623, 815, 897, 150, 900,
- 153, 901, 155, 1036, 157, 421, 159, 612, 816, 1121,
- 818, 1292, 864, 821, 666, 824, 1208, 827, 1211, 830,
- 684, 830, 628, 629, 598, 708, 709, 836, 1102, 875,
- 1186, -59, 604, 604, 1336, 608, -59, -59, -59, 844,
- 1343, 807, 246, 433, 847, 1164, 1097, 696, 892, 1165,
- 1166, 1167, 1168, 1164, 1350, 5, 728, 1165, 1166, 1167,
- 1168, 43, 728, 5, 704, 287, 728, 705, 706, 707,
- 1348, 1348, 704, 1066, 1067, 705, 706, 707, 1057, 622,
- 1164, 758, 807, 933, 1165, 1166, 1167, 855, 856, 857,
- 5, 708, 709, 710, 1329, 1314, 991, 992, 1164, 708,
- 709, 710, 1165, 1166, 1167, 839, 840, 1169, 5, 1015,
- 1015, 1162, 1163, 1314, 165, 1169, 166, 167, 807, 168,
- 1164, 169, 1031, 1052, 1165, 1166, 1167, 1170, 862, 280,
- 5, 866, 1123, 281, 1019, 1170, 1124, 1125, 1126, 1127,
- 566, 170, 1169, 502, 759, 872, 844, 1044, 878, 1046,
- 171, 10, 683, 1280, 172, 769, 173, 1074, 174, 769,
- 1169, 952, 507, 954, 955, 786, 175, 896, 958, 421,
- 268, 786, 251, 269, 962, 791, 17, 699, 176, 134,
- 228, 700, 1169, 230, 231, 232, 286, 696, 701, 702,
- 835, 830, 98, 974, 1128, 830, 177, 178, 179, 977,
- 979, 830, 31, 32, 983, 830, 180, 986, 830, 1422,
- 988, 228, 229, 989, 230, 231, 232, 181, 836, 836,
- 993, 458, 608, 406, 997, 998, 228, 863, 1109, 230,
- 231, 232, 474, 475, 1001, 1002, 410, 101, 1405, 3,
- 413, 488, 104, 1003, 873, 1137, 1119, 6, 495, 0,
- 0, 498, 0, 0, 501, 0, 8, 0, 0, 0,
- 0, 0, 511, 9, 696, 228, 11, 0, 230, 231,
- 232, 233, 234, 805, 898, 806, 902, 0, 0, 902,
- 0, 16, 902, 0, 0, 902, 0, 0, 902, 0,
- 0, 0, 18, 1056, 728, 20, 0, 22, 1061, 1062,
- 1063, 1064, 934, 0, 1015, 952, 952, 0, 25, 0,
- 27, 0, 28, 0, 30, 0, 0, 0, 1198, 0,
- 35, 0, 1073, 0, 0, 0, 0, 0, 0, 1077,
- 1078, 1079, 1097, 1080, 830, 830, 830, 0, 1085, 476,
- 1086, 5, 0, 0, 608, 0, 1091, 5, 844, 0,
- 704, 0, 1095, 705, 706, 707, 704, 0, 0, 705,
- 706, 707, 0, 0, 0, 0, 0, 0, 735, 0,
- 0, 0, 923, 736, 0, 1015, 0, 708, 709, 710,
- 0, 0, 0, 708, 709, 710, 0, 0, 0, 0,
- 0, 1139, 0, 1142, 0, 608, 1146, 0, 0, 0,
- 1149, 1150, 0, 0, 0, 1153, 1154, 0, 1155, 0,
- 1011, 830, 0, 1157, 0, 0, 0, 0, 0, 5,
- 0, 0, 844, 0, 0, 0, 0, 1161, 704, 1095,
- 1095, 705, 706, 707, 0, 902, 0, 902, 0, 0,
- 0, 902, 0, 1164, 0, 736, 1015, 1165, 1166, 1167,
- 1168, 728, 0, 5, 0, 708, 709, 710, 0, 0,
- 0, 0, 704, 0, 0, 705, 706, 707, 0, 0,
- 0, 1206, 1189, 1207, 0, 1142, 608, 1210, 0, 1146,
- 1212, 0, 0, 0, 1214, 608, 0, 1218, 0, 708,
- 709, 710, 0, 0, 1220, 1222, 0, 0, 0, 0,
- 476, 0, 0, 0, 0, 1169, 228, 229, 5, 230,
- 231, 232, 233, 234, 0, 1393, 806, 704, 1291, 1220,
- 705, 706, 707, 0, 0, 1170, 0, 1396, 0, 735,
- 0, 0, 0, 0, 1400, 134, 228, 229, 902, 230,
- 231, 232, 233, 234, 708, 709, 710, 0, 0, 0,
- 0, 0, 0, 728, 0, 0, 0, 1293, 1295, 1296,
- 1297, 1298, 0, 0, 1300, 1301, 1302, 1303, 1304, 476,
- 0, 1306, 0, 608, 0, 844, 0, 5, 228, 0,
- 608, 230, 231, 232, 233, 234, 704, 0, 806, 705,
- 706, 707, 0, 0, 0, 0, 0, 728, 735, 0,
- 728, 0, 0, 736, 728, 0, 0, 0, 728, 0,
- 0, 1359, 0, 708, 709, 710, 0, 110, 1364, 0,
- 1367, 0, 0, 0, 111, 112, 1371, 113, 1374, 0,
- 116, 0, 117, 1378, 118, 0, 1381, 0, 119, 0,
- 120, 1385, 121, 0, 122, 0, 123, 0, 124, 0,
- 125, 0, 126, 0, 0, 0, 0, 0, 0, 0,
- 127, 0, 0, 0, 728, 0, 0, 128, 0, 129,
- 0, 130, 728, 131, 0, 132, 0, 133, 0, 0,
- 728, 460, 462, 1222, 0, 465, 466, 0, 1409, 1411,
- 228, 229, 1414, 230, 231, 232, 233, 234, 0, 487,
- 0, 0, 0, 0, 0, 0, 494, 0, 0, 497,
- 0, 0, 500, 0, 0, 0, 0, 0, 0, 197,
- 510, 0, 135, 137, 139, 139, 142, 0, 0, 148,
- 139, 151, 139, 148, 139, 148, 139, 148, 139, 148,
- 161, 163, 0, 185, 185, 185, 0, 0, 0, 0,
- 0, 1315, 0, 1322, 1322, 1330, 1330, 0, 1337, 1341,
- 1322, 1346, 1346, 227, 1351, 0, 3, 0, 0, 0,
- 0, 0, 0, 300, 6, 305, 0, 310, 0, 5,
- 322, 0, 0, 8, 0, 0, 0, 0, 704, 0,
- 9, 705, 706, 707, 0, 0, 0, 0, 0, 0,
- 0, 0, 14, 0, 0, 244, 0, 0, 16, 0,
- 272, 0, 0, 0, 0, 708, 709, 710, 0, 18,
- 355, 0, 20, 0, 22, 356, 0, 358, 0, 0,
- 360, 361, 0, 0, 0, 25, 5, 27, 0, 28,
- 0, 30, 0, 0, 0, 704, 0, 35, 705, 706,
- 707, 0, 372, 373, 0, 0, 0, 376, 0, 0,
- 377, 0, 736, 0, 747, 0, 0, 381, 0, 0,
- 0, 385, 708, 709, 710, 0, 388, 0, 0, 0,
- 0, 391, 0, 0, 0, 0, 394, 0, 0, 0,
- 0, 397, 0, 400, 0, 0, 0, 402, 0, 0,
- 0, 0, 0, 0, 404, 0, 0, 407, 0, 0,
- 0, 0, 0, 0, 417, 416, 0, 0, 0, 0,
- 0, 432, 0, 438, 439, 635, 636, 637, 638, 639,
- 640, 641, 642, 643, 644, 645, 646, 647, 648, 0,
- 472, 0, 0, 0, 0, 480, 635, 636, 637, 638,
- 639, 640, 641, 642, 643, 0, 0, 0, 0, 0,
- 0, 0, 0, 426, 0, 0, 0, 0, 440, 137,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 481,
- 137, 0, 0, 0, 0, 0, 0, 0, 491, 0,
- 0, 529, 0, 530, 0, 0, 0, 0, 535, 0,
- 505, 0, 0, 508, 0, 0, 0, 0, 543, 0,
- 515, 0, 0, 0, 545, 544, 0, 0, 0, 3,
- 0, 0, 0, 550, 553, 0, 5, 6, 0, 0,
- 0, 561, 0, 0, 0, 704, 8, 0, 705, 706,
- 707, 567, 0, 9, 0, 0, 572, 571, 0, 0,
- 0, 0, 577, 578, 0, 14, 581, 0, 0, 584,
- 0, 16, 708, 709, 710, 0, 593, 0, 0, 595,
- 0, 0, 18, 0, 601, 20, 602, 22, 0, 0,
- 0, 0, 606, 0, 0, 611, 610, 0, 25, 0,
- 27, 0, 28, 0, 30, 0, 0, 0, 625, 0,
- 35, 0, 632, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 669, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 681, 0,
- 0, 0, 614, 616, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 658, 0, 0, 0, 0, 0, 732,
- 0, 0, 0, 0, 0, 744, 0, 0, 0, 750,
- 679, 0, 0, 0, 0, 753, 0, 754, 0, 0,
- 0, 756, 0, 0, 0, 0, 0, 760, 0, 0,
- 0, 0, 0, 761, 763, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 745,
- 0, 0, 0, 185, 0, 0, 0, 773, 0, 0,
- 775, 776, 777, 778, 0, 0, 0, 0, 0, 0,
- 781, 0, 0, 0, 784, 783, 0, 0, 0, 0,
- 0, 0, 0, 792, 0, 794, 0, 0, 797, 0,
- 799, 0, 801, 0, 0, 0, 0, 0, 814, 0,
+ 115, 672, 270, 236, 61, 421, 344, 479, 146, 291,
+ 57, 337, 187, 188, 339, 532, 347, 943, 531, 302,
+ 307, 312, 929, 613, 190, 1017, 434, 519, 421, 697,
+ 906, 711, 772, 326, 789, 871, 45, 737, 907, 345,
+ 926, 911, 54, 808, 931, 485, 970, 932, 1162, 349,
+ 918, 205, 803, 207, 512, 925, 1095, 1110, 1101, 1054,
+ 1101, 1106, 106, 1, 144, 670, 1325, 1325, 1333, 1333,
+ 671, 1340, 518, 1325, 15, 5, 114, 842, 249, 192,
+ 2, 193, 1, 194, 195, 464, 196, 250, 1170, 144,
+ 4, 5, 198, 199, 1318, 200, 201, 202, 204, 202,
+ 206, 202, 208, 209, 267, 211, 144, 212, 144, 189,
+ 40, 338, 476, 33, 340, 251, 1, 5, 447, 17,
+ 5, 5, 2, 134, 10, 333, 1184, 216, 266, 217,
+ 220, 223, 4, 226, 289, 1396, 246, 433, 1399, 26,
+ 145, 735, 1400, 29, 1106, 1403, 822, 333, 825, 1404,
+ 828, 422, 831, 189, 833, 316, 1013, 249, 26, 282,
+ 1394, 425, 29, 1172, 908, 145, 250, 912, 251, 370,
+ 915, 1012, 17, 19, 467, 31, 32, 476, 246, 1052,
+ 1423, 283, 145, 1038, 145, 1425, 484, 1077, 350, -629,
+ 352, 1039, 26, 5, 1041, 525, 29, 357, 34, 359,
+ -631, 502, 704, 362, 363, 1059, 735, 1049, 513, 364,
+ 365, 366, 367, 626, 368, -632, 369, 202, 371, 734,
+ 1094, 1190, 526, 1290, 326, 1205, 1357, 374, 956, 1113,
+ 707, 710, 378, 379, 961, 380, 485, 288, 948, 968,
+ 274, 384, 951, 682, 891, 386, 387, 850, 966, 731,
+ 389, 390, 708, 709, 442, 392, 393, 107, 108, 21,
+ 627, 2, 994, 398, 996, 1154, 15, 401, 19, 924,
+ 403, 4, 661, 246, 301, 483, 560, 405, 10, 408,
+ 409, 411, 412, 414, 36, 415, 1170, 600, 1114, 5,
+ 311, 7, 1286, 34, 1316, 1160, 1115, 1117, 5, 251,
+ 338, 1138, 1136, 340, 1125, 33, 12, 704, 1126, 1127,
+ 1128, 1129, 297, 670, 587, 459, 588, 1040, 671, 317,
+ 1042, 5, 1043, 5, 973, 1109, 1044, 296, 975, 31,
+ 32, 5, 978, 980, 981, 709, 664, 984, 985, 323,
+ 665, 987, -633, 899, 24, 903, 5, 633, 903, 493,
+ 5, 903, 496, 5, 903, 499, 807, 903, 1316, 704,
+ -51, 1172, 588, 1314, 315, 316, 1130, 443, 706, 707,
+ 527, 528, 1196, 476, 463, 473, 341, 352, 533, 664,
+ 536, 5, 687, 665, 537, 539, 540, 1091, 541, 21,
+ 868, 708, 709, 694, 306, 689, 696, 691, 546, 693,
+ 547, 548, 346, 549, 733, 551, 552, 762, 554, 555,
+ 1289, 556, 558, 1203, 36, -30, 562, 563, 564, 326,
+ 1185, 374, 1116, 1118, 1119, 1120, 569, 570, 1193, 5,
+ 573, 574, 1323, 851, 1316, 531, 229, 579, 580, 1147,
+ 582, 583, 5, 585, 586, 670, 1330, 444, 1310, 421,
+ 671, 704, 1347, 596, 597, 598, 654, 656, 1227, 1228,
+ 603, 459, 604, 532, 607, 882, 608, 1083, 1084, 1085,
+ 1086, 755, 676, 678, 757, 859, 860, 861, 708, 709,
+ 653, 655, 1166, 1273, 477, 1280, 1167, 1168, 1169, 517,
+ 7, 751, 5, 447, 490, 521, 675, 677, 1197, 1198,
+ 1199, 696, 10, 883, 903, 5, 903, 686, 522, 652,
+ 903, 5, 657, 423, 660, 1331, 1316, 662, 663, 424,
+ 1211, 213, 214, 251, 518, 674, -59, 17, 1217, 1218,
+ 1137, -59, -59, -59, 134, 228, 685, 286, 230, 231,
+ 232, 433, 688, 747, 1171, 690, 1158, 5, 692, 855,
+ 856, 857, 807, 31, 32, 752, 704, 329, 330, 698,
+ 706, 707, 533, 1285, 5, 533, 854, 537, 1186, 759,
+ 233, 234, 1189, 704, 1173, 628, 629, 1183, 707, 246,
+ 433, 1187, 587, 708, 709, 1192, 805, 764, 708, 709,
+ 423, 424, 765, 766, 767, 705, 768, 769, 771, 769,
+ 708, 709, 774, 884, 1350, 1350, 1067, 1068, 889, 903,
+ 228, 696, 892, 230, 231, 232, 921, 1309, 785, 786,
+ 788, 786, 588, 790, 1312, 791, 154, 793, 156, 795,
+ 158, 1099, 160, 709, 1058, 469, 502, 913, 942, 418,
+ 916, 1229, 804, 618, 971, 228, 815, 623, 230, 231,
+ 232, 233, 234, 805, 967, 806, 421, 1288, 816, 897,
+ 818, 900, 864, 821, 901, 824, 666, 827, 1037, 830,
+ 612, 830, 991, 992, 598, 839, 840, 836, 1123, 875,
+ 1164, 1165, 604, 604, 1294, 608, 1166, 1210, 1213, 844,
+ 1167, 1168, 1169, 807, 847, 684, 5, 696, 892, 1323,
+ 1104, 1316, 1188, 1338, 1352, 134, 228, 229, 728, 230,
+ 231, 232, 233, 234, 728, 1345, 43, 1166, 728, 1099,
+ 287, 1167, 1168, 1169, 622, 758, 933, 5, 5, 165,
+ 1058, 1331, 1316, 166, 167, 807, 168, 704, 169, 1320,
+ 705, 706, 707, 1337, 1337, 280, 1342, 1346, 1171, 1351,
+ 1351, 281, 1355, 1021, 1019, 566, 170, 1022, 1023, 1024,
+ 1015, 1015, 171, 5, 708, 709, 710, 683, 1282, 172,
+ 173, 807, 1032, 174, 1053, 141, 507, 175, 862, 1171,
+ 150, 866, 153, 268, 155, 269, 157, 699, 159, 176,
+ 700, 701, 702, 502, 759, 872, 844, 1045, 878, 1047,
+ 177, 178, 179, 180, 181, 769, 98, 835, 1076, 769,
+ 1397, 952, 406, 954, 955, 786, 101, 1401, 958, 896,
+ 3, 786, 421, 413, 962, 791, 410, 1405, 6, 228,
+ 229, 1406, 230, 231, 232, 233, 234, 8, 696, 806,
+ 1407, 830, 104, 974, 9, 830, 1003, 11, 1139, 977,
+ 979, 830, 0, 0, 983, 830, 1424, 986, 830, 0,
+ 988, 0, 16, 989, 0, 0, 0, 0, 836, 836,
+ 993, 0, 608, 18, 997, 998, 20, 1166, 22, 863,
+ 1111, 1167, 1168, 1169, 1001, 1002, 0, 5, 458, 25,
+ 0, 27, 1316, 28, 0, 30, 873, 0, 1121, 474,
+ 475, 35, 460, 462, 0, 0, 465, 466, 488, 228,
+ 229, 0, 230, 231, 232, 495, 696, 0, 498, 0,
+ 487, 501, 0, 0, 0, 0, 898, 494, 902, 511,
+ 497, 902, 0, 500, 902, 0, 0, 902, 0, 1171,
+ 902, 510, 0, 1057, 0, 0, 728, 0, 1062, 1063,
+ 1064, 1065, 0, 0, 934, 952, 952, 1015, 0, 228,
+ 0, 0, 230, 231, 232, 233, 234, 0, 0, 806,
+ 1200, 228, 229, 1075, 230, 231, 232, 233, 234, 0,
+ 1079, 1080, 1081, 0, 1082, 830, 830, 830, 0, 1087,
+ 0, 1088, 0, 0, 0, 608, 0, 1093, 0, 844,
+ 0, 0, 0, 1097, 0, 0, 0, 0, 1166, 1099,
+ 0, 0, 1167, 1168, 1169, 1170, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 704, 1015, 0,
+ 705, 706, 707, 635, 636, 637, 638, 639, 640, 641,
+ 642, 643, 0, 1141, 0, 1144, 0, 608, 1148, 0,
+ 0, 0, 1151, 1152, 708, 709, 710, 1155, 1156, 0,
+ 1157, 0, 1011, 830, 5, 1159, 0, 0, 0, 0,
+ 1171, 5, 1025, 704, 844, 0, 705, 706, 707, 1163,
+ 704, 1097, 1097, 705, 706, 707, 0, 902, 0, 902,
+ 1172, 0, 0, 902, 0, 0, 0, 736, 0, 1015,
+ 708, 709, 710, 728, 0, 0, 0, 708, 709, 710,
+ 0, 1166, 0, 0, 0, 1167, 1168, 1169, 1170, 0,
+ 0, 5, 0, 1208, 0, 1209, 0, 1144, 608, 1212,
+ 704, 1148, 1214, 705, 706, 707, 1216, 608, 0, 1220,
+ 1191, 0, 0, 476, 0, 0, 1222, 1224, 0, 0,
+ 0, 5, 0, 0, 0, 0, 0, 708, 709, 710,
+ 704, 0, 0, 705, 706, 707, 0, 1395, 0, 0,
+ 1293, 1222, 735, 1171, 0, 0, 923, 736, 0, 1398,
+ 0, 0, 0, 0, 0, 0, 1402, 708, 709, 710,
+ 0, 0, 902, 1172, 0, 134, 228, 229, 0, 230,
+ 231, 232, 233, 234, 0, 0, 0, 728, 0, 1295,
+ 1297, 1298, 1299, 1300, 0, 0, 1302, 1303, 1304, 1305,
+ 1306, 476, 0, 1308, 0, 608, 0, 844, 0, 5,
+ 0, 0, 608, 0, 0, 0, 0, 0, 704, 0,
+ 0, 705, 706, 707, 0, 0, 0, 0, 0, 0,
+ 735, 728, 0, 0, 728, 736, 0, 0, 728, 0,
+ 0, 0, 728, 1361, 0, 708, 709, 710, 0, 0,
+ 1366, 0, 1369, 0, 0, 0, 0, 0, 1373, 0,
+ 1376, 0, 0, 0, 0, 1380, 0, 0, 1383, 0,
+ 0, 0, 0, 1387, 0, 0, 110, 0, 0, 0,
+ 0, 0, 0, 111, 112, 0, 113, 0, 0, 116,
+ 0, 117, 0, 118, 0, 0, 0, 119, 728, 120,
+ 0, 121, 0, 122, 0, 123, 728, 124, 0, 125,
+ 0, 126, 0, 0, 728, 1224, 0, 0, 0, 127,
+ 1411, 1413, 0, 0, 1416, 0, 128, 0, 129, 0,
+ 130, 0, 131, 0, 132, 1166, 133, 5, 0, 1167,
+ 1168, 1169, 1170, 0, 0, 5, 704, 0, 0, 705,
+ 706, 707, 0, 0, 704, 0, 0, 705, 706, 707,
+ 0, 0, 0, 736, 0, 747, 0, 0, 0, 0,
+ 0, 0, 0, 708, 709, 710, 0, 0, 197, 0,
+ 0, 708, 709, 710, 0, 1317, 0, 1324, 1324, 1332,
+ 1332, 0, 1339, 1343, 1324, 1348, 1348, 1171, 1353, 3,
+ 0, 0, 0, 0, 476, 0, 5, 6, 0, 0,
+ 0, 0, 5, 0, 0, 704, 8, 1172, 705, 706,
+ 707, 704, 227, 9, 705, 706, 707, 0, 0, 3,
+ 0, 0, 300, 735, 305, 14, 310, 6, 0, 322,
+ 0, 16, 708, 709, 710, 0, 8, 0, 708, 709,
+ 710, 0, 18, 9, 0, 20, 0, 22, 0, 0,
+ 0, 0, 0, 0, 0, 14, 0, 0, 25, 0,
+ 27, 16, 28, 0, 30, 0, 0, 0, 0, 355,
+ 35, 0, 18, 0, 356, 20, 358, 22, 0, 360,
+ 361, 0, 0, 0, 0, 0, 0, 0, 25, 0,
+ 27, 0, 28, 0, 30, 0, 0, 0, 0, 0,
+ 35, 372, 373, 0, 0, 0, 376, 0, 0, 377,
+ 0, 0, 0, 0, 5, 0, 381, 0, 0, 0,
+ 385, 0, 0, 704, 0, 388, 705, 706, 707, 0,
+ 391, 0, 0, 1191, 0, 394, 0, 0, 0, 0,
+ 397, 0, 400, 0, 0, 0, 402, 0, 1, 2,
+ 708, 709, 710, 404, 3, 0, 407, 0, 0, 4,
+ 0, 5, 6, 417, 416, 0, 0, 0, 7, 0,
+ 432, 8, 438, 439, 0, 0, 0, 0, 9, 10,
+ 0, 11, 0, 12, 0, 0, 0, 0, 13, 472,
+ 14, 0, 0, 15, 480, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 17, 0, 0, 18, 0, 19,
+ 20, 21, 22, 0, 0, 0, 0, 0, 0, 0,
+ 23, 24, 0, 25, 26, 27, 0, 28, 29, 30,
+ 31, 32, 33, 0, 34, 35, 36, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 817, 0,
- 820, 0, 0, 823, 0, 826, 0, 829, 0, 832,
- 0, 0, 834, 0, 0, 0, 0, 0, 0, 0,
- 838, 0, 0, 841, 0, 843, 0, 0, 0, 0,
- 846, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 529, 0, 530, 0, 0, 0, 0, 535, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 543, 0, 0,
+ 0, 0, 0, 545, 544, 0, 0, 0, 0, 0,
+ 0, 0, 550, 553, 0, 0, 0, 0, 0, 0,
+ 561, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 567, 0, 0, 0, 0, 572, 571, 0, 0, 0,
+ 0, 577, 578, 0, 0, 581, 0, 0, 584, 0,
+ 0, 0, 0, 0, 0, 593, 0, 0, 595, 0,
+ 0, 0, 0, 601, 0, 602, 0, 0, 0, 0,
+ 0, 606, 0, 0, 611, 610, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 625, 0, 0,
+ 0, 632, 635, 636, 637, 638, 639, 640, 641, 642,
+ 643, 644, 645, 646, 647, 648, 669, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 681, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 865, 0, 867, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 877, 0, 879,
- 0, 0, 0, 0, 0, 0, 885, 0, 886, 0,
- 887, 0, 888, 0, 852, 0, 395, 396, 0, 399,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 869, 0, 869, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 930, 0, 0,
- 0, 0, 0, 0, 0, 935, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 732, 0,
+ 0, 0, 0, 0, 744, 0, 0, 0, 750, 0,
+ 0, 0, 0, 0, 753, 0, 754, 0, 0, 0,
+ 756, 0, 0, 0, 0, 0, 760, 0, 0, 0,
+ 0, 0, 761, 763, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 904, 0, 0, 909, 0, 0, 0,
- 0, 0, 0, 0, 0, 919, 0, 0, 0, 0,
- 0, 679, 0, 0, 679, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 773, 0, 0, 775,
+ 776, 777, 778, 0, 0, 0, 0, 0, 0, 781,
+ 0, 0, 0, 784, 783, 0, 0, 0, 0, 0,
+ 0, 0, 792, 0, 794, 0, 0, 797, 0, 799,
+ 0, 801, 0, 0, 0, 0, 0, 814, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 976, 0, 0, 0, 0,
- 982, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 990, 0, 0, 0, 0, 0, 0, 0,
- 995, 0, 0, 999, 0, 0, 0, 0, 0, 0,
- 1000, 0, 0, 1004, 1005, 1006, 1007, 1008, 1009, 0,
- 0, 1010, 0, 1014, 0, 0, 1018, 0, 559, 0,
- 0, 1020, 0, 1028, 1029, 1030, 565, 0, 0, 0,
- 0, 568, 1034, 0, 0, 0, 0, 0, 575, 576,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1228,
- 1229, 1230, 1231, 1232, 1233, 1234, 594, 1235, 1236, 1237,
- 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247,
- 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257,
- 1258, 0, 0, 1259, 1260, 1261, 1262, 1263, 1071, 0,
- 0, 0, 1049, 0, 0, 1076, 0, 0, 0, 0,
- 0, 1054, 0, 0, 0, 0, 0, 0, 0, 0,
- 1088, 0, 1090, 0, 0, 0, 0, 0, 0, 1094,
- 0, 0, 0, 0, 0, 0, 0, 0, 1105, 1106,
+ 0, 0, 0, 0, 0, 0, 0, 817, 0, 820,
+ 0, 0, 823, 0, 826, 0, 829, 0, 832, 0,
+ 0, 834, 0, 0, 0, 0, 0, 0, 0, 838,
+ 0, 0, 841, 0, 843, 0, 0, 0, 0, 846,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1122, 0, 0,
- 0, 0, 1132, 0, 0, 1133, 1138, 0, 0, 0,
- 0, 1141, 0, 1144, 0, 0, 1148, 0, 0, 0,
- 0, 0, 0, 0, 869, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 865,
+ 0, 867, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 877, 0, 879, 0,
+ 0, 0, 0, 0, 0, 885, 0, 886, 0, 887,
+ 0, 888, 0, 0, 0, 0, 0, 135, 137, 139,
+ 139, 142, 0, 0, 148, 139, 151, 139, 148, 139,
+ 148, 139, 148, 139, 148, 161, 163, 0, 185, 185,
+ 185, 0, 0, 0, 0, 0, 930, 0, 0, 0,
+ 0, 0, 0, 0, 935, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1159, 0, 0, 0, 679, 0, 0,
+ 0, 395, 396, 0, 399, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 779, 780, 0, 1200, 0,
- 1202, 782, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 796, 1204, 798, 1205,
- 800, 0, 802, 0, 1179, 0, 0, 1179, 0, 0,
- 0, 1179, 0, 0, 0, 1217, 0, 0, 0, 1219,
- 0, 0, 869, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1279, 0, 0, 0, 0, 0, 0,
- 0, 1285, 0, 1289, 1290, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 869, 869, 0,
+ 244, 0, 0, 0, 0, 272, 0, 0, 0, 0,
+ 0, 0, 0, 0, 976, 0, 0, 0, 0, 982,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1281, 0, 0, 0, 0, 0, 0, 0, 0, 1299,
- 0, 0, 0, 0, 0, 0, 1305, 0, 0, 0,
+ 0, 990, 0, 0, 0, 0, 0, 0, 0, 995,
+ 0, 0, 999, 0, 0, 0, 0, 0, 0, 1000,
+ 0, 0, 1004, 1005, 1006, 1007, 1008, 1009, 0, 0,
+ 1010, 0, 1014, 0, 0, 1018, 0, 0, 0, 0,
+ 1020, 0, 1029, 1030, 1031, 0, 0, 0, 0, 0,
+ 0, 1035, 1267, 1230, 1231, 1232, 1233, 1234, 1235, 1236,
+ 1268, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245,
+ 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255,
+ 1256, 1257, 1258, 1259, 1260, 1269, 1270, 1261, 1262, 1263,
+ 1264, 1265, 0, 559, 0, 0, 0, 0, 0, 0,
+ 0, 565, 0, 0, 0, 0, 568, 0, 1073, 0,
+ 0, 0, 0, 575, 576, 1078, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 426, 0,
+ 1090, 594, 1092, 440, 137, 0, 0, 0, 0, 1096,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1107, 1108,
+ 0, 0, 0, 0, 481, 137, 0, 0, 0, 0,
+ 0, 0, 0, 491, 0, 0, 0, 0, 1124, 0,
+ 0, 0, 0, 1134, 0, 505, 1135, 1140, 508, 0,
+ 0, 0, 1143, 0, 1146, 515, 0, 1150, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1311, 0, 1313, 0, 1320, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1354, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1361, 0, 0, 0, 0, 0, 0, 1366, 0,
- 0, 0, 0, 0, 0, 0, 1373, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 944, 945, 946,
- 947, 0, 949, 950, 0, 1390, 1391, 1, 2, 0,
- 0, 0, 957, 3, 959, 960, 0, 0, 4, 0,
- 5, 6, 964, 965, 0, 0, 0, 7, 0, 0,
- 8, 0, 0, 0, 0, 972, 0, 9, 10, 0,
- 11, 0, 12, 1407, 0, 0, 0, 13, 0, 14,
- 1416, 0, 15, 0, 0, 16, 0, 0, 0, 0,
- 0, 0, 0, 17, 0, 0, 18, 0, 19, 20,
- 21, 22, 1425, 0, 0, 0, 0, 0, 0, 23,
- 24, 0, 25, 26, 27, 0, 28, 29, 30, 31,
- 32, 33, 0, 34, 35, 36, 1265, 1228, 1229, 1230,
- 1231, 1232, 1233, 1234, 1266, 1235, 1236, 1237, 1238, 1239,
- 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249,
- 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1267,
- 1268, 1259, 1260, 1261, 1262, 1263, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1161, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1065, 0, 0, 0, 0, 1068, 1069, 0, 1070, 0,
- 0, 0, 0, 0, 0, 0, 1072, 1272, 1228, 1229,
- 1230, 1231, 1232, 1233, 1234, 1273, 1235, 1236, 1237, 1238,
- 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248,
- 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258,
- 1274, 1275, 1259, 1260, 1261, 1262, 1263, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1202,
+ 0, 1204, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1206, 0,
+ 1207, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1219, 0, 0, 0,
+ 1221, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 779, 780, 0, 0, 1281, 0, 782, 0, 0, 0,
+ 0, 0, 1287, 0, 1291, 1292, 0, 614, 616, 0,
+ 0, 796, 0, 798, 0, 800, 0, 802, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 658, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 679, 0, 0, 0, 0,
+ 1301, 0, 0, 0, 0, 0, 0, 1307, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1313, 0, 1315, 0, 1322, 0, 0, 0, 0,
+ 0, 0, 0, 0, 745, 0, 0, 0, 185, 1356,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1363, 0, 0, 0, 0, 0, 0, 1368,
+ 0, 0, 0, 0, 0, 0, 0, 1375, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1392, 1393, 0, 0,
+ 0, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 0, 1237,
+ 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247,
+ 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257,
+ 1258, 1259, 1260, 0, 1409, 1261, 1262, 1263, 1264, 1265,
+ 0, 1418, 944, 945, 946, 947, 0, 949, 950, 0,
+ 0, 0, 0, 0, 0, 0, 0, 957, 0, 959,
+ 960, 0, 0, 1427, 0, 0, 0, 964, 965, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 972, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 852,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 869,
+ 0, 869, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 904, 0,
+ 0, 909, 0, 0, 0, 0, 0, 0, 0, 0,
+ 919, 0, 0, 0, 0, 0, 679, 0, 0, 679,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1066, 0, 0, 0, 0,
+ 1069, 1070, 0, 1071, 0, 0, 0, 0, 0, 1072,
+ 0, 0, 1074, 1274, 1230, 1231, 1232, 1233, 1234, 1235,
+ 1236, 1275, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244,
+ 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254,
+ 1255, 1256, 1257, 1258, 1259, 1260, 1276, 1277, 1261, 1262,
+ 1263, 1264, 1265, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1213, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1224, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1050, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1055, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1215, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1226,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1309, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 869, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1356, 0, 0, 1357, 1358, 0, 1360, 0, 0,
- 0, 1362, 1363, 0, 1365, 0, 1368, 0, 0, 1369,
- 1370, 0, 1372, 0, 1375, 0, 1376, 1377, 0, 1379,
- 1380, 0, 1382, 1383, 0, 1384, 0, 1386, 1387, 0,
- 1388, 0, 1389, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 679, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1406, 0, 1408, 1410, 0, 1412, 1413, 1415, 0,
- 1417, 1418, 1419, 1420, 0, 0, 0, 0, 0, 0,
+ 1311, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1181, 0, 0, 1181, 0, 0, 0, 1181, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1358, 869,
+ 0, 1359, 1360, 0, 1362, 0, 0, 0, 1364, 1365,
+ 0, 1367, 0, 1370, 0, 0, 1371, 1372, 0, 1374,
+ 0, 1377, 0, 1378, 1379, 0, 1381, 1382, 0, 1384,
+ 1385, 0, 1386, 0, 1388, 1389, 0, 1390, 0, 1391,
+ 0, 0, 0, 0, 869, 869, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1283, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1424, 0, 1426
+ 0, 0, 0, 0, 0, 0, 0, 0, 1408, 0,
+ 1410, 1412, 0, 1414, 1415, 1417, 0, 1419, 1420, 1421,
+ 1422, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1426, 0, 1428
};
static const yytype_int16 yycheck[] =
{
- 57, 196, 0, 192, 346, 227, 558, 374, 115, 598,
- 0, 220, 131, 132, 223, 604, 242, 434, 853, 201,
- 206, 208, 434, 592, 212, 528, 204, 369, 836, 0,
- 821, 997, 411, 821, 742, 697, 824, 783, 656, 235,
- 838, 0, 352, 841, 893, 379, 955, 133, 243, 832,
- 1133, 836, 156, 1061, 158, 1063, 1064, 694, 678, 403,
- 4, 836, 1293, 4, 65, 67, 1073, 25, 1056, 14,
- 4, 49, 17, 1295, 1296, 1297, 1298, 22, 1300, 136,
- 1302, 138, 365, 140, 141, 19, 143, 6, 163, 90,
- 92, 17, 149, 150, 28, 152, 153, 154, 155, 156,
- 157, 158, 159, 160, 195, 162, 14, 164, 0, 17,
- 88, 356, 56, 720, 0, 722, 60, 724, 195, 726,
- 78, 728, 56, 35, 201, 51, 60, 184, 1359, 186,
- 187, 188, 377, 190, 220, 1142, 80, 223, 1146, 80,
- 84, 40, 1364, 84, 89, 1367, 80, 6, 7, 1371,
- 84, 347, 1374, 12, 49, 7, 1378, 40, 17, 11,
- 3, 350, 17, 82, 1144, 17, 821, 952, 1148, 824,
- 274, 26, 827, 368, 86, 87, 9, 952, 73, 78,
- 147, 89, 25, 974, 1033, 993, 974, 1409, 245, 977,
- 247, 163, 1414, 88, 416, 1161, 378, 254, 19, 256,
- 55, 397, 6, 260, 261, 38, 989, 28, 404, 266,
- 267, 268, 269, 17, 271, 403, 273, 274, 275, 927,
- 1055, 929, 418, 82, 603, 1074, 1001, 284, 1311, 539,
- 201, 893, 289, 290, 1222, 292, 570, 61, 807, 198,
- 1149, 298, 30, 31, 862, 302, 303, 836, 866, 752,
- 307, 308, 872, 890, 598, 312, 313, 540, 878, 569,
- 163, 1110, 5, 320, 6, 53, 54, 324, 9, 552,
- 327, 155, 15, 157, 16, 470, 17, 334, 82, 336,
- 337, 338, 339, 340, 17, 342, 1077, 513, 5, 1077,
- 1078, 898, 5, 26, 1129, 902, 1094, 38, 15, 906,
- 907, 908, 15, 17, 911, 912, 24, 17, 915, 65,
- 202, 1220, 35, 23, 155, 71, 157, 209, 61, 974,
- 1095, 39, 977, 409, 979, 1071, 412, 816, 983, 818,
- 48, 163, 821, 56, 90, 824, 50, 51, 827, 17,
- 82, 830, 17, 1051, 61, 62, 31, 543, 26, 163,
- 386, 26, 7, 389, 1296, 697, 392, 12, 9, 77,
- 1302, 64, 17, 86, 87, 1153, 17, 357, 53, 54,
- 427, 428, 41, 371, 364, 53, 54, 434, 435, 54,
- 437, 1142, 1291, 7, 441, 442, 443, 11, 445, 1150,
- 159, 160, 574, 589, 1102, 774, 592, 583, 455, 586,
- 457, 458, 580, 460, 600, 462, 463, 633, 465, 466,
- 598, 468, 469, 1159, 1222, 150, 473, 474, 475, 32,
- 33, 478, 1077, 1078, 1079, 1080, 483, 484, 150, 619,
- 487, 488, 622, 1040, 1041, 1042, 1043, 494, 495, 851,
- 497, 498, 149, 500, 501, 161, 162, 1282, 790, 759,
- 765, 766, 767, 510, 511, 512, 547, 548, 1204, 1205,
- 517, 57, 519, 7, 521, 882, 523, 11, 12, 13,
- 547, 548, 563, 564, 17, 1183, 24, 20, 793, 22,
- 67, 791, 374, 1191, 1192, 72, 563, 564, 977, 48,
- 979, 610, 384, 16, 983, 17, 17, 574, 1153, 1154,
- 1155, 697, 74, 75, 26, 92, 1095, 29, 30, 31,
- 546, 1118, 25, 549, 36, 551, 47, 1293, 554, 555,
- 32, 1297, 1298, 408, 1300, 1301, 562, 1303, 1304, 414,
- 1306, 53, 54, 55, 147, 148, 149, 573, 151, 152,
- 153, 154, 155, 579, 33, 17, 582, 17, 62, 585,
- 1139, 893, 22, 1142, 26, 612, 155, 1146, 30, 31,
- 596, 1150, 619, 1218, 17, 622, 762, 624, 45, 626,
- 7, 156, 1280, 26, 11, 12, 13, 29, 31, 1287,
- 17, 53, 54, 20, 7, 22, 147, 644, 1364, 12,
- 157, 1080, 649, 650, 651, 1371, 653, 654, 655, 656,
- 53, 54, 659, 8, 1210, 1381, 1212, 54, 804, 1385,
- 17, 807, 808, 795, 21, 22, 369, 1206, 675, 676,
- 677, 678, 120, 680, 122, 682, 124, 684, 126, 686,
- 154, 155, 69, 1222, 1001, 346, 832, 826, 847, 695,
- 829, 533, 894, 112, 891, 537, 703, 816, 117, 817,
- 119, 818, 121, 974, 123, 997, 125, 527, 715, 1086,
- 717, 1226, 769, 720, 556, 722, 1182, 724, 1186, 726,
- 571, 728, 58, 59, 731, 53, 54, 734, 1063, 786,
- 1146, 156, 739, 740, 1298, 742, 161, 162, 163, 746,
- 1301, 1033, 61, 62, 751, 7, 8, 893, 894, 11,
- 12, 13, 14, 7, 1304, 17, 598, 11, 12, 13,
- 14, 0, 604, 17, 26, 201, 608, 29, 30, 31,
- 1303, 1304, 26, 1012, 1013, 29, 30, 31, 1095, 536,
- 7, 624, 1074, 843, 11, 12, 13, 151, 152, 153,
- 17, 53, 54, 55, 21, 22, 925, 926, 7, 53,
- 54, 55, 11, 12, 13, 739, 740, 69, 17, 954,
- 955, 1136, 1137, 22, 129, 69, 129, 129, 1110, 129,
- 7, 129, 968, 995, 11, 12, 13, 89, 768, 199,
- 17, 771, 7, 199, 958, 89, 11, 12, 13, 14,
- 478, 129, 69, 989, 851, 785, 853, 986, 788, 988,
- 129, 35, 570, 1214, 129, 862, 129, 1033, 129, 866,
- 69, 868, 398, 870, 871, 872, 129, 815, 875, 1161,
- 195, 878, 56, 195, 881, 882, 60, 597, 129, 147,
- 148, 597, 69, 151, 152, 153, 70, 1033, 597, 597,
- 731, 898, 0, 900, 69, 902, 129, 129, 129, 906,
- 907, 908, 86, 87, 911, 912, 129, 914, 915, 1411,
- 917, 148, 149, 920, 151, 152, 153, 129, 925, 926,
- 927, 361, 929, 334, 931, 932, 148, 769, 1074, 151,
- 152, 153, 372, 373, 941, 942, 337, 0, 1390, 10,
- 339, 381, 0, 942, 786, 1095, 1085, 18, 388, -1,
- -1, 391, -1, -1, 394, -1, 27, -1, -1, -1,
- -1, -1, 402, 34, 1110, 148, 37, -1, 151, 152,
- 153, 154, 155, 156, 816, 158, 818, -1, -1, 821,
- -1, 52, 824, -1, -1, 827, -1, -1, 830, -1,
- -1, -1, 63, 1000, 836, 66, -1, 68, 1005, 1006,
- 1007, 1008, 844, -1, 1149, 1012, 1013, -1, 79, -1,
- 81, -1, 83, -1, 85, -1, -1, -1, 1157, -1,
- 91, -1, 1029, -1, -1, -1, -1, -1, -1, 1036,
- 1037, 1038, 8, 1040, 1041, 1042, 1043, -1, 1045, 9,
- 1047, 17, -1, -1, 1051, -1, 1053, 17, 1055, -1,
- 26, -1, 1059, 29, 30, 31, 26, -1, -1, 29,
- 30, 31, -1, -1, -1, -1, -1, -1, 38, -1,
- -1, -1, 42, 43, -1, 1220, -1, 53, 54, 55,
- -1, -1, -1, 53, 54, 55, -1, -1, -1, -1,
- -1, 1098, -1, 1100, -1, 1102, 1103, -1, -1, -1,
- 1107, 1108, -1, -1, -1, 1112, 1113, -1, 1115, -1,
- 952, 1118, -1, 1120, -1, -1, -1, -1, -1, 17,
- -1, -1, 1129, -1, -1, -1, -1, 1134, 26, 1136,
- 1137, 29, 30, 31, -1, 977, -1, 979, -1, -1,
- -1, 983, -1, 7, -1, 43, 1291, 11, 12, 13,
- 14, 993, -1, 17, -1, 53, 54, 55, -1, -1,
- -1, -1, 26, -1, -1, 29, 30, 31, -1, -1,
- -1, 1178, 36, 1180, -1, 1182, 1183, 1184, -1, 1186,
- 1187, -1, -1, -1, 1191, 1192, -1, 1194, -1, 53,
- 54, 55, -1, -1, 1201, 1202, -1, -1, -1, -1,
- 9, -1, -1, -1, -1, 69, 148, 149, 17, 151,
- 152, 153, 154, 155, -1, 1361, 158, 26, 1225, 1226,
- 29, 30, 31, -1, -1, 89, -1, 1366, -1, 38,
- -1, -1, -1, -1, 1373, 147, 148, 149, 1080, 151,
- 152, 153, 154, 155, 53, 54, 55, -1, -1, -1,
- -1, -1, -1, 1095, -1, -1, -1, 1264, 1265, 1266,
- 1267, 1268, -1, -1, 1271, 1272, 1273, 1274, 1275, 9,
- -1, 1278, -1, 1280, -1, 1282, -1, 17, 148, -1,
- 1287, 151, 152, 153, 154, 155, 26, -1, 158, 29,
- 30, 31, -1, -1, -1, -1, -1, 1139, 38, -1,
- 1142, -1, -1, 43, 1146, -1, -1, -1, 1150, -1,
- -1, 1318, -1, 53, 54, 55, -1, 45, 1325, -1,
- 1327, -1, -1, -1, 52, 53, 1333, 55, 1335, -1,
- 58, -1, 60, 1340, 62, -1, 1343, -1, 66, -1,
- 68, 1348, 70, -1, 72, -1, 74, -1, 76, -1,
- 78, -1, 80, -1, -1, -1, -1, -1, -1, -1,
- 88, -1, -1, -1, 1206, -1, -1, 95, -1, 97,
- -1, 99, 1214, 101, -1, 103, -1, 105, -1, -1,
- 1222, 362, 363, 1390, -1, 366, 367, -1, 1395, 1396,
- 148, 149, 1399, 151, 152, 153, 154, 155, -1, 380,
- -1, -1, -1, -1, -1, -1, 387, -1, -1, 390,
- -1, -1, 393, -1, -1, -1, -1, -1, -1, 147,
- 401, -1, 109, 110, 111, 112, 113, -1, -1, 116,
- 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
- 127, 128, -1, 130, 131, 132, -1, -1, -1, -1,
- -1, 1293, -1, 1295, 1296, 1297, 1298, -1, 1300, 1301,
- 1302, 1303, 1304, 191, 1306, -1, 10, -1, -1, -1,
- -1, -1, -1, 203, 18, 205, -1, 207, -1, 17,
- 210, -1, -1, 27, -1, -1, -1, -1, 26, -1,
- 34, 29, 30, 31, -1, -1, -1, -1, -1, -1,
- -1, -1, 46, -1, -1, 192, -1, -1, 52, -1,
- 197, -1, -1, -1, -1, 53, 54, 55, -1, 63,
- 248, -1, 66, -1, 68, 253, -1, 255, -1, -1,
- 258, 259, -1, -1, -1, 79, 17, 81, -1, 83,
- -1, 85, -1, -1, -1, 26, -1, 91, 29, 30,
- 31, -1, 280, 281, -1, -1, -1, 285, -1, -1,
- 288, -1, 43, -1, 45, -1, -1, 295, -1, -1,
- -1, 299, 53, 54, 55, -1, 304, -1, -1, -1,
- -1, 309, -1, -1, -1, -1, 314, -1, -1, -1,
- -1, 319, -1, 321, -1, -1, -1, 325, -1, -1,
- -1, -1, -1, -1, 332, -1, -1, 335, -1, -1,
- -1, -1, -1, -1, 344, 343, -1, -1, -1, -1,
- -1, 351, -1, 353, 354, 93, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 106, -1,
- 370, -1, -1, -1, -1, 375, 93, 94, 95, 96,
- 97, 98, 99, 100, 101, -1, -1, -1, -1, -1,
- -1, -1, -1, 350, -1, -1, -1, -1, 355, 356,
+ 57, 558, 196, 192, 0, 346, 227, 374, 115, 201,
+ 0, 220, 131, 132, 223, 434, 242, 853, 434, 204,
+ 206, 208, 836, 528, 133, 955, 352, 411, 369, 592,
+ 821, 598, 656, 212, 678, 783, 0, 604, 821, 235,
+ 836, 824, 0, 697, 838, 379, 893, 841, 1135, 243,
+ 832, 156, 694, 158, 403, 836, 1057, 1075, 1062, 997,
+ 1064, 1065, 0, 4, 6, 7, 1297, 1298, 1299, 1300,
+ 12, 1302, 25, 1304, 49, 17, 163, 742, 19, 136,
+ 5, 138, 4, 140, 141, 365, 143, 28, 14, 6,
+ 15, 17, 149, 150, 1295, 152, 153, 154, 155, 156,
+ 157, 158, 159, 160, 195, 162, 6, 164, 6, 40,
+ 0, 220, 9, 88, 223, 56, 4, 17, 16, 60,
+ 17, 17, 5, 147, 35, 78, 1144, 184, 195, 186,
+ 187, 188, 15, 190, 201, 1366, 61, 62, 1369, 80,
+ 82, 38, 1373, 84, 1148, 1376, 720, 78, 722, 1380,
+ 724, 347, 726, 40, 728, 51, 952, 19, 80, 3,
+ 1361, 350, 84, 89, 821, 82, 28, 824, 56, 274,
+ 827, 952, 60, 65, 368, 86, 87, 9, 61, 993,
+ 1411, 25, 82, 974, 82, 1416, 378, 1034, 245, 163,
+ 247, 974, 80, 17, 977, 416, 84, 254, 90, 256,
+ 163, 397, 26, 260, 261, 1001, 38, 989, 404, 266,
+ 267, 268, 269, 539, 271, 163, 273, 274, 275, 603,
+ 1056, 1151, 418, 1224, 403, 1163, 1313, 284, 872, 1076,
+ 31, 55, 289, 290, 878, 292, 570, 201, 862, 893,
+ 198, 298, 866, 569, 807, 302, 303, 752, 890, 598,
+ 307, 308, 53, 54, 356, 312, 313, 159, 160, 67,
+ 540, 5, 927, 320, 929, 1112, 49, 324, 65, 836,
+ 327, 15, 552, 61, 71, 377, 470, 334, 35, 336,
+ 337, 338, 339, 340, 92, 342, 14, 513, 1079, 17,
+ 73, 24, 1222, 90, 22, 1131, 1079, 1080, 17, 56,
+ 409, 1097, 1096, 412, 7, 88, 39, 26, 11, 12,
+ 13, 14, 202, 7, 155, 48, 157, 974, 12, 209,
+ 977, 17, 979, 17, 898, 1073, 983, 23, 902, 86,
+ 87, 17, 906, 907, 908, 54, 7, 911, 912, 64,
+ 11, 915, 163, 816, 77, 818, 17, 543, 821, 386,
+ 17, 824, 389, 17, 827, 392, 697, 830, 22, 26,
+ 155, 89, 157, 1293, 50, 51, 69, 357, 30, 31,
+ 427, 428, 1155, 9, 364, 371, 41, 434, 435, 7,
+ 437, 17, 574, 11, 441, 442, 443, 1052, 445, 67,
+ 774, 53, 54, 589, 72, 580, 592, 583, 455, 586,
+ 457, 458, 150, 460, 600, 462, 463, 633, 465, 466,
+ 1224, 468, 469, 1161, 92, 150, 473, 474, 475, 598,
+ 1144, 478, 1079, 1080, 1081, 1082, 483, 484, 1152, 17,
+ 487, 488, 20, 759, 22, 851, 149, 494, 495, 1104,
+ 497, 498, 17, 500, 501, 7, 1298, 57, 1284, 790,
+ 12, 26, 1304, 510, 511, 512, 547, 548, 1206, 1207,
+ 517, 48, 519, 882, 521, 791, 523, 1041, 1042, 1043,
+ 1044, 619, 563, 564, 622, 765, 766, 767, 53, 54,
+ 547, 548, 7, 1212, 374, 1214, 11, 12, 13, 408,
+ 24, 610, 17, 16, 384, 414, 563, 564, 1155, 1156,
+ 1157, 697, 35, 793, 977, 17, 979, 574, 47, 546,
+ 983, 17, 549, 32, 551, 21, 22, 554, 555, 33,
+ 1185, 161, 162, 56, 25, 562, 156, 60, 1193, 1194,
+ 1097, 161, 162, 163, 147, 148, 573, 70, 151, 152,
+ 153, 62, 579, 45, 69, 582, 1120, 17, 585, 151,
+ 152, 153, 893, 86, 87, 612, 26, 74, 75, 596,
+ 30, 31, 619, 1220, 17, 622, 762, 624, 1146, 626,
+ 154, 155, 1150, 26, 1141, 58, 59, 1144, 31, 61,
+ 62, 1148, 155, 53, 54, 1152, 156, 644, 53, 54,
+ 32, 33, 649, 650, 651, 29, 653, 654, 655, 656,
+ 53, 54, 659, 795, 1305, 1306, 1012, 1013, 804, 1082,
+ 148, 807, 808, 151, 152, 153, 147, 1282, 675, 676,
+ 677, 678, 157, 680, 1289, 682, 120, 684, 122, 686,
+ 124, 8, 126, 54, 1001, 369, 832, 826, 847, 346,
+ 829, 1208, 695, 533, 894, 148, 703, 537, 151, 152,
+ 153, 154, 155, 156, 891, 158, 997, 1224, 715, 816,
+ 717, 817, 769, 720, 818, 722, 556, 724, 974, 726,
+ 527, 728, 925, 926, 731, 739, 740, 734, 1088, 786,
+ 1138, 1139, 739, 740, 1228, 742, 7, 1184, 1188, 746,
+ 11, 12, 13, 1034, 751, 571, 17, 893, 894, 20,
+ 1064, 22, 1148, 1300, 1306, 147, 148, 149, 598, 151,
+ 152, 153, 154, 155, 604, 1303, 0, 7, 608, 8,
+ 201, 11, 12, 13, 536, 624, 843, 17, 17, 129,
+ 1097, 21, 22, 129, 129, 1076, 129, 26, 129, 1295,
+ 29, 30, 31, 1299, 1300, 199, 1302, 1303, 69, 1305,
+ 1306, 199, 1308, 7, 958, 478, 129, 11, 12, 13,
+ 954, 955, 129, 17, 53, 54, 55, 570, 1216, 129,
+ 129, 1112, 968, 129, 995, 112, 398, 129, 768, 69,
+ 117, 771, 119, 195, 121, 195, 123, 597, 125, 129,
+ 597, 597, 597, 989, 851, 785, 853, 986, 788, 988,
+ 129, 129, 129, 129, 129, 862, 0, 731, 1034, 866,
+ 1366, 868, 334, 870, 871, 872, 0, 1373, 875, 815,
+ 10, 878, 1163, 339, 881, 882, 337, 1383, 18, 148,
+ 149, 1387, 151, 152, 153, 154, 155, 27, 1034, 158,
+ 1392, 898, 0, 900, 34, 902, 942, 37, 1097, 906,
+ 907, 908, -1, -1, 911, 912, 1413, 914, 915, -1,
+ 917, -1, 52, 920, -1, -1, -1, -1, 925, 926,
+ 927, -1, 929, 63, 931, 932, 66, 7, 68, 769,
+ 1076, 11, 12, 13, 941, 942, -1, 17, 361, 79,
+ -1, 81, 22, 83, -1, 85, 786, -1, 1087, 372,
+ 373, 91, 362, 363, -1, -1, 366, 367, 381, 148,
+ 149, -1, 151, 152, 153, 388, 1112, -1, 391, -1,
+ 380, 394, -1, -1, -1, -1, 816, 387, 818, 402,
+ 390, 821, -1, 393, 824, -1, -1, 827, -1, 69,
+ 830, 401, -1, 1000, -1, -1, 836, -1, 1005, 1006,
+ 1007, 1008, -1, -1, 844, 1012, 1013, 1151, -1, 148,
+ -1, -1, 151, 152, 153, 154, 155, -1, -1, 158,
+ 1159, 148, 149, 1030, 151, 152, 153, 154, 155, -1,
+ 1037, 1038, 1039, -1, 1041, 1042, 1043, 1044, -1, 1046,
+ -1, 1048, -1, -1, -1, 1052, -1, 1054, -1, 1056,
+ -1, -1, -1, 1060, -1, -1, -1, -1, 7, 8,
+ -1, -1, 11, 12, 13, 14, -1, -1, 17, -1,
+ -1, -1, -1, -1, -1, -1, -1, 26, 1222, -1,
+ 29, 30, 31, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, -1, 1100, -1, 1102, -1, 1104, 1105, -1,
+ -1, -1, 1109, 1110, 53, 54, 55, 1114, 1115, -1,
+ 1117, -1, 952, 1120, 17, 1122, -1, -1, -1, -1,
+ 69, 17, 962, 26, 1131, -1, 29, 30, 31, 1136,
+ 26, 1138, 1139, 29, 30, 31, -1, 977, -1, 979,
+ 89, -1, -1, 983, -1, -1, -1, 43, -1, 1293,
+ 53, 54, 55, 993, -1, -1, -1, 53, 54, 55,
+ -1, 7, -1, -1, -1, 11, 12, 13, 14, -1,
+ -1, 17, -1, 1180, -1, 1182, -1, 1184, 1185, 1186,
+ 26, 1188, 1189, 29, 30, 31, 1193, 1194, -1, 1196,
+ 36, -1, -1, 9, -1, -1, 1203, 1204, -1, -1,
+ -1, 17, -1, -1, -1, -1, -1, 53, 54, 55,
+ 26, -1, -1, 29, 30, 31, -1, 1363, -1, -1,
+ 1227, 1228, 38, 69, -1, -1, 42, 43, -1, 1368,
+ -1, -1, -1, -1, -1, -1, 1375, 53, 54, 55,
+ -1, -1, 1082, 89, -1, 147, 148, 149, -1, 151,
+ 152, 153, 154, 155, -1, -1, -1, 1097, -1, 1266,
+ 1267, 1268, 1269, 1270, -1, -1, 1273, 1274, 1275, 1276,
+ 1277, 9, -1, 1280, -1, 1282, -1, 1284, -1, 17,
+ -1, -1, 1289, -1, -1, -1, -1, -1, 26, -1,
+ -1, 29, 30, 31, -1, -1, -1, -1, -1, -1,
+ 38, 1141, -1, -1, 1144, 43, -1, -1, 1148, -1,
+ -1, -1, 1152, 1320, -1, 53, 54, 55, -1, -1,
+ 1327, -1, 1329, -1, -1, -1, -1, -1, 1335, -1,
+ 1337, -1, -1, -1, -1, 1342, -1, -1, 1345, -1,
+ -1, -1, -1, 1350, -1, -1, 45, -1, -1, -1,
+ -1, -1, -1, 52, 53, -1, 55, -1, -1, 58,
+ -1, 60, -1, 62, -1, -1, -1, 66, 1208, 68,
+ -1, 70, -1, 72, -1, 74, 1216, 76, -1, 78,
+ -1, 80, -1, -1, 1224, 1392, -1, -1, -1, 88,
+ 1397, 1398, -1, -1, 1401, -1, 95, -1, 97, -1,
+ 99, -1, 101, -1, 103, 7, 105, 17, -1, 11,
+ 12, 13, 14, -1, -1, 17, 26, -1, -1, 29,
+ 30, 31, -1, -1, 26, -1, -1, 29, 30, 31,
+ -1, -1, -1, 43, -1, 45, -1, -1, -1, -1,
+ -1, -1, -1, 53, 54, 55, -1, -1, 147, -1,
+ -1, 53, 54, 55, -1, 1295, -1, 1297, 1298, 1299,
+ 1300, -1, 1302, 1303, 1304, 1305, 1306, 69, 1308, 10,
+ -1, -1, -1, -1, 9, -1, 17, 18, -1, -1,
+ -1, -1, 17, -1, -1, 26, 27, 89, 29, 30,
+ 31, 26, 191, 34, 29, 30, 31, -1, -1, 10,
+ -1, -1, 203, 38, 205, 46, 207, 18, -1, 210,
+ -1, 52, 53, 54, 55, -1, 27, -1, 53, 54,
+ 55, -1, 63, 34, -1, 66, -1, 68, -1, -1,
+ -1, -1, -1, -1, -1, 46, -1, -1, 79, -1,
+ 81, 52, 83, -1, 85, -1, -1, -1, -1, 248,
+ 91, -1, 63, -1, 253, 66, 255, 68, -1, 258,
+ 259, -1, -1, -1, -1, -1, -1, -1, 79, -1,
+ 81, -1, 83, -1, 85, -1, -1, -1, -1, -1,
+ 91, 280, 281, -1, -1, -1, 285, -1, -1, 288,
+ -1, -1, -1, -1, 17, -1, 295, -1, -1, -1,
+ 299, -1, -1, 26, -1, 304, 29, 30, 31, -1,
+ 309, -1, -1, 36, -1, 314, -1, -1, -1, -1,
+ 319, -1, 321, -1, -1, -1, 325, -1, 4, 5,
+ 53, 54, 55, 332, 10, -1, 335, -1, -1, 15,
+ -1, 17, 18, 344, 343, -1, -1, -1, 24, -1,
+ 351, 27, 353, 354, -1, -1, -1, -1, 34, 35,
+ -1, 37, -1, 39, -1, -1, -1, -1, 44, 370,
+ 46, -1, -1, 49, 375, -1, 52, -1, -1, -1,
+ -1, -1, -1, -1, 60, -1, -1, 63, -1, 65,
+ 66, 67, 68, -1, -1, -1, -1, -1, -1, -1,
+ 76, 77, -1, 79, 80, 81, -1, 83, 84, 85,
+ 86, 87, 88, -1, 90, 91, 92, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 376,
- 377, -1, -1, -1, -1, -1, -1, -1, 385, -1,
- -1, 429, -1, 431, -1, -1, -1, -1, 436, -1,
- 397, -1, -1, 400, -1, -1, -1, -1, 446, -1,
- 407, -1, -1, -1, 454, 453, -1, -1, -1, 10,
- -1, -1, -1, 461, 464, -1, 17, 18, -1, -1,
- -1, 471, -1, -1, -1, 26, 27, -1, 29, 30,
- 31, 479, -1, 34, -1, -1, 486, 485, -1, -1,
- -1, -1, 492, 493, -1, 46, 496, -1, -1, 499,
- -1, 52, 53, 54, 55, -1, 506, -1, -1, 509,
- -1, -1, 63, -1, 514, 66, 516, 68, -1, -1,
- -1, -1, 520, -1, -1, 525, 524, -1, 79, -1,
- 81, -1, 83, -1, 85, -1, -1, -1, 538, -1,
- 91, -1, 542, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 557, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 568, -1,
- -1, -1, 529, 530, -1, -1, -1, -1, -1, -1,
+ 429, -1, 431, -1, -1, -1, -1, 436, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 446, -1, -1,
+ -1, -1, -1, 454, 453, -1, -1, -1, -1, -1,
+ -1, -1, 461, 464, -1, -1, -1, -1, -1, -1,
+ 471, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 479, -1, -1, -1, -1, 486, 485, -1, -1, -1,
+ -1, 492, 493, -1, -1, 496, -1, -1, 499, -1,
+ -1, -1, -1, -1, -1, 506, -1, -1, 509, -1,
+ -1, -1, -1, 514, -1, 516, -1, -1, -1, -1,
+ -1, 520, -1, -1, 525, 524, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 538, -1, -1,
+ -1, 542, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 104, 105, 106, 557, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 568, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 550, -1, -1, -1, -1, -1, 599,
- -1, -1, -1, -1, -1, 605, -1, -1, -1, 609,
- 567, -1, -1, -1, -1, 615, -1, 617, -1, -1,
- -1, 621, -1, -1, -1, -1, -1, 627, -1, -1,
- -1, -1, -1, 631, 634, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 606,
- -1, -1, -1, 610, -1, -1, -1, 657, -1, -1,
- 660, 661, 662, 663, -1, -1, -1, -1, -1, -1,
- 668, -1, -1, -1, 674, 673, -1, -1, -1, -1,
- -1, -1, -1, 683, -1, 685, -1, -1, 688, -1,
- 690, -1, 692, -1, -1, -1, -1, -1, 698, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 716, -1,
- 718, -1, -1, 721, -1, 723, -1, 725, -1, 727,
- -1, -1, 730, -1, -1, -1, -1, -1, -1, -1,
- 738, -1, -1, 741, -1, 743, -1, -1, -1, -1,
- 748, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 599, -1,
+ -1, -1, -1, -1, 605, -1, -1, -1, 609, -1,
+ -1, -1, -1, -1, 615, -1, 617, -1, -1, -1,
+ 621, -1, -1, -1, -1, -1, 627, -1, -1, -1,
+ -1, -1, 631, 634, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 770, -1, 772, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 787, -1, 789,
- -1, -1, -1, -1, -1, -1, 796, -1, 798, -1,
- 800, -1, 802, -1, 761, -1, 317, 318, -1, 320,
+ -1, -1, -1, -1, -1, -1, 657, -1, -1, 660,
+ 661, 662, 663, -1, -1, -1, -1, -1, -1, 668,
+ -1, -1, -1, 674, 673, -1, -1, -1, -1, -1,
+ -1, -1, 683, -1, 685, -1, -1, 688, -1, 690,
+ -1, 692, -1, -1, -1, -1, -1, 698, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 781, -1, 783, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 837, -1, -1,
- -1, -1, -1, -1, -1, 845, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 716, -1, 718,
+ -1, -1, 721, -1, 723, -1, 725, -1, 727, -1,
+ -1, 730, -1, -1, -1, -1, -1, -1, -1, 738,
+ -1, -1, 741, -1, 743, -1, -1, -1, -1, 748,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 820, -1, -1, 823, -1, -1, -1,
- -1, -1, -1, -1, -1, 832, -1, -1, -1, -1,
- -1, 838, -1, -1, 841, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 770,
+ -1, 772, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 787, -1, 789, -1,
+ -1, -1, -1, -1, -1, 796, -1, 798, -1, 800,
+ -1, 802, -1, -1, -1, -1, -1, 109, 110, 111,
+ 112, 113, -1, -1, 116, 117, 118, 119, 120, 121,
+ 122, 123, 124, 125, 126, 127, 128, -1, 130, 131,
+ 132, -1, -1, -1, -1, -1, 837, -1, -1, -1,
+ -1, -1, -1, -1, 845, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 905, -1, -1, -1, -1,
- 910, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 922, -1, -1, -1, -1, -1, -1, -1,
- 928, -1, -1, 933, -1, -1, -1, -1, -1, -1,
- 940, -1, -1, 943, 944, 945, 946, 947, 948, -1,
- -1, 951, -1, 953, -1, -1, 956, -1, 469, -1,
- -1, 961, -1, 963, 964, 965, 477, -1, -1, -1,
- -1, 482, 972, -1, -1, -1, -1, -1, 489, 490,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 108,
- 109, 110, 111, 112, 113, 114, 507, 116, 117, 118,
- 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
- 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
- 139, -1, -1, 142, 143, 144, 145, 146, 1026, -1,
- -1, -1, 989, -1, -1, 1035, -1, -1, -1, -1,
- -1, 998, -1, -1, -1, -1, -1, -1, -1, -1,
- 1050, -1, 1052, -1, -1, -1, -1, -1, -1, 1057,
- -1, -1, -1, -1, -1, -1, -1, -1, 1068, 1069,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1087, -1, -1,
- -1, -1, 1092, -1, -1, 1093, 1096, -1, -1, -1,
- -1, 1099, -1, 1101, -1, -1, 1104, -1, -1, -1,
- -1, -1, -1, -1, 1071, -1, -1, -1, -1, -1,
+ -1, 317, 318, -1, 320, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1131, -1, -1, -1, 1094, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 666, 667, -1, 1158, -1,
- 1160, 672, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 687, 1175, 689, 1177,
- 691, -1, 693, -1, 1141, -1, -1, 1144, -1, -1,
- -1, 1148, -1, -1, -1, 1193, -1, -1, -1, 1199,
- -1, -1, 1159, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1213, -1, -1, -1, -1, -1, -1,
- -1, 1221, -1, 1223, 1224, -1, -1, -1, -1, -1,
+ 192, -1, -1, -1, -1, 197, -1, -1, -1, -1,
+ -1, -1, -1, -1, 905, -1, -1, -1, -1, 910,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1204, 1205, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1217, -1, -1, -1, -1, -1, -1, -1, -1, 1269,
- -1, -1, -1, -1, -1, -1, 1276, -1, -1, -1,
+ -1, 922, -1, -1, -1, -1, -1, -1, -1, 928,
+ -1, -1, 933, -1, -1, -1, -1, -1, -1, 940,
+ -1, -1, 943, 944, 945, 946, 947, 948, -1, -1,
+ 951, -1, 953, -1, -1, 956, -1, -1, -1, -1,
+ 961, -1, 963, 964, 965, -1, -1, -1, -1, -1,
+ -1, 972, 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
+ 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
+ 145, 146, -1, 469, -1, -1, -1, -1, -1, -1,
+ -1, 477, -1, -1, -1, -1, 482, -1, 1027, -1,
+ -1, -1, -1, 489, 490, 1036, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 350, -1,
+ 1051, 507, 1053, 355, 356, -1, -1, -1, -1, 1058,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1069, 1070,
+ -1, -1, -1, -1, 376, 377, -1, -1, -1, -1,
+ -1, -1, -1, 385, -1, -1, -1, -1, 1089, -1,
+ -1, -1, -1, 1094, -1, 397, 1095, 1098, 400, -1,
+ -1, -1, 1101, -1, 1103, 407, -1, 1106, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1288, -1, 1292, -1, 1294, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 1308, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1319, -1, -1, -1, -1, -1, -1, 1326, -1,
- -1, -1, -1, -1, -1, -1, 1334, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 858, 859, 860,
- 861, -1, 863, 864, -1, 1355, 1356, 4, 5, -1,
- -1, -1, 873, 10, 875, 876, -1, -1, 15, -1,
- 17, 18, 883, 884, -1, -1, -1, 24, -1, -1,
- 27, -1, -1, -1, -1, 896, -1, 34, 35, -1,
- 37, -1, 39, 1393, -1, -1, -1, 44, -1, 46,
- 1400, -1, 49, -1, -1, 52, -1, -1, -1, -1,
- -1, -1, -1, 60, -1, -1, 63, -1, 65, 66,
- 67, 68, 1422, -1, -1, -1, -1, -1, -1, 76,
- 77, -1, 79, 80, 81, -1, 83, 84, 85, 86,
- 87, 88, -1, 90, 91, 92, 107, 108, 109, 110,
- 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
- 131, 132, 133, 134, 135, 136, 137, 138, 139, 140,
- 141, 142, 143, 144, 145, 146, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1133, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1011, -1, -1, -1, -1, 1016, 1017, -1, 1019, -1,
- -1, -1, -1, -1, -1, -1, 1027, 107, 108, 109,
- 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
- 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
- 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
- 140, 141, 142, 143, 144, 145, 146, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 1160,
+ -1, 1162, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1177, -1,
+ 1179, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1195, -1, -1, -1,
+ 1201, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 666, 667, -1, -1, 1215, -1, 672, -1, -1, -1,
+ -1, -1, 1223, -1, 1225, 1226, -1, 529, 530, -1,
+ -1, 687, -1, 689, -1, 691, -1, 693, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 550, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 567, -1, -1, -1, -1,
+ 1271, -1, -1, -1, -1, -1, -1, 1278, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1290, -1, 1294, -1, 1296, -1, -1, -1, -1,
+ -1, -1, -1, -1, 606, -1, -1, -1, 610, 1310,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1321, -1, -1, -1, -1, -1, -1, 1328,
+ -1, -1, -1, -1, -1, -1, -1, 1336, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1357, 1358, -1, -1,
+ -1, 108, 109, 110, 111, 112, 113, 114, -1, 116,
+ 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
+ 137, 138, 139, -1, 1395, 142, 143, 144, 145, 146,
+ -1, 1402, 858, 859, 860, 861, -1, 863, 864, -1,
+ -1, -1, -1, -1, -1, -1, -1, 873, -1, 875,
+ 876, -1, -1, 1424, -1, -1, -1, 883, 884, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 896, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 761,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 781,
+ -1, 783, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 820, -1,
+ -1, 823, -1, -1, -1, -1, -1, -1, -1, -1,
+ 832, -1, -1, -1, -1, -1, 838, -1, -1, 841,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1011, -1, -1, -1, -1,
+ 1016, 1017, -1, 1019, -1, -1, -1, -1, -1, 1025,
+ -1, -1, 1028, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
+ 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1188, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1203, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 989, -1, -1,
+ -1, -1, -1, -1, -1, -1, 998, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1190, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 1205,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1284, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1073, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1312, -1, -1, 1315, 1316, -1, 1318, -1, -1,
- -1, 1322, 1323, -1, 1325, -1, 1327, -1, -1, 1330,
- 1331, -1, 1333, -1, 1335, -1, 1337, 1338, -1, 1340,
- 1341, -1, 1343, 1344, -1, 1346, -1, 1348, 1349, -1,
- 1351, -1, 1353, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1096, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1392, -1, 1394, 1395, -1, 1397, 1398, 1399, -1,
- 1401, 1402, 1403, 1404, -1, -1, -1, -1, -1, -1,
+ 1286, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1143, -1, -1, 1146, -1, -1, -1, 1150, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 1314, 1161,
+ -1, 1317, 1318, -1, 1320, -1, -1, -1, 1324, 1325,
+ -1, 1327, -1, 1329, -1, -1, 1332, 1333, -1, 1335,
+ -1, 1337, -1, 1339, 1340, -1, 1342, 1343, -1, 1345,
+ 1346, -1, 1348, -1, 1350, 1351, -1, 1353, -1, 1355,
+ -1, -1, -1, -1, 1206, 1207, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1219, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1421, -1, 1423
+ -1, -1, -1, -1, -1, -1, -1, -1, 1394, -1,
+ 1396, 1397, -1, 1399, 1400, 1401, -1, 1403, 1404, 1405,
+ 1406, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1423, -1, 1425
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -2064,47 +2080,47 @@ static const yytype_uint16 yystos[] =
203, 482, 482, 204, 207, 202, 207, 204, 204, 203,
203, 204, 204, 512, 203, 203, 203, 203, 203, 203,
203, 238, 425, 429, 203, 172, 267, 267, 203, 373,
- 203, 7, 11, 12, 13, 256, 257, 386, 203, 203,
- 203, 180, 195, 196, 203, 218, 220, 223, 229, 234,
- 229, 234, 234, 234, 169, 226, 169, 233, 184, 205,
- 237, 494, 167, 385, 205, 431, 204, 383, 429, 513,
- 516, 204, 204, 204, 204, 259, 419, 419, 259, 259,
- 259, 202, 259, 204, 168, 198, 203, 204, 204, 204,
- 204, 209, 209, 209, 209, 204, 204, 230, 203, 207,
- 203, 204, 330, 507, 202, 204, 514, 8, 282, 284,
- 281, 284, 282, 283, 284, 203, 203, 266, 281, 180,
- 197, 198, 223, 229, 234, 229, 234, 234, 234, 169,
- 227, 260, 203, 7, 11, 12, 13, 14, 69, 426,
- 427, 428, 203, 202, 384, 208, 429, 516, 203, 204,
- 272, 202, 204, 270, 202, 207, 204, 275, 202, 204,
- 204, 392, 198, 204, 204, 204, 209, 204, 330, 202,
- 504, 204, 514, 514, 7, 11, 12, 13, 14, 69,
- 89, 208, 252, 253, 254, 255, 261, 265, 305, 205,
- 285, 208, 281, 305, 285, 208, 283, 285, 267, 36,
- 208, 305, 393, 394, 229, 234, 234, 234, 169, 228,
- 203, 266, 203, 385, 202, 202, 204, 204, 270, 207,
- 204, 275, 204, 259, 204, 207, 207, 202, 204, 203,
- 204, 262, 204, 505, 259, 266, 266, 208, 108, 109,
- 110, 111, 112, 113, 114, 116, 117, 118, 119, 120,
- 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
- 131, 132, 133, 134, 135, 136, 137, 138, 139, 142,
- 143, 144, 145, 146, 298, 107, 115, 140, 141, 286,
- 289, 298, 107, 115, 140, 141, 291, 294, 298, 203,
- 393, 205, 395, 234, 267, 203, 208, 494, 507, 203,
- 203, 204, 262, 204, 296, 204, 204, 204, 204, 203,
- 204, 204, 204, 204, 204, 203, 204, 207, 330, 259,
- 207, 202, 267, 203, 22, 238, 261, 297, 303, 304,
- 203, 20, 238, 253, 287, 299, 300, 303, 287, 21,
- 238, 253, 288, 301, 302, 303, 288, 238, 253, 290,
- 303, 238, 292, 299, 303, 287, 238, 293, 301, 303,
- 293, 238, 295, 303, 203, 504, 259, 259, 259, 204,
- 259, 202, 259, 259, 204, 259, 202, 204, 259, 259,
- 259, 204, 259, 202, 204, 259, 259, 259, 204, 259,
- 259, 204, 259, 259, 259, 204, 259, 259, 259, 259,
- 203, 203, 261, 180, 253, 303, 169, 253, 253, 303,
- 169, 253, 253, 303, 303, 505, 259, 203, 259, 204,
- 259, 204, 259, 259, 204, 259, 203, 259, 259, 259,
- 259, 253, 258, 253, 259, 203, 259
+ 203, 7, 11, 12, 13, 238, 256, 257, 386, 203,
+ 203, 203, 180, 195, 196, 203, 218, 220, 223, 229,
+ 234, 229, 234, 234, 234, 169, 226, 169, 233, 184,
+ 205, 237, 494, 167, 385, 205, 431, 204, 383, 429,
+ 513, 516, 204, 204, 204, 204, 259, 419, 419, 259,
+ 259, 259, 259, 202, 259, 204, 168, 198, 203, 204,
+ 204, 204, 204, 209, 209, 209, 209, 204, 204, 230,
+ 203, 207, 203, 204, 330, 507, 202, 204, 514, 8,
+ 282, 284, 281, 284, 282, 283, 284, 203, 203, 266,
+ 281, 180, 197, 198, 223, 229, 234, 229, 234, 234,
+ 234, 169, 227, 260, 203, 7, 11, 12, 13, 14,
+ 69, 426, 427, 428, 203, 202, 384, 208, 429, 516,
+ 203, 204, 272, 202, 204, 270, 202, 207, 204, 275,
+ 202, 204, 204, 392, 198, 204, 204, 204, 209, 204,
+ 330, 202, 504, 204, 514, 514, 7, 11, 12, 13,
+ 14, 69, 89, 208, 252, 253, 254, 255, 261, 265,
+ 305, 205, 285, 208, 281, 305, 285, 208, 283, 285,
+ 267, 36, 208, 305, 393, 394, 229, 234, 234, 234,
+ 169, 228, 203, 266, 203, 385, 202, 202, 204, 204,
+ 270, 207, 204, 275, 204, 259, 204, 207, 207, 202,
+ 204, 203, 204, 262, 204, 505, 259, 266, 266, 208,
+ 108, 109, 110, 111, 112, 113, 114, 116, 117, 118,
+ 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
+ 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 142, 143, 144, 145, 146, 298, 107, 115, 140,
+ 141, 286, 289, 298, 107, 115, 140, 141, 291, 294,
+ 298, 203, 393, 205, 395, 234, 267, 203, 208, 494,
+ 507, 203, 203, 204, 262, 204, 296, 204, 204, 204,
+ 204, 203, 204, 204, 204, 204, 204, 203, 204, 207,
+ 330, 259, 207, 202, 267, 203, 22, 238, 261, 297,
+ 303, 304, 203, 20, 238, 253, 287, 299, 300, 303,
+ 287, 21, 238, 253, 288, 301, 302, 303, 288, 238,
+ 253, 290, 303, 238, 292, 299, 303, 287, 238, 293,
+ 301, 303, 293, 238, 295, 303, 203, 504, 259, 259,
+ 259, 204, 259, 202, 259, 259, 204, 259, 202, 204,
+ 259, 259, 259, 204, 259, 202, 204, 259, 259, 259,
+ 204, 259, 259, 204, 259, 259, 259, 204, 259, 259,
+ 259, 259, 203, 203, 261, 180, 253, 303, 169, 253,
+ 253, 303, 169, 253, 253, 303, 303, 505, 259, 203,
+ 259, 204, 259, 204, 259, 259, 204, 259, 203, 259,
+ 259, 259, 259, 253, 258, 253, 259, 203, 259
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
@@ -2156,30 +2172,30 @@ static const yytype_uint16 yyr1[] =
362, 363, 363, 364, 364, 364, 364, 365, 366, 366,
366, 366, 366, 367, 368, 369, 370, 371, 372, 373,
374, 375, 375, 375, 376, 377, 378, 379, 379, 380,
- 381, 382, 382, 383, 384, 385, 386, 387, 387, 388,
- 389, 390, 390, 391, 392, 392, 392, 392, 392, 393,
- 394, 395, 396, 396, 397, 398, 398, 398, 399, 400,
- 400, 401, 402, 402, 403, 404, 405, 406, 406, 407,
- 408, 409, 410, 410, 410, 410, 410, 411, 411, 412,
- 413, 414, 414, 415, 416, 417, 418, 419, 419, 419,
- 419, 420, 421, 422, 423, 424, 425, 426, 427, 428,
- 428, 428, 428, 428, 428, 429, 430, 431, 432, 432,
- 432, 433, 433, 434, 435, 435, 436, 437, 437, 438,
- 439, 440, 441, 441, 441, 442, 443, 444, 445, 446,
- 447, 448, 449, 450, 450, 450, 450, 451, 452, 452,
- 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
- 463, 464, 465, 466, 466, 466, 466, 466, 466, 466,
- 466, 466, 466, 466, 466, 467, 467, 468, 468, 468,
- 469, 470, 471, 472, 472, 473, 473, 473, 474, 475,
- 475, 476, 477, 477, 477, 477, 477, 477, 477, 477,
- 477, 477, 477, 477, 477, 477, 478, 478, 478, 478,
- 478, 478, 478, 479, 480, 480, 481, 482, 482, 482,
- 482, 482, 482, 482, 483, 484, 485, 486, 487, 488,
- 489, 490, 491, 492, 493, 494, 495, 496, 497, 497,
- 498, 499, 499, 499, 499, 499, 500, 501, 502, 502,
- 503, 504, 504, 504, 504, 505, 505, 505, 505, 506,
- 507, 508, 509, 510, 511, 511, 512, 513, 513, 514,
- 514, 514, 514, 515, 516
+ 381, 382, 382, 382, 383, 384, 385, 386, 387, 387,
+ 388, 389, 390, 390, 391, 392, 392, 392, 392, 392,
+ 393, 394, 395, 396, 396, 397, 398, 398, 398, 399,
+ 400, 400, 401, 402, 402, 403, 404, 405, 406, 406,
+ 407, 408, 409, 410, 410, 410, 410, 410, 411, 411,
+ 412, 413, 414, 414, 415, 416, 417, 418, 419, 419,
+ 419, 419, 420, 421, 422, 423, 424, 425, 426, 427,
+ 428, 428, 428, 428, 428, 428, 429, 430, 431, 432,
+ 432, 432, 433, 433, 434, 435, 435, 436, 437, 437,
+ 438, 439, 440, 441, 441, 441, 442, 443, 444, 445,
+ 446, 447, 448, 449, 450, 450, 450, 450, 451, 452,
+ 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
+ 462, 463, 464, 465, 466, 466, 466, 466, 466, 466,
+ 466, 466, 466, 466, 466, 466, 467, 467, 468, 468,
+ 468, 469, 470, 471, 472, 472, 473, 473, 473, 474,
+ 475, 475, 476, 477, 477, 477, 477, 477, 477, 477,
+ 477, 477, 477, 477, 477, 477, 477, 478, 478, 478,
+ 478, 478, 478, 478, 479, 480, 480, 481, 482, 482,
+ 482, 482, 482, 482, 482, 483, 484, 485, 486, 487,
+ 488, 489, 490, 491, 492, 493, 494, 495, 496, 497,
+ 497, 498, 499, 499, 499, 499, 499, 500, 501, 502,
+ 502, 503, 504, 504, 504, 504, 505, 505, 505, 505,
+ 506, 507, 508, 509, 510, 511, 511, 512, 513, 513,
+ 514, 514, 514, 514, 515, 516
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
@@ -2231,30 +2247,30 @@ static const yytype_uint8 yyr2[] =
10, 1, 1, 1, 1, 1, 1, 7, 0, 3,
5, 3, 3, 9, 7, 9, 1, 1, 1, 1,
7, 0, 3, 3, 1, 1, 5, 1, 1, 1,
- 7, 0, 3, 1, 1, 1, 1, 1, 1, 8,
- 10, 1, 1, 10, 0, 3, 5, 3, 2, 5,
- 1, 1, 1, 1, 5, 1, 1, 1, 8, 1,
- 1, 5, 1, 1, 8, 1, 5, 1, 1, 8,
- 1, 5, 0, 3, 5, 3, 3, 1, 1, 4,
- 1, 1, 1, 4, 1, 1, 7, 0, 3, 3,
- 3, 1, 1, 5, 1, 1, 9, 1, 5, 1,
- 1, 1, 1, 1, 1, 7, 1, 1, 1, 1,
- 1, 1, 1, 10, 1, 1, 10, 1, 1, 10,
- 10, 7, 0, 3, 3, 9, 7, 9, 10, 1,
- 1, 9, 1, 1, 1, 1, 1, 10, 1, 1,
- 7, 9, 1, 10, 7, 1, 10, 7, 1, 10,
- 7, 1, 9, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 3, 2,
- 1, 1, 4, 1, 1, 1, 2, 3, 4, 1,
- 3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 7, 0, 3, 3, 1, 1, 1, 1, 1, 1,
+ 8, 10, 1, 1, 10, 0, 3, 5, 3, 2,
+ 5, 1, 1, 1, 1, 5, 1, 1, 1, 8,
+ 1, 1, 5, 1, 1, 8, 1, 5, 1, 1,
+ 8, 1, 5, 0, 3, 5, 3, 3, 1, 1,
+ 4, 1, 1, 1, 4, 1, 1, 7, 0, 3,
+ 3, 3, 1, 1, 5, 1, 1, 9, 1, 5,
+ 1, 1, 1, 1, 1, 1, 7, 1, 1, 1,
+ 1, 1, 1, 1, 10, 1, 1, 10, 1, 1,
+ 10, 10, 7, 0, 3, 3, 9, 7, 9, 10,
+ 1, 1, 9, 1, 1, 1, 1, 1, 10, 1,
+ 1, 7, 9, 1, 10, 7, 1, 10, 7, 1,
+ 10, 7, 1, 9, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 3,
+ 2, 1, 1, 4, 1, 1, 1, 2, 3, 4,
+ 1, 3, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 4, 3, 1, 8, 0, 3, 3,
- 3, 5, 3, 2, 1, 1, 4, 1, 1, 4,
- 1, 4, 1, 4, 1, 4, 1, 4, 3, 1,
- 6, 0, 3, 3, 3, 2, 1, 4, 3, 1,
- 16, 1, 1, 1, 1, 0, 6, 3, 2, 1,
- 1, 9, 1, 4, 3, 1, 6, 1, 1, 0,
- 3, 3, 2, 1, 7
+ 1, 1, 1, 1, 4, 3, 1, 8, 0, 3,
+ 3, 3, 5, 3, 2, 1, 1, 4, 1, 1,
+ 4, 1, 4, 1, 4, 1, 4, 1, 4, 3,
+ 1, 6, 0, 3, 3, 3, 2, 1, 4, 3,
+ 1, 16, 1, 1, 1, 1, 0, 6, 3, 2,
+ 1, 1, 9, 1, 4, 3, 1, 6, 1, 1,
+ 0, 3, 3, 2, 1, 7
};
diff --git a/src/wkt2_grammar.y b/src/wkt2_grammar.y
index 4f30b5b2..fc2e8bf0 100644
--- a/src/wkt2_grammar.y
+++ b/src/wkt2_grammar.y
@@ -1073,6 +1073,7 @@ map_projection_parameter: parameter_keyword left_delimiter parameter_name
right_delimiter
opt_separator_param_unit_identifier_list:
+ | wkt_separator identifier opt_separator_identifier_list
| wkt_separator map_projection_parameter_unit opt_separator_identifier_list
parameter_keyword: T_PARAMETER
diff --git a/test/cli/Makefile.am b/test/cli/Makefile.am
index 4d11eaf3..46d9d36c 100644
--- a/test/cli/Makefile.am
+++ b/test/cli/Makefile.am
@@ -35,13 +35,13 @@ testprojinfo-check:
PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) $(TESTPROJINFO) $(PROJINFOEXE)
test27-check:
- $(TEST27) $(PROJEXE)
+ PROJ_LIB=$(PROJ_LIB) $(TEST27) $(PROJEXE)
test83-check:
- $(TEST83) $(PROJEXE)
+ PROJ_LIB=$(PROJ_LIB) $(TEST83) $(PROJEXE)
testproj-check:
- $(TESTPROJ) $(PROJEXE)
+ PROJ_LIB=$(PROJ_LIB) $(TESTPROJ) $(PROJEXE)
testvarious-check:
PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) $(TESTVARIOUS) $(CS2CSEXE)
diff --git a/test/cli/td_out.dist b/test/cli/td_out.dist
index ab0c0911..6bad8e57 100644
--- a/test/cli/td_out.dist
+++ b/test/cli/td_out.dist
@@ -7,6 +7,18 @@ As above, but without ntv1 everything goes through conus file.
111d00'00.000"W 44d00'00.000"N 0.0 111d0'2.788"W 43d59'59.725"N 0.000
111d00'00.000"W 39d00'00.000"N 0.0 111d0'2.604"W 38d59'59.912"N 0.000
##############################################################
+Test --area Canada NAD27 NAD83 (using ntv1_can)
+43d59'59.732"N 111d0'3.208"W 0.000
+* * inf
+##############################################################
+Test --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 (using ntv1_can)
+43d59'59.732"N 111d0'3.208"W 0.000
+* * inf
+##############################################################
+Test --area "USA - CONUS - onshore" NAD27 NAD83 (using conus)
+43d59'59.725"N 111d0'2.788"W 0.000
+38d59'59.912"N 111d0'2.604"W 0.000
+##############################################################
Test MD used where available
79d58'00.000"W 37d02'00.000"N 0.0 79d58'0.005"W 37d1'59.998"N 0.000
79d58'00.000"W 36d58'00.000"N 0.0 79d57'59.128"W 36d58'0.501"N 0.000
diff --git a/test/cli/testcct b/test/cli/testcct
index 3fb0dd95..686931ea 100755
--- a/test/cli/testcct
+++ b/test/cli/testcct
@@ -32,6 +32,133 @@ echo "Testing cct -d 8 +proj=merc +R=1" >> ${OUT}
echo "90 45" 0 | $EXE -d 8 +proj=merc +R=1 >>${OUT}
echo "" >>${OUT}
+# tests without specifying the number of decimals (by default: 10 for radians and degrees, 4 for meters)
+echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad" >> ${OUT}
+echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad >> ${OUT}
+
+echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg" >> ${OUT}
+echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg >> ${OUT}
+
+echo "Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km" >> ${OUT}
+echo 0.5 2 | $EXE -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km >> ${OUT}
+echo "" >> ${OUT}
+
+# tests for which the number of decimals has been specified (-d 6)
+echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad" >> ${OUT}
+echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad >> ${OUT}
+
+echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg" >> ${OUT}
+echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg >> ${OUT}
+
+echo "Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km" >> ${OUT}
+echo 0.5 2 | $EXE -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km >> ${OUT}
+echo "" >> ${OUT}
+
+echo "Test cct with object code initialization" >> ${OUT}
+echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE EPSG:8366 >>${OUT}
+
+echo "Test cct with object name initialization" >> ${OUT}
+echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE "ITRF2014 to ETRF2014 (1)" >>${OUT}
+
+echo "Test cct with object code initialization and file input" >> ${OUT}
+echo "3541657.3778 948984.2343 5201383.5231 2020.5" > a
+echo "3541658.0000 948985.0000 5201384.0000 2020.5" > b
+$EXE EPSG:8366 a b >>${OUT}
+/bin/rm a b
+
+cat > in.wkt <<EOF
+COORDINATEOPERATION["ITRF2014 to ETRF2014 (1)",
+ VERSION["EUREF-Eur"],
+ SOURCECRS[
+ GEODCRS["ITRF2014",
+ DYNAMIC[
+ FRAMEEPOCH[2010]],
+ DATUM["International Terrestrial Reference Frame 2014",
+ ELLIPSOID["GRS 1980",6378137,298.257222101,
+ LENGTHUNIT["metre",1]]],
+ PRIMEM["Greenwich",0,
+ ANGLEUNIT["degree",0.0174532925199433]],
+ CS[Cartesian,3],
+ AXIS["(X)",geocentricX,
+ ORDER[1],
+ LENGTHUNIT["metre",1]],
+ AXIS["(Y)",geocentricY,
+ ORDER[2],
+ LENGTHUNIT["metre",1]],
+ AXIS["(Z)",geocentricZ,
+ ORDER[3],
+ LENGTHUNIT["metre",1]],
+ ID["EPSG",7789]]],
+ TARGETCRS[
+ GEODCRS["ETRF2014",
+ DATUM["European Terrestrial Reference Frame 2014",
+ ELLIPSOID["GRS 1980",6378137,298.257222101,
+ LENGTHUNIT["metre",1]]],
+ PRIMEM["Greenwich",0,
+ ANGLEUNIT["degree",0.0174532925199433]],
+ CS[Cartesian,3],
+ AXIS["(X)",geocentricX,
+ ORDER[1],
+ LENGTHUNIT["metre",1]],
+ AXIS["(Y)",geocentricY,
+ ORDER[2],
+ LENGTHUNIT["metre",1]],
+ AXIS["(Z)",geocentricZ,
+ ORDER[3],
+ LENGTHUNIT["metre",1]],
+ ID["EPSG",8401]]],
+ METHOD["Time-dependent Position Vector tfm (geocentric)",
+ ID["EPSG",1053]],
+ PARAMETER["X-axis translation",0,
+ LENGTHUNIT["millimetre",0.001],
+ ID["EPSG",8605]],
+ PARAMETER["Y-axis translation",0,
+ LENGTHUNIT["millimetre",0.001],
+ ID["EPSG",8606]],
+ PARAMETER["Z-axis translation",0,
+ LENGTHUNIT["millimetre",0.001],
+ ID["EPSG",8607]],
+ PARAMETER["X-axis rotation",0,
+ ANGLEUNIT["milliarc-second",4.84813681109536E-09],
+ ID["EPSG",8608]],
+ PARAMETER["Y-axis rotation",0,
+ ANGLEUNIT["milliarc-second",4.84813681109536E-09],
+ ID["EPSG",8609]],
+ PARAMETER["Z-axis rotation",0,
+ ANGLEUNIT["milliarc-second",4.84813681109536E-09],
+ ID["EPSG",8610]],
+ PARAMETER["Scale difference",0,
+ SCALEUNIT["parts per billion",1E-09],
+ ID["EPSG",8611]],
+ PARAMETER["Rate of change of X-axis translation",0,
+ LENGTHUNIT["millimetres per year",3.16887651727315E-11],
+ ID["EPSG",1040]],
+ PARAMETER["Rate of change of Y-axis translation",0,
+ LENGTHUNIT["millimetres per year",3.16887651727315E-11],
+ ID["EPSG",1041]],
+ PARAMETER["Rate of change of Z-axis translation",0,
+ LENGTHUNIT["millimetres per year",3.16887651727315E-11],
+ ID["EPSG",1042]],
+ PARAMETER["Rate of change of X-axis rotation",0.085,
+ ANGLEUNIT["milliarc-seconds per year",1.53631468932076E-16],
+ ID["EPSG",1043]],
+ PARAMETER["Rate of change of Y-axis rotation",0.531,
+ ANGLEUNIT["milliarc-seconds per year",1.53631468932076E-16],
+ ID["EPSG",1044]],
+ PARAMETER["Rate of change of Z-axis rotation",-0.77,
+ ANGLEUNIT["milliarc-seconds per year",1.53631468932076E-16],
+ ID["EPSG",1045]],
+ PARAMETER["Rate of change of Scale difference",0,
+ SCALEUNIT["parts per billion per year",3.16887651727315E-17],
+ ID["EPSG",1046]],
+ PARAMETER["Parameter reference epoch",1989,
+ TIMEUNIT["year",31556925.445],
+ ID["EPSG",1047]]]
+EOF
+echo "Test cct with WKT in a file" >> ${OUT}
+echo "3541657.3778 948984.2343 5201383.5231 2020.5" | $EXE @in.wkt >>${OUT}
+rm in.wkt
+
# do 'diff' with distribution results
echo "diff ${OUT} with testcct_out.dist"
diff -u ${OUT} ${TEST_CLI_DIR}/testcct_out.dist
diff --git a/test/cli/testcct_out.dist b/test/cli/testcct_out.dist
index 44dd6964..7762ace7 100644
--- a/test/cli/testcct_out.dist
+++ b/test/cli/testcct_out.dist
@@ -1,3 +1,26 @@
Testing cct -d 8 +proj=merc +R=1
1.57079633 0.88137359 0.00000000 inf
+Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad
+ 0.5000000000 2.0000000000 0.0000 0.0000
+Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg
+ 0.5000000000 2.0000000000 0.0000 0.0000
+Testing echo 0.5 2 | cct -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km
+ 0.0005 0.0020 0.0000 0.0000
+
+Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad
+ 0.500000 2.000000 0.000000 0.0000
+Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=deg
+ 0.500000 2.000000 0.000000 0.0000
+Testing echo 0.5 2 | cct -d 6 -z 0 -t 0 +proj=pipeline +step +proj=unitconvert +xy_in=m +xy_out=km
+ 0.000500 0.002000 0.000000 0.0000
+
+Test cct with object code initialization
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
+Test cct with object name initialization
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
+Test cct with object code initialization and file input
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
+ 3541658.5334 948984.5160 5201383.7251 2020.5000
+Test cct with WKT in a file
+ 3541657.9112 948983.7503 5201383.2482 2020.5000
diff --git a/test/cli/testdatumfile b/test/cli/testdatumfile
index 16e4bbc3..5a013f12 100755
--- a/test/cli/testdatumfile
+++ b/test/cli/testdatumfile
@@ -60,6 +60,27 @@ $EXE +proj=latlong +ellps=clrk66 '+nadgrids="./dir with "" space/myconus"' \
EOF
echo "##############################################################" >> ${OUT}
+echo "Test --area Canada NAD27 NAD83 (using ntv1_can)" >> ${OUT}
+$EXE --area Canada NAD27 NAD83 >>${OUT} <<EOF
+44 -111
+39 -111
+EOF
+
+echo "##############################################################" >> ${OUT}
+echo "Test --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 (using ntv1_can)" >> ${OUT}
+$EXE --bbox -141.01,40.04,-47.74,86.46 NAD27 NAD83 >>${OUT} <<EOF
+44 -111
+39 -111
+EOF
+
+echo "##############################################################" >> ${OUT}
+echo "Test --area \"USA - CONUS - onshore\" NAD27 NAD83 (using conus)" >> ${OUT}
+$EXE --area "USA - CONUS - onshore" NAD27 NAD83 >>${OUT} <<EOF
+44 -111
+39 -111
+EOF
+
+echo "##############################################################" >> ${OUT}
echo Test MD used where available >> ${OUT}
#
$EXE +proj=latlong +ellps=clrk66 +nadgrids=MD,conus \
diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo
index 62713af5..c31cfef0 100755
--- a/test/cli/testprojinfo
+++ b/test/cli/testprojinfo
@@ -171,6 +171,10 @@ echo 'Testing -k datum EPSG:6326' >> ${OUT}
$EXE -k datum EPSG:6326 >>${OUT} 2>&1
echo "" >>${OUT}
+echo 'Testing -k ensemble WGS84' >> ${OUT}
+$EXE -k ensemble WGS84 >>${OUT} 2>&1
+echo "" >>${OUT}
+
echo 'Testing -k operation EPSG:8457 -o PROJ -q' >> ${OUT}
$EXE -k operation EPSG:8457 -o PROJ -q >>${OUT} 2>&1
echo "" >>${OUT}
diff --git a/test/cli/testprojinfo_out.dist b/test/cli/testprojinfo_out.dist
index 245bb258..8e8ef294 100644
--- a/test/cli/testprojinfo_out.dist
+++ b/test/cli/testprojinfo_out.dist
@@ -4,9 +4,16 @@ PROJ.4 string:
WKT2:2019 string:
GEOGCRS["WGS 84",
- DATUM["World Geodetic System 1984",
+ ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)"],
+ MEMBER["World Geodetic System 1984 (G730)"],
+ MEMBER["World Geodetic System 1984 (G873)"],
+ MEMBER["World Geodetic System 1984 (G1150)"],
+ MEMBER["World Geodetic System 1984 (G1674)"],
+ MEMBER["World Geodetic System 1984 (G1762)"],
ELLIPSOID["WGS 84",6378137,298.257223563,
- LENGTHUNIT["metre",1]]],
+ LENGTHUNIT["metre",1]],
+ ENSEMBLEACCURACY[2.0]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
@@ -59,9 +66,16 @@ GEODCRS["WGS 84",
Testing projinfo -o WKT2_2019 EPSG:4326
WKT2:2019 string:
GEOGCRS["WGS 84",
- DATUM["World Geodetic System 1984",
+ ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)"],
+ MEMBER["World Geodetic System 1984 (G730)"],
+ MEMBER["World Geodetic System 1984 (G873)"],
+ MEMBER["World Geodetic System 1984 (G1150)"],
+ MEMBER["World Geodetic System 1984 (G1674)"],
+ MEMBER["World Geodetic System 1984 (G1762)"],
ELLIPSOID["WGS 84",6378137,298.257223563,
- LENGTHUNIT["metre",1]]],
+ LENGTHUNIT["metre",1]],
+ ENSEMBLEACCURACY[2.0]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
@@ -102,9 +116,16 @@ GEODCRS["WGS 84",
WKT2:2019 string:
GEOGCRS["WGS 84",
- DATUM["World Geodetic System 1984",
+ ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)"],
+ MEMBER["World Geodetic System 1984 (G730)"],
+ MEMBER["World Geodetic System 1984 (G873)"],
+ MEMBER["World Geodetic System 1984 (G1150)"],
+ MEMBER["World Geodetic System 1984 (G1674)"],
+ MEMBER["World Geodetic System 1984 (G1762)"],
ELLIPSOID["WGS 84",6378137,298.257223563,
- LENGTHUNIT["metre",1]]],
+ LENGTHUNIT["metre",1]],
+ ENSEMBLEACCURACY[2.0]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
CS[ellipsoidal,2],
@@ -142,13 +163,61 @@ PROJJSON:
"$schema": "https://proj.org/schemas/v0.2/projjson.schema.json",
"type": "GeographicCRS",
"name": "WGS 84",
- "datum": {
- "type": "GeodeticReferenceFrame",
- "name": "World Geodetic System 1984",
+ "datum_ensemble": {
+ "name": "World Geodetic System 1984 ensemble",
+ "members": [
+ {
+ "name": "World Geodetic System 1984 (Transit)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1166
+ }
+ },
+ {
+ "name": "World Geodetic System 1984 (G730)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1152
+ }
+ },
+ {
+ "name": "World Geodetic System 1984 (G873)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1153
+ }
+ },
+ {
+ "name": "World Geodetic System 1984 (G1150)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1154
+ }
+ },
+ {
+ "name": "World Geodetic System 1984 (G1674)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1155
+ }
+ },
+ {
+ "name": "World Geodetic System 1984 (G1762)",
+ "id": {
+ "authority": "EPSG",
+ "code": 1156
+ }
+ }
+ ],
"ellipsoid": {
"name": "WGS 84",
"semi_major_axis": 6378137,
"inverse_flattening": 298.257223563
+ },
+ "accuracy": "2.0",
+ "id": {
+ "authority": "EPSG",
+ "code": 6326
}
},
"coordinate_system": {
@@ -317,7 +386,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (3)",
SCOPE["Historic record only - now superseded - see remarks."],
AREA["Canada - onshore and offshore - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon."],
BBOX[40.04,-141.01,86.46,-47.74]],
- ID["DERIVED_FROM(EPSG)",1312]]
+ ID["DERIVED_FROM(EPSG)",1312],
+ REMARK["Uses NTv1 method. Replaced in Quebec by code 1462 and elsewhere in 1997 by NTv2 (transformation code 1313). Input expects longitudes to be positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]]
-------------------------------------
Operation No. 2:
@@ -371,7 +441,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (4)",
SCOPE["Transformation of coordinates at 1m to 2m level of accuracy."],
AREA["Canada - onshore - Alberta; British Columbia; Manitoba; New Brunswick; Newfoundland and Labrador; Northwest Territories; Nova Scotia; Nunavut; Ontario; Prince Edward Island; Quebec; Saskatchewan; Yukon; offshore east coast."],
BBOX[40.04,-141.01,83.17,-47.74]],
- ID["DERIVED_FROM(EPSG)",1313]]
+ ID["DERIVED_FROM(EPSG)",1313],
+ REMARK["Uses NTv2 data files. Replaces NTv1 (transformation code 1312) except in Quebec. Input expects longitudes to be positive west; EPSG GeogCRS NAD27 (code 4267) and (code 4269) have longitudes positive east. May be used as tfm to WGS 84 - see code 1693."]]
-------------------------------------
Operation No. 3:
@@ -425,7 +496,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (1)",
SCOPE["Transformation of coordinates at 0.2m level of accuracy."],
AREA["United States (USA) - CONUS including EEZ -onshore and offshore - Alabama; Arizona; Arkansas; California; Colorado; Connecticut; Delaware; Florida; Georgia; Idaho; Illinois; Indiana; Iowa; Kansas; Kentucky; Louisiana; Maine; Maryland; Massachusetts; Michigan; Minnesota; Mississippi; Missouri; Montana; Nebraska; Nevada; New Hampshire; New Jersey; New Mexico; New York; North Carolina; North Dakota; Ohio; Oklahoma; Oregon; Pennsylvania; Rhode Island; South Carolina; South Dakota; Tennessee; Texas; Utah; Vermont; Virginia; Washington; West Virginia; Wisconsin; Wyoming. US Gulf of Mexico (GoM) OCS."],
BBOX[23.81,-129.17,49.38,-65.69]],
- ID["DERIVED_FROM(EPSG)",1241]]
+ ID["DERIVED_FROM(EPSG)",1241],
+ REMARK["Uses NADCON method which expects longitudes positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]]
-------------------------------------
Operation No. 4:
@@ -479,7 +551,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (2)",
SCOPE["Geodesy."],
AREA["United States (USA) - Alaska including EEZ."],
BBOX[47.88,167.65,74.71,-129.99]],
- ID["DERIVED_FROM(EPSG)",1243]]
+ ID["DERIVED_FROM(EPSG)",1243],
+ REMARK["Uses NADCON method which expects longitudes positive west; EPSG GeogCRS NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east. May be used as transformation to WGS 84 - see NAD27 to WGS 84 (85) (code 15864)."]]
-------------------------------------
Operation No. 5:
@@ -533,7 +606,8 @@ COORDINATEOPERATION["NAD27 to NAD83 (6)",
SCOPE["Transformation of coordinates at 1m to 2m level of accuracy."],
AREA["Canada - Quebec."],
BBOX[44.99,-79.85,62.62,-57.1]],
- ID["DERIVED_FROM(EPSG)",1573]]
+ ID["DERIVED_FROM(EPSG)",1573],
+ REMARK["Also distributed with file name QUE27-83.gsb. Replaces NAD27 to NAD83 (5) (code 1462). Uses NT method which expects longitudes positive west; EPSG GeogCRSs NAD27 (code 4267) and NAD83 (code 4269) have longitudes positive east."]]
-------------------------------------
Operation No. 6:
@@ -916,7 +990,7 @@ PROJ.4 string:
+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs
Testing RH2000 height to SWEREF99: projinfo -s EPSG:5613 -t EPSG:4977
-Candidate operations found: 1
+Candidate operations found: 2
-------------------------------------
Operation No. 1:
@@ -968,8 +1042,55 @@ COORDINATEOPERATION["Inverse of SWEREF99 to RH2000 height",
BBOX[55.28,10.93,69.07,24.17]],
ID["INVERSE(DERIVED_FROM(PROJ))","EPSG_4977_TO_EPSG_5613"]]
+-------------------------------------
+Operation No. 2:
+
+unknown id, Transformation from RH2000 height to SWEREF99 (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation
+
+PROJ string:
++proj=noop
+
+WKT2:2019 string:
+COORDINATEOPERATION["Transformation from RH2000 height to SWEREF99 (ballpark vertical transformation, without ellipsoid height to vertical height correction)",
+ SOURCECRS[
+ VERTCRS["RH2000 height",
+ DYNAMIC[
+ FRAMEEPOCH[2000]],
+ VDATUM["Rikets hojdsystem 2000"],
+ CS[vertical,1],
+ AXIS["gravity-related height (H)",up,
+ LENGTHUNIT["metre",1]],
+ ID["EPSG",5613]]],
+ TARGETCRS[
+ GEOGCRS["SWEREF99",
+ DATUM["SWEREF99",
+ ELLIPSOID["GRS 1980",6378137,298.257222101,
+ LENGTHUNIT["metre",1]]],
+ PRIMEM["Greenwich",0,
+ ANGLEUNIT["degree",0.0174532925199433]],
+ CS[ellipsoidal,3],
+ AXIS["geodetic latitude (Lat)",north,
+ ORDER[1],
+ ANGLEUNIT["degree",0.0174532925199433]],
+ AXIS["geodetic longitude (Lon)",east,
+ ORDER[2],
+ ANGLEUNIT["degree",0.0174532925199433]],
+ AXIS["ellipsoidal height (h)",up,
+ ORDER[3],
+ LENGTHUNIT["metre",1]],
+ ID["EPSG",4977]]],
+ METHOD["Change of Vertical Unit",
+ ID["EPSG",1069]],
+ PARAMETER["Unit conversion scalar",1,
+ SCALEUNIT["unity",1],
+ ID["EPSG",1051]],
+ USAGE[
+ SCOPE["unknown"],
+ AREA["World"],
+ BBOX[-90,-180,90,180]]]
+
Testing NAD83(2011) + NAVD88 height -> NAD83(2011) : projinfo -s EPSG:6349 -t EPSG:6319 --spatial-test intersects -o PROJ
-Candidate operations found: 2
+Candidate operations found: 3
-------------------------------------
Operation No. 1:
@@ -996,8 +1117,16 @@ PROJ string:
+step +proj=unitconvert +xy_in=rad +xy_out=deg
+step +proj=axisswap +order=2,1
+-------------------------------------
+Operation No. 3:
+
+unknown id, Transformation from NAVD88 height to NAD83(2011) (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation
+
+PROJ string:
++proj=noop
+
Testing NGF IGN69 height to RGF93: projinfo -s EPSG:5720 -t EPSG:4965 -o PROJ
-Candidate operations found: 1
+Candidate operations found: 2
-------------------------------------
Operation No. 1:
@@ -1011,6 +1140,14 @@ PROJ string:
+step +proj=unitconvert +xy_in=rad +xy_out=deg
+step +proj=axisswap +order=2,1
+-------------------------------------
+Operation No. 2:
+
+unknown id, Transformation from NGF-IGN69 height to RGF93 (ballpark vertical transformation, without ellipsoid height to vertical height correction), unknown accuracy, World, has ballpark transformation
+
+PROJ string:
++proj=noop
+
Testing EPSG:32631 --3d
PROJ.4 string:
+proj=utm +zone=31 +datum=WGS84 +units=m +no_defs +type=crs
@@ -1018,9 +1155,16 @@ PROJ.4 string:
WKT2:2019 string:
PROJCRS["WGS 84 / UTM zone 31N",
BASEGEOGCRS["WGS 84",
- DATUM["World Geodetic System 1984",
+ ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)"],
+ MEMBER["World Geodetic System 1984 (G730)"],
+ MEMBER["World Geodetic System 1984 (G873)"],
+ MEMBER["World Geodetic System 1984 (G1150)"],
+ MEMBER["World Geodetic System 1984 (G1674)"],
+ MEMBER["World Geodetic System 1984 (G1762)"],
ELLIPSOID["WGS 84",6378137,298.257223563,
- LENGTHUNIT["metre",1]]],
+ LENGTHUNIT["metre",1]],
+ ENSEMBLEACCURACY[2.0]],
PRIMEM["Greenwich",0,
ANGLEUNIT["degree",0.0174532925199433]],
ID["EPSG",4979]],
@@ -1179,6 +1323,27 @@ DATUM["World Geodetic System 1984",
LENGTHUNIT["metre",1]],
ID["EPSG",6326]]
+Testing -k ensemble WGS84
+WKT2:2019 string:
+ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)",
+ ID["EPSG",1166]],
+ MEMBER["World Geodetic System 1984 (G730)",
+ ID["EPSG",1152]],
+ MEMBER["World Geodetic System 1984 (G873)",
+ ID["EPSG",1153]],
+ MEMBER["World Geodetic System 1984 (G1150)",
+ ID["EPSG",1154]],
+ MEMBER["World Geodetic System 1984 (G1674)",
+ ID["EPSG",1155]],
+ MEMBER["World Geodetic System 1984 (G1762)",
+ ID["EPSG",1156]],
+ ELLIPSOID["WGS 84",6378137,298.257223563,
+ LENGTHUNIT["metre",1],
+ ID["EPSG",7030]],
+ ENSEMBLEACCURACY[2.0],
+ ID["EPSG",6326]]
+
Testing -k operation EPSG:8457 -o PROJ -q
+proj=pipeline
+step +proj=axisswap +order=2,1
@@ -1193,9 +1358,23 @@ Testing -k operation EPSG:8457 -o PROJ -q
Testing D_WGS_1984
WKT2:2019 string:
-DATUM["World Geodetic System 1984",
+ENSEMBLE["World Geodetic System 1984 ensemble",
+ MEMBER["World Geodetic System 1984 (Transit)",
+ ID["EPSG",1166]],
+ MEMBER["World Geodetic System 1984 (G730)",
+ ID["EPSG",1152]],
+ MEMBER["World Geodetic System 1984 (G873)",
+ ID["EPSG",1153]],
+ MEMBER["World Geodetic System 1984 (G1150)",
+ ID["EPSG",1154]],
+ MEMBER["World Geodetic System 1984 (G1674)",
+ ID["EPSG",1155]],
+ MEMBER["World Geodetic System 1984 (G1762)",
+ ID["EPSG",1156]],
ELLIPSOID["WGS 84",6378137,298.257223563,
- LENGTHUNIT["metre",1]],
+ LENGTHUNIT["metre",1],
+ ID["EPSG",7030]],
+ ENSEMBLEACCURACY[2.0],
ID["EPSG",6326]]
Testing -k datum D_WGS_1984
diff --git a/test/cli/testvarious b/test/cli/testvarious
index 292ee316..82be4992 100755
--- a/test/cli/testvarious
+++ b/test/cli/testvarious
@@ -1009,6 +1009,19 @@ $EXE -f %.3f EPSG:4686 EPSG:6247 -E >> ${OUT} <<EOF
4.8 -74.25
EOF
+echo "##############################################################" >> ${OUT}
+echo "Test effect of --authority (https://github.com/OSGeo/PROJ/issues/2442)" >> ${OUT}
+echo "This test might be a bit fragile if proj.db content changes" >> ${OUT}
+echo "The first result should use the 'WGS_1984_(ITRF08)_To_NAD_1983_2011' (ESRI:108363) operation" >> ${OUT}
+echo "and the second one a no-op" >> ${OUT}
+$EXE -E +proj=latlong +datum=WGS84 +no_defs +to +init=epsg:6342 >> ${OUT} <<EOF
+-105 40
+EOF
+$EXE --authority EPSG -E +proj=latlong +datum=WGS84 +no_defs +to +init=epsg:6342 >> ${OUT} <<EOF
+-105 40
+EOF
+
+
# Done!
# do 'diff' with distribution results
echo "diff ${OUT} with ${OUT}.dist"
diff --git a/test/cli/tv_out.dist b/test/cli/tv_out.dist
index 70b2ab6e..fe1aa452 100644
--- a/test/cli/tv_out.dist
+++ b/test/cli/tv_out.dist
@@ -485,3 +485,10 @@ Test EPSG:xxxx EPSG:yyyy filename
##############################################################
Test Colombia Urban
4.8 -74.25 122543.174 80859.033 0.000
+##############################################################
+Test effect of --authority (https://github.com/OSGeo/PROJ/issues/2442)
+This test might be a bit fragile if proj.db content changes
+The first result should use the 'WGS_1984_(ITRF08)_To_NAD_1983_2011' (ESRI:108363) operation
+and the second one a no-op
+-105 40 500000.86 4427756.50 0.00
+-105 40 500000.00 4427757.22 0.00
diff --git a/test/fuzzers/build.sh b/test/fuzzers/build.sh
index 1b2bf79c..37a207e0 100755
--- a/test/fuzzers/build.sh
+++ b/test/fuzzers/build.sh
@@ -69,12 +69,8 @@ build_fuzzer()
$LIB_FUZZING_ENGINE src/.libs/libproj.a $EXTRA_LIBS
}
-build_fuzzer standard_fuzzer test/fuzzers/standard_fuzzer.cpp
build_fuzzer proj_crs_to_crs_fuzzer test/fuzzers/proj_crs_to_crs_fuzzer.cpp
-echo "[libfuzzer]" > $OUT/standard_fuzzer.options
-echo "max_len = 10000" >> $OUT/standard_fuzzer.options
-
echo "[libfuzzer]" > $OUT/proj_crs_to_crs_fuzzer.options
echo "max_len = 10000" >> $OUT/proj_crs_to_crs_fuzzer.options
diff --git a/test/fuzzers/standard_fuzzer.cpp b/test/fuzzers/standard_fuzzer.cpp
deleted file mode 100644
index 468e8cbb..00000000
--- a/test/fuzzers/standard_fuzzer.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/******************************************************************************
- *
- * Project: proj.4
- * Purpose: Fuzzer
- * Author: Even Rouault, even.rouault at spatialys.com
- *
- ******************************************************************************
- * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.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 <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
-#include "proj.h"
-#include "proj_api.h"
-
-/* Standalone build:
-g++ -g -std=c++11 standard_fuzzer.cpp -o standard_fuzzer -fvisibility=hidden -DSTANDALONE ../../src/.libs/libproj.a -lpthread -lsqlite3 -I../../src -I../../include
-*/
-
-extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv);
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
-
-int LLVMFuzzerInitialize(int* /*argc*/, char*** argv)
-{
- const char* argv0 = (*argv)[0];
- char* path = pj_strdup(argv0);
- char* lastslash = strrchr(path, '/');
- if( lastslash )
- {
- *lastslash = '\0';
- setenv("PROJ_LIB", path, 1);
- }
- else
- {
- setenv("PROJ_LIB", ".", 1);
- }
- free(path);
- return 0;
-}
-
-int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
-{
- if( len > 1000 )
- {
-#ifdef STANDALONE
- fprintf(stderr, "Input too large\n");
-#endif
- return 0;
- }
-
- /* We expect the blob to be 3 lines: */
- /* source proj string\ndestination proj string\nx y */
- char* buf_dup = (char*)malloc(len+1);
- memcpy(buf_dup, buf, len);
- buf_dup[len] = 0;
- char* first_line = buf_dup;
- char* first_newline = strchr(first_line, '\n');
- if( !first_newline )
- {
- free(buf_dup);
- return 0;
- }
- first_newline[0] = 0;
- char* second_line = first_newline + 1;
- char* second_newline = strchr(second_line, '\n');
- if( !second_newline )
- {
- free(buf_dup);
- return 0;
- }
- second_newline[0] = 0;
- char* third_line = second_newline + 1;
- projPJ pj_src = pj_init_plus(first_line);
- if( !pj_src )
- {
- free(buf_dup);
- return 0;
- }
- projPJ pj_dst = pj_init_plus(second_line);
- if( !pj_dst )
- {
- free(buf_dup);
- pj_free(pj_src);
- proj_cleanup();
- return 0;
- }
- double x = 0, y = 0, z = 9;
- bool from_binary = false;
- bool has_z = false;
- if( strncmp(third_line, "BINARY_2D:", strlen("BINARY_2D:")) == 0 &&
- third_line - first_line + strlen("BINARY_2D:") + 2 * sizeof(double) <= len )
- {
- from_binary = true;
- memcpy(&x, third_line + strlen("BINARY_2D:"), sizeof(double));
- memcpy(&y, third_line + strlen("BINARY_2D:") + sizeof(double), sizeof(double));
- }
- else if( strncmp(third_line, "BINARY_3D:", strlen("BINARY_3D:")) == 0 &&
- third_line - first_line + strlen("BINARY_3D:") + 3 * sizeof(double) <= len )
- {
- from_binary = true;
- has_z = true;
- memcpy(&x, third_line + strlen("BINARY_3D:"), sizeof(double));
- memcpy(&y, third_line + strlen("BINARY_3D:") + sizeof(double), sizeof(double));
- memcpy(&z, third_line + strlen("BINARY_3D:") + 2 * sizeof(double), sizeof(double));
- }
- else if( sscanf(third_line, "%lf %lf", &x, &y) != 2 )
- {
- free(buf_dup);
- pj_free(pj_src);
- pj_free(pj_dst);
- proj_cleanup();
- return 0;
- }
-#ifdef STANDALONE
- fprintf(stderr, "src=%s\n", first_line);
- fprintf(stderr, "dst=%s\n", second_line);
- if( from_binary )
- {
- if( has_z )
- fprintf(stderr, "coord (from binary)=%.18g %.18g %.18g\n", x, y, z);
- else
- fprintf(stderr, "coord (from binary)=%.18g %.18g\n", x, y);
- }
- else
- fprintf(stderr, "coord=%s\n", third_line);
-#endif
- if( has_z )
- pj_transform( pj_src, pj_dst, 1, 0, &x, &y, &z );
- else
- pj_transform( pj_src, pj_dst, 1, 0, &x, &y, NULL );
- free(buf_dup);
- pj_free(pj_src);
- pj_free(pj_dst);
- proj_cleanup();
- return 0;
-}
-
-#ifdef STANDALONE
-
-int main(int argc, char* argv[])
-{
- if( argc < 2 )
- {
- const char str[] =
- "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\n2 49";
- int ret = LLVMFuzzerTestOneInput((const uint8_t*)(str), sizeof(str) - 1);
- if( ret )
- return ret;
-
- const char str2[] =
- "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\nBINARY_2D:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF";
- ret = LLVMFuzzerTestOneInput((const uint8_t*)(str2), sizeof(str2) - 1);
- if( ret )
- return ret;
-
- const char str3[] =
- "+proj=longlat +datum=WGS84 +nodefs\n+proj=longlat +datum=WGS84 +nodefs\nBINARY_3D:\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00";
- ret = LLVMFuzzerTestOneInput((const uint8_t*)(str3), sizeof(str3) - 1);
- if( ret )
- return ret;
-
- return 0;
- }
- else
- {
- int nRet = 0;
- void* buf = NULL;
- int nLen = 0;
- FILE* f = fopen(argv[1], "rb");
- if( !f )
- {
- fprintf(stderr, "%s does not exist.\n", argv[1]);
- exit(1);
- }
- fseek(f, 0, SEEK_END);
- nLen = (int)ftell(f);
- fseek(f, 0, SEEK_SET);
- buf = malloc(nLen);
- if( !buf )
- {
- fprintf(stderr, "malloc failed.\n");
- fclose(f);
- exit(1);
- }
- fread(buf, nLen, 1, f);
- fclose(f);
- nRet = LLVMFuzzerTestOneInput((const uint8_t*)(buf), nLen);
- free(buf);
- return nRet;
- }
-}
-
-#endif // STANDALONE
diff --git a/test/gie/builtins.gie b/test/gie/builtins.gie
index cfce5041..813b67bb 100644
--- a/test/gie/builtins.gie
+++ b/test/gie/builtins.gie
@@ -1423,9 +1423,9 @@ expect -0.001790143 -0.000895247
===============================================================================
-------------------------------------------------------------------------------
-operation +proj=etmerc +ellps=GRS80 +zone=30
+operation +proj=etmerc +ellps=GRS80
-------------------------------------------------------------------------------
-tolerance 0.1 mm
+tolerance 50 nm
accept 2 1
expect 222650.796797586 110642.229411933
accept 2 -1
@@ -1434,17 +1434,28 @@ accept -2 1
expect -222650.796797586 110642.229411933
accept -2 -1
expect -222650.796797586 -110642.229411933
+# near pole
+accept 30 89.9999
+expect 5.584698978 10001956.056248082
+# 3900 km from central meridian
+accept 44.69 35.37
+expect 4168136.489446198 4985511.302287407
direction inverse
accept 200 100
-expect 0.001796631 0.000904369
+expect 0.00179663056816 0.00090436947663
accept 200 -100
-expect 0.001796631 -0.000904369
+expect 0.00179663056816 -0.00090436947663
accept -200 100
-expect -0.001796631 0.000904369
+expect -0.00179663056816 0.00090436947663
accept -200 -100
-expect -0.001796631 -0.000904369
-
+expect -0.00179663056816 -0.00090436947663
+# near pole
+accept 6 1.0001e7
+expect 0.35596960759234 89.99135362646302
+# 3900 km from central meridian
+accept 4168136.489446198 4985511.302287407
+expect 44.69 35.37
===============================================================================
# Fahey
@@ -3355,30 +3366,54 @@ expect -0.001953415 -0.000820580
-------------------------------------------------------------------------------
operation +proj=merc +ellps=GRS80
-------------------------------------------------------------------------------
-tolerance 0.1 mm
+tolerance 0 m
+accept 0 0
+expect 0 0
+tolerance 50 nm
accept 2 1
-expect 222638.981586547 110579.965218250
+expect 222638.981586547 110579.965218249
accept 2 -1
expect 222638.981586547 -110579.965218249
accept -2 1
-expect -222638.981586547 110579.965218250
+expect -222638.981586547 110579.965218249
accept -2 -1
expect -222638.981586547 -110579.965218249
+# inflate tolerance by scale (k = 5.7e15)
+tolerance 3e8
+accept 0 89.99999999999999
+expect 0 235805185.015130176
+accept 0 -89.99999999999999
+expect 0 -235805185.015130176
direction inverse
+tolerance 0 m
+accept 0 0
+expect 0 0
+tolerance 50 nm
accept 200 100
-expect 0.001796631 0.000904369
+expect 0.00179663056824 0.00090436947704
accept 200 -100
-expect 0.001796631 -0.000904369
+expect 0.00179663056824 -0.00090436947704
accept -200 100
-expect -0.001796631 0.000904369
+expect -0.00179663056824 0.00090436947704
accept -200 -100
-expect -0.001796631 -0.000904369
+expect -0.00179663056824 -0.00090436947704
+accept 0 235805185.015130176
+expect 0 89.99999999999999
+accept 0 -235805185.015130176
+expect 0 -89.99999999999999
+accept 0 1e10
+expect 0 90
+accept 0 -1e10
+expect 0 -90
-------------------------------------------------------------------------------
operation +proj=merc +R=6400000
-------------------------------------------------------------------------------
-tolerance 0.1 mm
+tolerance 0 m
+accept 0 0
+expect 0 0
+tolerance 50 nm
accept 2 1
expect 223402.144255274 111706.743574944
accept 2 -1
@@ -3389,25 +3424,32 @@ accept -2 -1
expect -223402.144255274 -111706.743574944
direction inverse
+tolerance 0 m
+accept 0 0
+expect 0 0
+tolerance 50 nm
accept 200 100
-expect 0.001790493 0.000895247
+expect 0.00179049310978 0.00089524655486
accept 200 -100
-expect 0.001790493 -0.000895247
+expect 0.00179049310978 -0.00089524655486
accept -200 100
-expect -0.001790493 0.000895247
+expect -0.00179049310978 0.00089524655486
accept -200 -100
-expect -0.001790493 -0.000895247
-
+expect -0.00179049310978 -0.00089524655486
-------------------------------------------------------------------------------
operation +proj=merc +R=1
-------------------------------------------------------------------------------
# Test the numerical stability of the inverse spherical Mercator
-------------------------------------------------------------------------------
-tolerance 1e-15 m
-accept 0 1e-15
+tolerance 1e-17 m
+accept 0 57.295779513e-15
expect 0 1e-15
+direction inverse
+accept 0 1e-15
+expect 0 57.295779513e-15
+
===============================================================================
# Miller Oblated Stereographic
@@ -5377,6 +5419,32 @@ accept -200 -100
expect -0.001790493 -0.000895247
+-------------------------------------------------------------------------------
+operation +proj=stere +ellps=GRS80 +lat_0=90 +lat_ts=70
+-------------------------------------------------------------------------------
+tolerance 1e-15m
+accept 0 90
+expect 0 0
+roundtrip 1
+
+tolerance 0.1 mm
+accept 20 70
+expect 748315.3282 -2055979.4669
+roundtrip 1
+
+-------------------------------------------------------------------------------
+operation +proj=stere +ellps=GRS80 +lat_0=-90 +lat_ts=-70
+-------------------------------------------------------------------------------
+tolerance 1e-15m
+accept 0 -90
+expect 0 0
+roundtrip 1
+
+tolerance 0.1 mm
+accept 20 -70
+expect 748315.3282 2055979.4669
+roundtrip 1
+
===============================================================================
# Oblique Stereographic Alternative
# Azimuthal, Sph&Ell
@@ -5658,25 +5726,37 @@ expect -0.001790143 0.511651393
-------------------------------------------------------------------------------
operation +proj=tmerc +ellps=GRS80
-------------------------------------------------------------------------------
-tolerance 0.1 mm
+tolerance 50 nm
accept 2 1
-expect 222650.796795778 110642.229411927
+expect 222650.796797586 110642.229411933
accept 2 -1
-expect 222650.796795778 -110642.229411927
+expect 222650.796797586 -110642.229411933
accept -2 1
-expect -222650.796795778 110642.229411927
+expect -222650.796797586 110642.229411933
accept -2 -1
-expect -222650.796795778 -110642.229411927
+expect -222650.796797586 -110642.229411933
+# near pole
+accept 30 89.9999
+expect 5.584698978 10001956.056248082
+# 3900 km from central meridian
+accept 44.69 35.37
+expect 4168136.489446198 4985511.302287407
direction inverse
accept 200 100
-expect 0.001796631 0.000904369
+expect 0.00179663056816 0.00090436947663
accept 200 -100
-expect 0.001796631 -0.000904369
+expect 0.00179663056816 -0.00090436947663
accept -200 100
-expect -0.001796631 0.000904369
+expect -0.00179663056816 0.00090436947663
accept -200 -100
-expect -0.001796631 -0.000904369
+expect -0.00179663056816 -0.00090436947663
+# near pole
+accept 6 1.0001e7
+expect 0.35596960759234 89.99135362646302
+# 3900 km from central meridian
+accept 4168136.489446198 4985511.302287407
+expect 44.69 35.37
-------------------------------------------------------------------------------
operation +proj=tmerc +R=6400000
@@ -5691,6 +5771,74 @@ expect -223413.466406322 111769.145040597
accept -2 -1
expect -223413.466406322 -111769.145040597
+accept 0 0
+expect 0 0
+roundtrip 1
+
+accept 0 90
+expect 0 10053096.491487337276
+roundtrip 1
+
+accept 0 -90
+expect 0 -10053096.491487337276
+roundtrip 1
+
+accept 170 60
+expect 557076.820490954560 13361866.764138307422
+roundtrip 1
+
+accept 89 0.01
+expect 30344312.098578717560 64001.116414904580
+roundtrip 1
+
+accept 91 0.01
+expect 30344312.098578717560 20042191.866555366665
+roundtrip 1
+
+accept 179.999 0.01
+expect 111.701070433669 20105075.972255337983
+roundtrip 1
+
+accept -89 0.01
+expect -30344312.098578717560 64001.116414904580
+roundtrip 1
+
+accept -91 0.01
+expect -30344312.098578717560 20042191.866555366665
+roundtrip 1
+
+accept -179.999 0.01
+expect -111.701070433669 20105075.972255337983
+roundtrip 1
+
+accept 89 -0.01
+expect 30344312.098578717560 -64001.116414904580
+roundtrip 1
+
+accept 91 -0.01
+expect 30344312.098578717560 -20042191.866555366665
+roundtrip 1
+
+accept 179.999 -0.01
+expect 111.701070433669 -20105075.972255337983
+roundtrip 1
+
+accept -89 -0.01
+expect -30344312.098578717560 -64001.116414904580
+roundtrip 1
+
+accept -91 -0.01
+expect -30344312.098578717560 -20042191.866555366665
+roundtrip 1
+
+accept -179.999 -0.01
+expect -111.701070433669 -20105075.972255337983
+roundtrip 1
+
+accept 150 0
+expect 3515559.323737951461 20106192.982974674553
+roundtrip 1
+
direction inverse
accept 200 100
expect 0.001790493 0.000895247
@@ -5702,6 +5850,130 @@ accept -200 -100
expect -0.001790493 -0.000895247
-------------------------------------------------------------------------------
+# Approx tmerc on a almost spherical ellipsoid, lat_0 north hemisphere
+
+operation +proj=tmerc +a=6400000 +rf=1e12 +k=0.9 +lat_0=40 +approx
+-------------------------------------------------------------------------------
+tolerance 0.1 mm
+
+accept 0 -30
+expect 0 -7037167.5440
+roundtrip 1
+
+accept 1 -30
+expect 87064.5795 -7037547.4590
+roundtrip 1
+
+accept -1 -30
+expect -87064.5795 -7037547.4590
+roundtrip 1
+
+accept 0 30
+expect 0 -1005309.6491
+roundtrip 1
+
+accept 0 40
+expect 0 0
+roundtrip 1
+
+accept 1 41
+expect 75872.2182 100965.3718
+roundtrip 1
+
+-------------------------------------------------------------------------------
+# Approx tmerc on a sphere, lat_0 north hemisphere
+
+operation +proj=tmerc +R=6400000 +k=0.9 +lat_0=40
+-------------------------------------------------------------------------------
+tolerance 0.1 mm
+
+accept 0 -30
+expect 0 -7037167.5440
+roundtrip 1
+
+accept 1 -30
+expect 87064.5795 -7037547.4590
+roundtrip 1
+
+accept -1 -30
+expect -87064.5795 -7037547.4590
+roundtrip 1
+
+accept 0 30
+expect 0 -1005309.6491
+roundtrip 1
+
+accept 0 40
+expect 0 0
+roundtrip 1
+
+accept 1 41
+expect 75872.2182 100965.3718
+roundtrip 1
+
+-------------------------------------------------------------------------------
+# Approx tmerc on a almost spherical ellipsoid, lat_0 south hemisphere
+
+operation +proj=tmerc +a=6400000 +rf=1e12 +k=0.9 +lat_0=-40 +approx
+-------------------------------------------------------------------------------
+tolerance 0.1 mm
+
+accept 0 -30
+expect 0 1005309.6491
+roundtrip 1
+
+accept 1 -30
+expect 87064.5795 1004929.7341
+roundtrip 1
+
+accept -1 -30
+expect -87064.5795 1004929.7341
+roundtrip 1
+
+accept 0 30
+expect 0 7037167.5440
+roundtrip 1
+
+accept 0 -40
+expect 0 0
+roundtrip 1
+
+accept 1 -41
+expect 75872.2182 -100965.3718
+roundtrip 1
+
+-------------------------------------------------------------------------------
+# Approx tmerc on a sphere, lat_0 south hemisphere
+
+operation +proj=tmerc +R=6400000 +k=0.9 +lat_0=-40
+-------------------------------------------------------------------------------
+tolerance 0.1 mm
+
+accept 0 -30
+expect 0 1005309.6491
+roundtrip 1
+
+accept 1 -30
+expect 87064.5795 1004929.7341
+roundtrip 1
+
+accept -1 -30
+expect -87064.5795 1004929.7341
+roundtrip 1
+
+accept 0 30
+expect 0 7037167.5440
+roundtrip 1
+
+accept 0 -40
+expect 0 0
+roundtrip 1
+
+accept 1 -41
+expect 75872.2182 -100965.3718
+roundtrip 1
+
+-------------------------------------------------------------------------------
operation +proj=tmerc +R=1
-------------------------------------------------------------------------------
direction inverse
@@ -6601,4 +6873,46 @@ accept -74.25 4.8
expect 80859.033 122543.174
roundtrip 1
+===============================================================================
+# Geocentric/topocentric conversion
+===============================================================================
+
+# Test parameter and point from IOGP Publication 373-7-2 - Geomatics Guidance Note number 7, part 2 - October 2020
+operation +proj=topocentric +ellps=WGS84 +X_0=3652755.3058 +Y_0=319574.6799 +Z_0=5201547.3536
+tolerance 1 mm
+accept 3771793.968 140253.342 5124304.349
+expect -189013.869 -128642.040 -4220.171
+roundtrip 1
+
+===============================================================================
+# Geographic/topocentric conversion
+===============================================================================
+
+# Test parameter and point from IOGP Publication 373-7-2 - Geomatics Guidance Note number 7, part 2 - October 2020
+operation +proj=pipeline +step +proj=cart +ellps=WGS84 +step +proj=topocentric +ellps=WGS84 +lon_0=5 +lat_0=55 +h_0=200
+tolerance 1 mm
+accept 2.12955 53.80939444444444 73
+expect -189013.869 -128642.040 -4220.171
+roundtrip 1
+
+===============================================================================
+# Error cases of topocentric
+===============================================================================
+
+# missing X_0,Y_0,Z_0 or lon_0,lat_0
+operation +proj=topocentric +ellps=WGS84
+expect failure errno missing_args
+
+# missing Z_0
+operation +proj=topocentric +ellps=WGS84 +X_0=0 +Y_0=0
+expect failure errno missing_args
+
+# missing lat_0
+operation +proj=topocentric +ellps=WGS84 +lon_0=0
+expect failure errno missing_args
+
+# X_0 and lon_0 are mutually exclusive
+operation +proj=topocentric +ellps=WGS84 +X_0=0 +lon_0=0
+expect failure errno mutually_exclusive_args
+
</gie-strict>
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 2c0c19a9..3924f47d 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -69,17 +69,6 @@ set(PROJ_TEST_ENVIRONMENT
"PROJ_SOURCE_DATA=${PROJ_SOURCE_DIR}/data"
)
-add_executable(proj_pj_transform_test
- main.cpp
- pj_transform_test.cpp)
-target_link_libraries(proj_pj_transform_test
- GTest::gtest
- ${PROJ_LIBRARIES})
-add_test(NAME proj_pj_transform_test COMMAND proj_pj_transform_test)
-set_property(TEST proj_pj_transform_test
- PROPERTY ENVIRONMENT ${PROJ_TEST_ENVIRONMENT})
-
-
add_executable(proj_errno_string_test
main.cpp
proj_errno_string_test.cpp)
diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am
index 483cb0bd..4e931c2b 100644
--- a/test/unit/Makefile.am
+++ b/test/unit/Makefile.am
@@ -9,8 +9,7 @@ AM_CXXFLAGS = @CXX_WFLAGS@ @NO_ZERO_AS_NULL_POINTER_CONSTANT_FLAG@
PROJ_LIB ?= ../../data/for_tests
-noinst_PROGRAMS = pj_transform_test
-noinst_PROGRAMS += pj_phi2_test
+noinst_PROGRAMS = pj_phi2_test
noinst_PROGRAMS += proj_errno_string_test
noinst_PROGRAMS += proj_angular_io_test
noinst_PROGRAMS += proj_context_test
@@ -21,11 +20,6 @@ noinst_PROGRAMS += test_network
noinst_PROGRAMS += test_defmodel
noinst_PROGRAMS += test_tinshift
-pj_transform_test_SOURCES = pj_transform_test.cpp main.cpp
-pj_transform_test_LDADD = ../../src/libproj.la @GTEST_LIBS@
-
-pj_transform_test-check: pj_transform_test
- PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY=YES PROJ_LIB=$(PROJ_LIB) ./pj_transform_test
pj_phi2_test_SOURCES = pj_phi2_test.cpp main.cpp
pj_phi2_test_LDADD = ../../src/libproj.la @GTEST_LIBS@
@@ -84,6 +78,6 @@ test_tinshift_LDADD = ../../src/libproj.la @GTEST_LIBS@
test_tinshift-check: test_tinshift
PROJ_LIB=$(PROJ_LIB) ./test_tinshift
-check-local: pj_transform_test-check pj_phi2_test-check proj_errno_string_test-check \
+check-local: pj_phi2_test-check proj_errno_string_test-check \
proj_angular_io_test-check proj_context_test-check test_cpp_api-check \
gie_self_tests-check test_network-check test_defmodel-check test_tinshift-check
diff --git a/test/unit/gie_self_tests.cpp b/test/unit/gie_self_tests.cpp
index 6f1b3c32..f9252137 100644
--- a/test/unit/gie_self_tests.cpp
+++ b/test/unit/gie_self_tests.cpp
@@ -548,7 +548,7 @@ static void test_time(const char *args, double tol, double t_in, double t_exp) {
out = proj_trans(P, PJ_INV, out);
EXPECT_NEAR(out.xyzt.t, t_in, tol);
- pj_free(P);
+ proj_destroy(P);
proj_log_level(NULL, PJ_LOG_NONE);
}
diff --git a/test/unit/pj_phi2_test.cpp b/test/unit/pj_phi2_test.cpp
index c4db6e52..7ccbb01c 100644
--- a/test/unit/pj_phi2_test.cpp
+++ b/test/unit/pj_phi2_test.cpp
@@ -37,49 +37,58 @@
namespace {
TEST(PjPhi2Test, Basic) {
- projCtx ctx = pj_get_default_ctx();
+ PJ_CONTEXT *ctx = pj_get_default_ctx();
+
+ // Expectation is that only sane values of e (and nan is here reckoned to
+ // be sane) are passed to pj_phi2. Thus the return value with other values
+ // of e is "implementation dependent".
+
+ constexpr auto inf = std::numeric_limits<double>::infinity();
+ constexpr auto nan = std::numeric_limits<double>::quiet_NaN();
+
+ // Strict equality is demanded here.
+ EXPECT_EQ(M_PI_2, pj_phi2(ctx, +0.0, 0.0));
+ EXPECT_EQ(0.0, pj_phi2(ctx, 1.0, 0.0));
+ EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0));
+ // We don't expect pj_phi2 to be called with negative ts (since ts =
+ // exp(-psi)). However, in the current implementation it is odd in ts.
+ // N.B. ts = +0.0 and ts = -0.0 return different results.
+ EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, 0.0));
+ EXPECT_EQ(0.0, pj_phi2(ctx, -1.0, 0.0));
+ EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, 0.0));
+
+ constexpr double e = 0.2;
+ EXPECT_EQ(M_PI_2, pj_phi2(ctx, +0.0, e));
+ EXPECT_EQ(0.0, pj_phi2(ctx, 1.0, e));
+ EXPECT_EQ(-M_PI_2, pj_phi2(ctx, inf, e));
+ EXPECT_EQ(-M_PI_2, pj_phi2(ctx, -0.0, e));
+ EXPECT_EQ(0.0, pj_phi2(ctx, -1.0, e));
+ EXPECT_EQ(+M_PI_2, pj_phi2(ctx, -inf, e));
- EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, 0.0));
-
- EXPECT_NEAR(0.0, pj_phi2(ctx, 1.0, 0.0), 1e-16);
- EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, 1.0));
- EXPECT_DOUBLE_EQ(M_PI, pj_phi2(ctx, -1.0, 0.0));
- EXPECT_DOUBLE_EQ(M_PI_2, pj_phi2(ctx, 0.0, -1.0));
-
- EXPECT_NEAR(0.0, pj_phi2(ctx, 1.0, 1.0), 1e-16);
- EXPECT_DOUBLE_EQ(M_PI, pj_phi2(ctx, -1.0, -1.0));
-
- // TODO(schwehr): M_PI_4, M_PI_2, M_PI, M_E
- // https://www.gnu.org/software/libc/manual/html_node/Mathematical-Constants.html
-
- EXPECT_DOUBLE_EQ(-0.95445818456292697, pj_phi2(ctx, M_PI, 0.0));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, M_PI)));
- EXPECT_DOUBLE_EQ(4.0960508381527205, pj_phi2(ctx, -M_PI, 0.0));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, -M_PI)));
-
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, M_PI, M_PI)));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, -M_PI, -M_PI)));
-}
-
-TEST(PjPhi2Test, AvoidUndefinedBehavior) {
- auto ctx = pj_get_default_ctx();
-
- const auto nan = std::numeric_limits<double>::quiet_NaN();
EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, 0.0)));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, e)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, +0.0, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, 1.0, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, -0.0, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, -1.0, nan)));
+ EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, nan)));
EXPECT_TRUE(std::isnan(pj_phi2(ctx, nan, nan)));
- // We do not really care about the values that follow.
- const auto inf = std::numeric_limits<double>::infinity();
-
- EXPECT_DOUBLE_EQ(-M_PI_2, pj_phi2(ctx, inf, 0.0));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, inf)));
-
- EXPECT_DOUBLE_EQ(4.7123889803846897, pj_phi2(ctx, -inf, 0.0));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, 0.0, -inf)));
-
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, inf, inf)));
- EXPECT_TRUE(std::isnan(pj_phi2(ctx, -inf, -inf)));
+ EXPECT_DOUBLE_EQ(M_PI / 3, pj_phi2(ctx, 1 / (sqrt(3.0) + 2), 0.0));
+ EXPECT_DOUBLE_EQ(M_PI / 4, pj_phi2(ctx, 1 / (sqrt(2.0) + 1), 0.0));
+ EXPECT_DOUBLE_EQ(M_PI / 6, pj_phi2(ctx, 1 / sqrt(3.0), 0.0));
+ EXPECT_DOUBLE_EQ(-M_PI / 3, pj_phi2(ctx, sqrt(3.0) + 2, 0.0));
+ EXPECT_DOUBLE_EQ(-M_PI / 4, pj_phi2(ctx, sqrt(2.0) + 1, 0.0));
+ EXPECT_DOUBLE_EQ(-M_PI / 6, pj_phi2(ctx, sqrt(3.0), 0.0));
+
+ // Generated with exp(e * atanh(e * sin(phi))) / (tan(phi) + sec(phi))
+ EXPECT_DOUBLE_EQ(M_PI / 3, pj_phi2(ctx, 0.27749174377027023413, e));
+ EXPECT_DOUBLE_EQ(M_PI / 4, pj_phi2(ctx, 0.42617788119104192995, e));
+ EXPECT_DOUBLE_EQ(M_PI / 6, pj_phi2(ctx, 0.58905302448626726064, e));
+ EXPECT_DOUBLE_EQ(-M_PI / 3, pj_phi2(ctx, 3.6037108218537833089, e));
+ EXPECT_DOUBLE_EQ(-M_PI / 4, pj_phi2(ctx, 2.3464380582241712935, e));
+ EXPECT_DOUBLE_EQ(-M_PI / 6, pj_phi2(ctx, 1.6976400399134411849, e));
}
} // namespace
diff --git a/test/unit/pj_transform_test.cpp b/test/unit/pj_transform_test.cpp
deleted file mode 100644
index ddb054f0..00000000
--- a/test/unit/pj_transform_test.cpp
+++ /dev/null
@@ -1,740 +0,0 @@
-/******************************************************************************
- *
- * 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 <proj.h>
-#include "proj_internal.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");
- ASSERT_TRUE(dst != nullptr);
- 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(proj_api_h, pj_set_searchpath) {
-
- const char *path = "/i_do/not/exit";
- pj_set_searchpath(1, &path);
- {
- auto info = proj_info();
- EXPECT_EQ(info.path_count, 1U);
- ASSERT_NE(info.paths, nullptr);
- ASSERT_NE(info.paths[0], nullptr);
- EXPECT_EQ(std::string(info.paths[0]), path);
- }
-
- pj_set_searchpath(0, nullptr);
- {
- auto info = proj_info();
- EXPECT_EQ(info.path_count, 0U);
- EXPECT_EQ(info.paths, nullptr);
- }
-}
-
-// ---------------------------------------------------------------------------
-
-TEST(proj_api_h, pj_set_finder) {
-
- const auto myfinder = [](const char *) -> const char * { return nullptr; };
- pj_set_finder(myfinder);
-
- pj_set_finder(nullptr);
-}
-
-// ---------------------------------------------------------------------------
-
-TEST(proj_api_h, default_fileapi) {
- auto ctx = pj_ctx_alloc();
- auto fid = pj_open_lib(ctx, "proj.db", "rb");
- ASSERT_NE(fid, nullptr);
- char header[6];
- ASSERT_EQ(pj_ctx_fread(ctx, header, 1, 6, fid), 6U);
- ASSERT_TRUE(memcmp(header, "SQLite", 6) == 0);
- ASSERT_EQ(pj_ctx_ftell(ctx, fid), 6);
- ASSERT_EQ(pj_ctx_fseek(ctx, fid, 0, SEEK_SET), 0);
- ASSERT_EQ(pj_ctx_ftell(ctx, fid), 0);
- pj_ctx_fclose(ctx, fid);
- pj_ctx_free(ctx);
-}
-
-// ---------------------------------------------------------------------------
-
-TEST(pj_transform_test, ob_tran_to_meter_as_dest) {
- auto src = pj_init_plus(
- "+ellps=WGS84 +a=57.29577951308232 +proj=eqc +lon_0=0.0 +no_defs");
- auto dst = pj_init_plus("+ellps=WGS84 +proj=ob_tran +o_proj=latlon "
- "+o_lon_p=0.0 +o_lat_p=90.0 +lon_0=360.0 "
- "+to_meter=0.0174532925199433 +no_defs");
- 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);
-}
-
-// ---------------------------------------------------------------------------
-
-struct Spy {
- bool gotInMyFOpen = false;
- bool gotInMyFRead = false;
- bool gotInMyFSeek = false;
- bool gotInMyFTell = false;
- bool gotInMyFClose = false;
-};
-
-struct MyFile {
- FILE *fp;
- Spy *spy;
-};
-
-static PAFile myFOpen(projCtx ctx, const char *filename, const char *access) {
- FILE *fp = fopen(filename, access);
- if (!fp)
- return nullptr;
- MyFile *myF = new MyFile;
- myF->spy = (Spy *)pj_ctx_get_app_data(ctx);
- myF->spy->gotInMyFOpen = true;
- myF->fp = fp;
- return reinterpret_cast<PAFile>(myF);
-}
-
-static size_t myFRead(void *buffer, size_t size, size_t nmemb, PAFile file) {
- MyFile *myF = reinterpret_cast<MyFile *>(file);
- myF->spy->gotInMyFRead = true;
- return fread(buffer, size, nmemb, myF->fp);
-}
-
-static int myFSeek(PAFile file, long offset, int whence) {
- MyFile *myF = reinterpret_cast<MyFile *>(file);
- myF->spy->gotInMyFSeek = true;
- return fseek(myF->fp, offset, whence);
-}
-
-static long myFTell(PAFile file) {
- MyFile *myF = reinterpret_cast<MyFile *>(file);
- myF->spy->gotInMyFTell = true;
- return ftell(myF->fp);
-}
-
-static void myFClose(PAFile file) {
- MyFile *myF = reinterpret_cast<MyFile *>(file);
- myF->spy->gotInMyFClose = true;
- fclose(myF->fp);
- delete myF;
-}
-
-TEST(proj_api_h, custom_fileapi) {
- auto ctx = pj_ctx_alloc();
- Spy spy;
- pj_ctx_set_app_data(ctx, &spy);
- projFileAPI myAPI = {myFOpen, myFRead, myFSeek, myFTell, myFClose};
- pj_ctx_set_fileapi(ctx, &myAPI);
- EXPECT_EQ(pj_ctx_get_fileapi(ctx), &myAPI);
- auto fid = pj_open_lib(ctx, "proj.db", "rb");
- ASSERT_NE(fid, nullptr);
- char header[6];
- ASSERT_EQ(pj_ctx_fread(ctx, header, 1, 6, fid), 6U);
- ASSERT_TRUE(memcmp(header, "SQLite", 6) == 0);
- ASSERT_EQ(pj_ctx_ftell(ctx, fid), 6);
- ASSERT_EQ(pj_ctx_fseek(ctx, fid, 0, SEEK_SET), 0);
- ASSERT_EQ(pj_ctx_ftell(ctx, fid), 0);
- pj_ctx_fclose(ctx, fid);
- pj_ctx_free(ctx);
- EXPECT_TRUE(spy.gotInMyFOpen);
- EXPECT_TRUE(spy.gotInMyFRead);
- EXPECT_TRUE(spy.gotInMyFSeek);
- EXPECT_TRUE(spy.gotInMyFTell);
- EXPECT_TRUE(spy.gotInMyFClose);
-}
-
-TEST(pj_transform_test, ob_tran_to_meter_as_srouce) {
- auto src = pj_init_plus("+ellps=WGS84 +proj=ob_tran +o_proj=latlon "
- "+o_lon_p=0.0 +o_lat_p=90.0 +lon_0=360.0 "
- "+to_meter=0.0174532925199433 +no_defs");
- auto dst = pj_init_plus(
- "+ellps=WGS84 +a=57.29577951308232 +proj=eqc +lon_0=0.0 +no_defs");
- 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);
-}
-
-} // namespace
diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp
index 5da6b369..c417371d 100644
--- a/test/unit/test_c_api.cpp
+++ b/test/unit/test_c_api.cpp
@@ -433,16 +433,27 @@ TEST_F(CApi, proj_as_wkt) {
ObjectKeeper keeper_crs4979(crs4979);
ASSERT_NE(crs4979, nullptr);
+ EXPECT_EQ(proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, nullptr), nullptr);
+
// STRICT=NO
{
- EXPECT_EQ(proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, nullptr), nullptr);
-
const char *const options[] = {"STRICT=NO", nullptr};
auto wkt = proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, options);
ASSERT_NE(wkt, nullptr);
EXPECT_TRUE(std::string(wkt).find("GEOGCS[\"WGS 84\"") == 0) << wkt;
}
+ // ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES
+ {
+ const char *const options[] = {
+ "ALLOW_ELLIPSOIDAL_HEIGHT_AS_VERTICAL_CRS=YES", nullptr};
+ auto wkt = proj_as_wkt(m_ctxt, crs4979, PJ_WKT1_GDAL, options);
+ ASSERT_NE(wkt, nullptr);
+ EXPECT_TRUE(std::string(wkt).find(
+ "COMPD_CS[\"WGS 84 + Ellipsoid (metre)\"") == 0)
+ << wkt;
+ }
+
// unsupported option
{
const char *const options[] = {"unsupported=yes", nullptr};
@@ -845,6 +856,13 @@ TEST_F(CApi, proj_create_from_database) {
EXPECT_EQ(proj_get_type(datum), PJ_TYPE_GEODETIC_REFERENCE_FRAME);
}
{
+ auto ensemble = proj_create_from_database(
+ m_ctxt, "EPSG", "6326", PJ_CATEGORY_DATUM_ENSEMBLE, false, nullptr);
+ ASSERT_NE(ensemble, nullptr);
+ ObjectKeeper keeper(ensemble);
+ EXPECT_EQ(proj_get_type(ensemble), PJ_TYPE_DATUM_ENSEMBLE);
+ }
+ {
// International Terrestrial Reference Frame 2008
auto datum = proj_create_from_database(
m_ctxt, "EPSG", "1061", PJ_CATEGORY_DATUM, false, nullptr);
@@ -4643,10 +4661,21 @@ TEST_F(CApi, proj_create_vertical_crs_ex) {
ObjectKeeper keeper_geog_crs(geog_crs);
ASSERT_NE(geog_crs, nullptr);
- auto P = proj_create_crs_to_crs_from_pj(m_ctxt, compound, geog_crs, nullptr,
- nullptr);
- ObjectKeeper keeper_P(P);
- ASSERT_NE(P, nullptr);
+ PJ_OPERATION_FACTORY_CONTEXT *ctxt =
+ proj_create_operation_factory_context(m_ctxt, nullptr);
+ ASSERT_NE(ctxt, nullptr);
+ ContextKeeper keeper_ctxt(ctxt);
+ proj_operation_factory_context_set_grid_availability_use(
+ m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED);
+ proj_operation_factory_context_set_spatial_criterion(
+ m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);
+ PJ_OBJ_LIST *operations =
+ proj_create_operations(m_ctxt, compound, geog_crs, ctxt);
+ ASSERT_NE(operations, nullptr);
+ ObjListKeeper keeper_operations(operations);
+ EXPECT_GE(proj_list_get_count(operations), 1);
+ auto P = proj_list_get(m_ctxt, operations, 0);
+ ObjectKeeper keeper_transform(P);
auto name = proj_get_name(P);
ASSERT_TRUE(name != nullptr);
@@ -4699,10 +4728,21 @@ TEST_F(CApi, proj_create_vertical_crs_ex_with_geog_crs) {
ObjectKeeper keeper_geog_crs(geog_crs);
ASSERT_NE(geog_crs, nullptr);
- auto P = proj_create_crs_to_crs_from_pj(m_ctxt, compound, geog_crs, nullptr,
- nullptr);
- ObjectKeeper keeper_P(P);
- ASSERT_NE(P, nullptr);
+ PJ_OPERATION_FACTORY_CONTEXT *ctxt =
+ proj_create_operation_factory_context(m_ctxt, nullptr);
+ ASSERT_NE(ctxt, nullptr);
+ ContextKeeper keeper_ctxt(ctxt);
+ proj_operation_factory_context_set_grid_availability_use(
+ m_ctxt, ctxt, PROJ_GRID_AVAILABILITY_IGNORED);
+ proj_operation_factory_context_set_spatial_criterion(
+ m_ctxt, ctxt, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);
+ PJ_OBJ_LIST *operations =
+ proj_create_operations(m_ctxt, compound, geog_crs, ctxt);
+ ASSERT_NE(operations, nullptr);
+ ObjListKeeper keeper_operations(operations);
+ EXPECT_GE(proj_list_get_count(operations), 1);
+ auto P = proj_list_get(m_ctxt, operations, 0);
+ ObjectKeeper keeper_transform(P);
auto name = proj_get_name(P);
ASSERT_TRUE(name != nullptr);
@@ -4732,10 +4772,13 @@ TEST_F(CApi, proj_create_vertical_crs_ex_with_geog_crs) {
ObjectKeeper keeper_compound_from_projjson(compound_from_projjson);
ASSERT_NE(compound_from_projjson, nullptr);
- auto P2 = proj_create_crs_to_crs_from_pj(m_ctxt, compound_from_projjson,
- geog_crs, nullptr, nullptr);
- ObjectKeeper keeper_P2(P2);
- ASSERT_NE(P2, nullptr);
+ PJ_OBJ_LIST *operations2 =
+ proj_create_operations(m_ctxt, compound_from_projjson, geog_crs, ctxt);
+ ASSERT_NE(operations2, nullptr);
+ ObjListKeeper keeper_operations2(operations2);
+ EXPECT_GE(proj_list_get_count(operations2), 1);
+ auto P2 = proj_list_get(m_ctxt, operations2, 0);
+ ObjectKeeper keeper_transform2(P2);
auto name_bis = proj_get_name(P2);
ASSERT_TRUE(name_bis != nullptr);
@@ -4841,9 +4884,16 @@ TEST_F(CApi, proj_create_derived_geographic_crs) {
const char *expected_wkt =
"GEOGCRS[\"my rotated CRS\",\n"
" BASEGEOGCRS[\"WGS 84\",\n"
- " DATUM[\"World Geodetic System 1984\",\n"
+ " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n"
+ " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G730)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G873)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n"
" ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
- " LENGTHUNIT[\"metre\",1]]],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " ENSEMBLEACCURACY[2.0]],\n"
" PRIMEM[\"Greenwich\",0,\n"
" ANGLEUNIT[\"degree\",0.0174532925199433]]],\n"
" DERIVINGCONVERSION[\"Pole rotation (GRIB convention)\",\n"
diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp
index a0fee905..cea5ff6c 100644
--- a/test/unit/test_crs.cpp
+++ b/test/unit/test_crs.cpp
@@ -414,6 +414,20 @@ TEST(crs, EPSG_4326_as_WKT1_ESRI_with_database) {
// ---------------------------------------------------------------------------
+TEST(crs, EPSG_4901_as_WKT1_ESRI_with_PRIMEM_unit_name_morphing) {
+ auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG");
+ auto crs = factory->createCoordinateReferenceSystem("4901");
+ WKTFormatterNNPtr f(WKTFormatter::create(
+ WKTFormatter::Convention::WKT1_ESRI, DatabaseContext::create()));
+ EXPECT_EQ(crs->exportToWKT(f.get()),
+ "GEOGCS[\"GCS_ATF_Paris\",DATUM[\"D_ATF\","
+ "SPHEROID[\"Plessis_1817\",6376523.0,308.64]],"
+ "PRIMEM[\"Paris_RGS\",2.33720833333333],"
+ "UNIT[\"Grad\",0.0157079632679489]]");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, EPSG_4326_as_WKT1_ESRI_without_database) {
auto crs = GeographicCRS::EPSG_4326;
WKTFormatterNNPtr f(
@@ -513,6 +527,34 @@ TEST(crs, EPSG_4979_as_WKT1_GDAL) {
// ---------------------------------------------------------------------------
+TEST(crs, EPSG_4979_as_WKT1_GDAL_with_ellipsoidal_height_as_vertical_crs) {
+ auto crs = GeographicCRS::EPSG_4979;
+ auto wkt = crs->exportToWKT(
+ &(WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL,
+ DatabaseContext::create())
+ ->setAllowEllipsoidalHeightAsVerticalCRS(true)));
+
+ // For LAS 1.4 WKT1...
+ EXPECT_EQ(wkt, "COMPD_CS[\"WGS 84 + Ellipsoid (metre)\",\n"
+ " GEOGCS[\"WGS 84\",\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[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4326\"]],\n"
+ " VERT_CS[\"Ellipsoid (metre)\",\n"
+ " VERT_DATUM[\"Ellipsoid\",2002],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Ellipsoidal height\",UP]]]");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, EPSG_4979_as_WKT1_ESRI) {
auto crs = GeographicCRS::EPSG_4979;
WKTFormatterNNPtr f(
@@ -2037,6 +2079,50 @@ TEST(crs, projectedCRS_as_WKT1_ESRI) {
// ---------------------------------------------------------------------------
+TEST(crs,
+ projectedCRS_3D_as_WKT1_GDAL_with_ellipsoidal_height_as_vertical_crs) {
+ auto dbContext = DatabaseContext::create();
+ auto crs = AuthorityFactory::create(dbContext, "EPSG")
+ ->createProjectedCRS("32631")
+ ->promoteTo3D(std::string(), dbContext);
+ auto wkt = crs->exportToWKT(
+ &(WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext)
+ ->setAllowEllipsoidalHeightAsVerticalCRS(true)));
+
+ // For LAS 1.4 WKT1...
+ EXPECT_EQ(wkt,
+ "COMPD_CS[\"WGS 84 / UTM zone 31N + Ellipsoid (metre)\",\n"
+ " PROJCS[\"WGS 84 / UTM zone 31N\",\n"
+ " GEOGCS[\"WGS 84\",\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[\"degree\",0.0174532925199433,\n"
+ " AUTHORITY[\"EPSG\",\"9122\"]],\n"
+ " AUTHORITY[\"EPSG\",\"4326\"]],\n"
+ " PROJECTION[\"Transverse_Mercator\"],\n"
+ " PARAMETER[\"latitude_of_origin\",0],\n"
+ " PARAMETER[\"central_meridian\",3],\n"
+ " PARAMETER[\"scale_factor\",0.9996],\n"
+ " PARAMETER[\"false_easting\",500000],\n"
+ " PARAMETER[\"false_northing\",0],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Easting\",EAST],\n"
+ " AXIS[\"Northing\",NORTH],\n"
+ " AUTHORITY[\"EPSG\",\"32631\"]],\n"
+ " VERT_CS[\"Ellipsoid (metre)\",\n"
+ " VERT_DATUM[\"Ellipsoid\",2002],\n"
+ " UNIT[\"metre\",1,\n"
+ " AUTHORITY[\"EPSG\",\"9001\"]],\n"
+ " AXIS[\"Ellipsoidal height\",UP]]]");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, projectedCRS_with_ESRI_code_as_WKT1_ESRI) {
auto dbContext = DatabaseContext::create();
auto crs = AuthorityFactory::create(dbContext, "ESRI")
@@ -2107,6 +2193,53 @@ TEST(crs, projectedCRS_as_PROJ_string) {
// ---------------------------------------------------------------------------
+TEST(crs, projectedCRS_3D_is_WKT1_equivalent_to_WKT2) {
+ auto dbContext = DatabaseContext::create();
+
+ // "Illegal" WKT1 with a Projected 3D CRS
+ auto wkt1 = "PROJCS[\"WGS 84 / UTM zone 16N [EGM08-1]\","
+ "GEOGCS[\"WGS 84 / UTM zone 16N [EGM08-1]\","
+ "DATUM[\"WGS84\",SPHEROID[\"WGS84\",6378137.000,298.257223563,"
+ "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],"
+ "PRIMEM[\"Greenwich\",0.0000000000000000,"
+ "AUTHORITY[\"EPSG\",\"8901\"]],"
+ "UNIT[\"Degree\",0.01745329251994329547,"
+ "AUTHORITY[\"EPSG\",\"9102\"]],AUTHORITY[\"EPSG\",\"32616\"]],"
+ "UNIT[\"Meter\",1.00000000000000000000,"
+ "AUTHORITY[\"EPSG\",\"9001\"]],"
+ "PROJECTION[\"Transverse_Mercator\"],"
+ "PARAMETER[\"latitude_of_origin\",0.0000000000000000],"
+ "PARAMETER[\"central_meridian\",-87.0000000002777938],"
+ "PARAMETER[\"scale_factor\",0.9996000000000000],"
+ "PARAMETER[\"false_easting\",500000.000],"
+ "PARAMETER[\"false_northing\",0.000],"
+ "AXIS[\"Easting\",EAST],"
+ "AXIS[\"Northing\",NORTH],"
+ "AXIS[\"Height\",UP],"
+ "AUTHORITY[\"EPSG\",\"32616\"]]";
+
+ auto obj = WKTParser()
+ .setStrict(false)
+ .attachDatabaseContext(dbContext)
+ .createFromWKT(wkt1);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ WKTFormatterNNPtr f(
+ WKTFormatter::create(WKTFormatter::Convention::WKT2_2019));
+ auto wkt2 = crs->exportToWKT(f.get());
+ auto obj2 =
+ WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt2);
+ auto crs2 = nn_dynamic_pointer_cast<ProjectedCRS>(obj2);
+ ASSERT_TRUE(crs2 != nullptr);
+
+ EXPECT_TRUE(crs->isEquivalentTo(
+ crs2.get(),
+ IComparable::Criterion::EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS));
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, projectedCRS_Krovak_EPSG_5221_as_PROJ_string) {
auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG");
auto crs = factory->createProjectedCRS("5221");
@@ -4750,6 +4883,18 @@ static DerivedGeographicCRSNNPtr createDerivedGeographicCRS() {
// ---------------------------------------------------------------------------
+TEST(crs, derivedGeographicCRS_basic) {
+
+ auto derivedCRS = createDerivedGeographicCRS();
+ EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get()));
+ EXPECT_FALSE(derivedCRS->isEquivalentTo(
+ derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo(
+ derivedCRS.get(), IComparable::Criterion::EQUIVALENT));
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, derivedGeographicCRS_WKT2) {
auto expected = "GEODCRS[\"WMO Atlantic Pole\",\n"
@@ -4950,6 +5095,18 @@ static DerivedGeodeticCRSNNPtr createDerivedGeodeticCRS() {
// ---------------------------------------------------------------------------
+TEST(crs, derivedGeodeticCRS_basic) {
+
+ auto derivedCRS = createDerivedGeodeticCRS();
+ EXPECT_TRUE(derivedCRS->isEquivalentTo(derivedCRS.get()));
+ EXPECT_FALSE(derivedCRS->isEquivalentTo(
+ derivedCRS->baseCRS().get(), IComparable::Criterion::EQUIVALENT));
+ EXPECT_FALSE(derivedCRS->baseCRS()->isEquivalentTo(
+ derivedCRS.get(), IComparable::Criterion::EQUIVALENT));
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, derivedGeodeticCRS_WKT2) {
auto expected = "GEODCRS[\"Derived geodetic CRS\",\n"
@@ -5796,6 +5953,31 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) {
CoordinateOperationContext::IntermediateCRSUse::NEVER),
crs_5340);
}
+
+ // Check that we get the same result from an EPSG code and a CRS created
+ // from its WKT1 representation.
+ {
+ // Pulkovo 1942 / CS63 zone A2
+ auto crs = factory->createCoordinateReferenceSystem("2936");
+
+ // Two candidate transformations found, so not picking up any
+ EXPECT_EQ(crs->createBoundCRSToWGS84IfPossible(
+ dbContext,
+ CoordinateOperationContext::IntermediateCRSUse::NEVER),
+ crs);
+
+ auto wkt = crs->exportToWKT(
+ WKTFormatter::create(WKTFormatter::Convention::WKT1_GDAL, dbContext)
+ .get());
+ auto obj =
+ WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs_from_wkt = nn_dynamic_pointer_cast<CRS>(obj);
+ ASSERT_TRUE(crs_from_wkt != nullptr);
+ EXPECT_EQ(crs_from_wkt->createBoundCRSToWGS84IfPossible(
+ dbContext,
+ CoordinateOperationContext::IntermediateCRSUse::NEVER),
+ crs_from_wkt);
+ }
}
// ---------------------------------------------------------------------------
diff --git a/test/unit/test_factory.cpp b/test/unit/test_factory.cpp
index 1005d49b..ff86c4d3 100644
--- a/test/unit/test_factory.cpp
+++ b/test/unit/test_factory.cpp
@@ -531,8 +531,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geographic2D) {
EXPECT_EQ(gcrs->identifiers()[0]->code(), "4326");
EXPECT_EQ(*(gcrs->identifiers()[0]->codeSpace()), "EPSG");
EXPECT_EQ(*(gcrs->name()->description()), "WGS 84");
- EXPECT_TRUE(
- gcrs->datum()->isEquivalentTo(factory->createDatum("6326").get()));
+ ASSERT_TRUE(gcrs->datum() == nullptr);
+ ASSERT_TRUE(gcrs->datumEnsemble() != nullptr);
+ EXPECT_TRUE(gcrs->datumEnsemble()->isEquivalentTo(
+ factory->createDatumEnsemble("6326").get()));
EXPECT_TRUE(gcrs->coordinateSystem()->isEquivalentTo(
factory->createCoordinateSystem("6422").get()));
auto domain = crs->domains()[0];
@@ -566,8 +568,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geographic3D) {
EXPECT_EQ(gcrs->identifiers()[0]->code(), "4979");
EXPECT_EQ(*(gcrs->identifiers()[0]->codeSpace()), "EPSG");
EXPECT_EQ(*(gcrs->name()->description()), "WGS 84");
- EXPECT_TRUE(
- gcrs->datum()->isEquivalentTo(factory->createDatum("6326").get()));
+ ASSERT_TRUE(gcrs->datum() == nullptr);
+ ASSERT_TRUE(gcrs->datumEnsemble() != nullptr);
+ EXPECT_TRUE(gcrs->datumEnsemble()->isEquivalentTo(
+ factory->createDatumEnsemble("6326").get()));
EXPECT_TRUE(gcrs->coordinateSystem()->isEquivalentTo(
factory->createCoordinateSystem("6423").get()));
}
@@ -582,8 +586,10 @@ TEST(factory, AuthorityFactory_createGeodeticCRS_geocentric) {
EXPECT_EQ(crs->identifiers()[0]->code(), "4978");
EXPECT_EQ(*(crs->identifiers()[0]->codeSpace()), "EPSG");
EXPECT_EQ(*(crs->name()->description()), "WGS 84");
- EXPECT_TRUE(
- crs->datum()->isEquivalentTo(factory->createDatum("6326").get()));
+ ASSERT_TRUE(crs->datum() == nullptr);
+ ASSERT_TRUE(crs->datumEnsemble() != nullptr);
+ EXPECT_TRUE(crs->datumEnsemble()->isEquivalentTo(
+ factory->createDatumEnsemble("6326").get()));
EXPECT_TRUE(crs->coordinateSystem()->isEquivalentTo(
factory->createCoordinateSystem("6500").get()));
}
@@ -613,6 +619,20 @@ TEST(factory, AuthorityFactory_createVerticalCRS) {
// ---------------------------------------------------------------------------
+TEST(factory, AuthorityFactory_createVerticalCRS_with_datum_ensemble) {
+ auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG");
+ EXPECT_THROW(factory->createVerticalCRS("-1"),
+ NoSuchAuthorityCodeException);
+
+ auto crs = factory->createVerticalCRS("9451"); // BI height
+ ASSERT_TRUE(crs->datum() == nullptr);
+ ASSERT_TRUE(crs->datumEnsemble() != nullptr);
+ EXPECT_TRUE(crs->datumEnsemble()->isEquivalentTo(
+ factory->createDatumEnsemble("1288").get()));
+}
+
+// ---------------------------------------------------------------------------
+
TEST(factory, AuthorityFactory_createConversion) {
auto factory = AuthorityFactory::create(DatabaseContext::create(), "EPSG");
EXPECT_THROW(factory->createConversion("-1"), NoSuchAuthorityCodeException);
@@ -3062,6 +3082,12 @@ TEST(factory, createObjectsFromName) {
.size(),
1U);
+ // Exact name, but with other CRS that have an aliases to it ==> should
+ // match only the CRS with the given name, not those other CRS.
+ EXPECT_EQ(factory->createObjectsFromName("ETRS89 / UTM zone 32N", {}, false)
+ .size(),
+ 1U);
+
// Prime meridian
EXPECT_EQ(factoryEPSG->createObjectsFromName("Paris", {}, false, 2).size(),
1U);
@@ -3166,6 +3192,29 @@ TEST(factory, createObjectsFromName) {
.size(),
1U);
+ {
+ auto res = factory->createObjectsFromName(
+ "World Geodetic System 1984 ensemble",
+ {AuthorityFactory::ObjectType::DATUM_ENSEMBLE}, false);
+ EXPECT_EQ(res.size(), 1U);
+ if (!res.empty()) {
+ EXPECT_EQ(res.front()->getEPSGCode(), 6326);
+ EXPECT_TRUE(dynamic_cast<DatumEnsemble *>(res.front().get()) !=
+ nullptr);
+ }
+ }
+
+ {
+ auto res = factory->createObjectsFromName(
+ "World Geodetic System 1984 ensemble", {}, false);
+ EXPECT_EQ(res.size(), 1U);
+ if (!res.empty()) {
+ EXPECT_EQ(res.front()->getEPSGCode(), 6326);
+ EXPECT_TRUE(dynamic_cast<DatumEnsemble *>(res.front().get()) !=
+ nullptr);
+ }
+ }
+
const auto types = std::vector<AuthorityFactory::ObjectType>{
AuthorityFactory::ObjectType::PRIME_MERIDIAN,
AuthorityFactory::ObjectType::ELLIPSOID,
@@ -3187,6 +3236,7 @@ TEST(factory, createObjectsFromName) {
AuthorityFactory::ObjectType::CONVERSION,
AuthorityFactory::ObjectType::TRANSFORMATION,
AuthorityFactory::ObjectType::CONCATENATED_OPERATION,
+ AuthorityFactory::ObjectType::DATUM_ENSEMBLE,
};
for (const auto type : types) {
factory->createObjectsFromName("i_dont_exist", {type}, false, 1);
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 555d1159..4e903473 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -488,6 +488,62 @@ TEST(wkt_parse, wkt1_EPSG_4807_grad_mess) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse, wkt1_esri_EPSG_4901_grad) {
+ auto obj =
+ WKTParser()
+ .attachDatabaseContext(DatabaseContext::create())
+ .createFromWKT("GEOGCS[\"GCS_ATF_Paris\",DATUM[\"D_ATF\","
+ "SPHEROID[\"Plessis_1817\",6376523.0,308.64]],"
+ "PRIMEM[\"Paris_RGS\",2.33720833333333],"
+ "UNIT[\"Grad\",0.0157079632679489]]");
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ auto datum = crs->datum();
+ auto primem = datum->primeMeridian();
+ EXPECT_EQ(primem->nameStr(), "Paris RGS");
+ // The PRIMEM is really in degree
+ EXPECT_EQ(primem->longitude().unit(), UnitOfMeasure::DEGREE);
+ EXPECT_NEAR(primem->longitude().value(), 2.33720833333333, 1e-14);
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(wkt_parse, wkt2_epsg_org_EPSG_4901_PRIMEM_weird_sexagesimal_DMS) {
+ // Current epsg.org output may use the EPSG:9110 "sexagesimal DMS"
+ // unit and a DD.MMSSsss value, but this will likely be changed to
+ // use decimal degree.
+ auto obj = WKTParser().createFromWKT(
+ "GEOGCRS[\"ATF (Paris)\","
+ " DATUM[\"Ancienne Triangulation Francaise (Paris)\","
+ " ELLIPSOID[\"Plessis 1817\",6376523,308.64,"
+ " LENGTHUNIT[\"metre\",1,ID[\"EPSG\",9001]],"
+ " ID[\"EPSG\",7027]],"
+ " ID[\"EPSG\",6901]],"
+ " PRIMEM[\"Paris RGS\",2.201395,"
+ " ANGLEUNIT[\"sexagesimal DMS\",1,ID[\"EPSG\",9110]],"
+ " ID[\"EPSG\",8914]],"
+ " CS[ellipsoidal,2,"
+ " ID[\"EPSG\",6403]],"
+ " AXIS[\"Geodetic latitude (Lat)\",north,"
+ " ORDER[1]],"
+ " AXIS[\"Geodetic longitude (Lon)\",east,"
+ " ORDER[2]],"
+ " ANGLEUNIT[\"grad\",0.015707963267949,ID[\"EPSG\",9105]],"
+ " USAGE[SCOPE[\"Geodesy.\"],AREA[\"France - mainland onshore.\"],"
+ " BBOX[42.33,-4.87,51.14,8.23]],"
+ "ID[\"EPSG\",4901]]");
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ auto datum = crs->datum();
+ auto primem = datum->primeMeridian();
+ EXPECT_EQ(primem->longitude().unit(), UnitOfMeasure::DEGREE);
+ EXPECT_NEAR(primem->longitude().value(), 2.33720833333333, 1e-14);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(wkt_parse, wkt1_geographic_old_datum_name_from_EPSG_code) {
auto wkt =
"GEOGCS[\"S-JTSK (Ferro)\",\n"
@@ -619,6 +675,52 @@ TEST(wkt_parse, wkt1_geographic_with_PROJ4_extension) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse, wkt1_geographic_epsg_org_api_4326) {
+ // Output from
+ // https://apps.epsg.org/api/v1/CoordRefSystem/4326/export/?format=wkt&formatVersion=1
+ // using a datum ensemble name
+ auto wkt =
+ "GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System 1984 ensemble\","
+ "SPHEROID[\"WGS 84\",6378137,298.257223563,"
+ "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],"
+ "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+ "UNIT[\"degree (supplier to define representation)\","
+ "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],"
+ "AXIS[\"Lat\",north],AXIS[\"Lon\",east],"
+ "AUTHORITY[\"EPSG\",\"4326\"]]";
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ auto datum = crs->datum();
+ EXPECT_EQ(datum->nameStr(), "World Geodetic System 1984");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(wkt_parse, wkt1_geographic_epsg_org_api_4258) {
+ // Output from
+ // https://apps.epsg.org/api/v1/CoordRefSystem/4258/export/?format=wkt&formatVersion=1
+ // using a datum ensemble name
+ auto wkt = "GEOGCS[\"ETRS89\","
+ "DATUM[\"European Terrestrial Reference System 1989 ensemble\","
+ "SPHEROID[\"GRS 1980\",6378137,298.257222101,"
+ "AUTHORITY[\"EPSG\",\"7019\"]],AUTHORITY[\"EPSG\",\"6258\"]],"
+ "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+ "UNIT[\"degree (supplier to define representation)\","
+ "0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],"
+ "AXIS[\"Lat\",north],AXIS[\"Lon\",east],"
+ "AUTHORITY[\"EPSG\",\"4258\"]]";
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<GeographicCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ auto datum = crs->datum();
+ EXPECT_EQ(datum->nameStr(), "European Terrestrial Reference System 1989");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(wkt_parse, wkt1_geocentric_with_PROJ4_extension) {
auto wkt = "GEOCCS[\"WGS 84\",\n"
" DATUM[\"unknown\",\n"
@@ -1658,16 +1760,21 @@ TEST(wkt_parse, wkt2_projected) {
" ID[\"EPSG\",9122]],\n"
" ID[\"EPSG\",8801]],\n"
" PARAMETER[\"Longitude of natural origin\",3,\n"
- " ANGLEUNIT[\"degree\",0.0174532925199433,\n"
- " ID[\"EPSG\",9122]],\n"
+ // Volontary omit LENGTHUNIT to check the WKT grammar accepts
+ // Check that we default to degree
+ //" ANGLEUNIT[\"degree\",0.0174532925199433,\n"
+ //" ID[\"EPSG\",9122]],\n"
" ID[\"EPSG\",8802]],\n"
" PARAMETER[\"Scale factor at natural origin\",0.9996,\n"
- " SCALEUNIT[\"unity\",1,\n"
- " ID[\"EPSG\",9201]],\n"
+ // Check that we default to unity
+ //" SCALEUNIT[\"unity\",1,\n"
+ //" ID[\"EPSG\",9201]],\n"
" ID[\"EPSG\",8805]],\n"
" PARAMETER[\"False easting\",500000,\n"
- " LENGTHUNIT[\"metre\",1,\n"
- " ID[\"EPSG\",9001]],\n"
+ // Volontary omit LENGTHUNIT to check the WKT grammar accepts
+ // Check that we default to metre
+ //" LENGTHUNIT[\"metre\",1,\n"
+ //" ID[\"EPSG\",9001]],\n"
" ID[\"EPSG\",8806]],\n"
" PARAMETER[\"False northing\",0,\n"
" LENGTHUNIT[\"metre\",1,\n"
@@ -1879,6 +1986,60 @@ TEST(wkt_parse, wkt2_2019_projected_utm_3D) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse, wkt2_2019_projected_with_base_geocentric) {
+ auto wkt =
+ "PROJCRS[\"EPSG topocentric example B\",\n"
+ " BASEGEODCRS[\"WGS 84\",\n"
+ " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n"
+ " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G730)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G873)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n"
+ " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " ENSEMBLEACCURACY[2.0]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " ID[\"EPSG\",4978]],\n"
+ " CONVERSION[\"EPSG topocentric example B\",\n"
+ " METHOD[\"Geocentric/topocentric conversions\",\n"
+ " ID[\"EPSG\",9836]],\n"
+ " PARAMETER[\"Geocentric X of topocentric origin\",3771793.97,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8837]],\n"
+ " PARAMETER[\"Geocentric Y of topocentric origin\",140253.34,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8838]],\n"
+ " PARAMETER[\"Geocentric Z of topocentric origin\",5124304.35,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8839]]],\n"
+ " CS[Cartesian,3],\n"
+ " AXIS[\"topocentric East (U)\",east,\n"
+ " ORDER[1],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric North (V)\",north,\n"
+ " ORDER[2],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric height (W)\",up,\n"
+ " ORDER[3],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " USAGE[\n"
+ " SCOPE[\"Example only (fictitious).\"],\n"
+ " AREA[\"Description of the extent of the CRS.\"],\n"
+ " BBOX[-90,-180,90,180]],\n"
+ " ID[\"EPSG\",5820]]";
+ auto dbContext = DatabaseContext::create();
+ // Need a database so that EPSG:4978 is resolved
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ EXPECT_TRUE(crs->baseCRS()->isGeocentric());
+}
+
+// ---------------------------------------------------------------------------
+
TEST(crs, projected_angular_unit_from_primem) {
auto obj = WKTParser().createFromWKT(
"PROJCRS[\"NTF (Paris) / Lambert Nord France\",\n"
@@ -10444,6 +10605,14 @@ TEST(io, createFromUserInput) {
ParsingException);
EXPECT_THROW(createFromUserInput("foobar + EGM96 height", dbContext),
ParsingException);
+
+ {
+ auto obj = createFromUserInput("World Geodetic System 1984 ensemble",
+ dbContext);
+ auto ensemble = nn_dynamic_pointer_cast<DatumEnsemble>(obj);
+ ASSERT_TRUE(ensemble != nullptr);
+ EXPECT_EQ(ensemble->identifiers().size(), 1U);
+ }
}
// ---------------------------------------------------------------------------
@@ -11139,6 +11308,155 @@ TEST(json_import, projected_crs) {
// ---------------------------------------------------------------------------
+TEST(json_import, projected_crs_with_geocentric_base) {
+ auto json = "{\n"
+ " \"$schema\": \"foo\",\n"
+ " \"type\": \"ProjectedCRS\",\n"
+ " \"name\": \"EPSG topocentric example B\",\n"
+ " \"base_crs\": {\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"datum_ensemble\": {\n"
+ " \"name\": \"World Geodetic System 1984 ensemble\",\n"
+ " \"members\": [\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (Transit)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G730)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G873)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1150)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1674)\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"World Geodetic System 1984 (G1762)\"\n"
+ " }\n"
+ " ],\n"
+ " \"ellipsoid\": {\n"
+ " \"name\": \"WGS 84\",\n"
+ " \"semi_major_axis\": 6378137,\n"
+ " \"inverse_flattening\": 298.257223563\n"
+ " },\n"
+ " \"accuracy\": \"2.0\"\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"Cartesian\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Geocentric X\",\n"
+ " \"abbreviation\": \"X\",\n"
+ " \"direction\": \"geocentricX\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Y\",\n"
+ " \"abbreviation\": \"Y\",\n"
+ " \"direction\": \"geocentricY\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Z\",\n"
+ " \"abbreviation\": \"Z\",\n"
+ " \"direction\": \"geocentricZ\",\n"
+ " \"unit\": \"metre\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 4978\n"
+ " }\n"
+ " },\n"
+ " \"conversion\": {\n"
+ " \"name\": \"EPSG topocentric example B\",\n"
+ " \"method\": {\n"
+ " \"name\": \"Geocentric/topocentric conversions\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 9836\n"
+ " }\n"
+ " },\n"
+ " \"parameters\": [\n"
+ " {\n"
+ " \"name\": \"Geocentric X of topocentric origin\",\n"
+ " \"value\": 3771793.97,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8837\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Y of topocentric origin\",\n"
+ " \"value\": 140253.34,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8838\n"
+ " }\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Geocentric Z of topocentric origin\",\n"
+ " \"value\": 5124304.35,\n"
+ " \"unit\": \"metre\",\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 8839\n"
+ " }\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"coordinate_system\": {\n"
+ " \"subtype\": \"Cartesian\",\n"
+ " \"axis\": [\n"
+ " {\n"
+ " \"name\": \"Topocentric East\",\n"
+ " \"abbreviation\": \"U\",\n"
+ " \"direction\": \"east\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Topocentric North\",\n"
+ " \"abbreviation\": \"V\",\n"
+ " \"direction\": \"north\",\n"
+ " \"unit\": \"metre\"\n"
+ " },\n"
+ " {\n"
+ " \"name\": \"Topocentric height\",\n"
+ " \"abbreviation\": \"W\",\n"
+ " \"direction\": \"up\",\n"
+ " \"unit\": \"metre\"\n"
+ " }\n"
+ " ]\n"
+ " },\n"
+ " \"scope\": \"Example only (fictitious).\",\n"
+ " \"area\": \"Description of the extent of the CRS.\",\n"
+ " \"bbox\": {\n"
+ " \"south_latitude\": -90,\n"
+ " \"west_longitude\": -180,\n"
+ " \"north_latitude\": 90,\n"
+ " \"east_longitude\": 180\n"
+ " },\n"
+ " \"id\": {\n"
+ " \"authority\": \"EPSG\",\n"
+ " \"code\": 5820\n"
+ " }\n"
+ "}";
+ auto obj = createFromUserInput(json, nullptr);
+ auto pcrs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(pcrs != nullptr);
+ EXPECT_TRUE(pcrs->baseCRS()->isGeocentric());
+ EXPECT_EQ(pcrs->exportToJSON(&(JSONFormatter::create()->setSchema("foo"))),
+ json);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(json_import, compound_crs) {
auto json = "{\n"
" \"$schema\": \"foo\",\n"
diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp
index ce4b866b..d0085004 100644
--- a/test/unit/test_operation.cpp
+++ b/test/unit/test_operation.cpp
@@ -4867,7 +4867,7 @@ TEST(operation, vertCRS_to_geogCRS_context) {
"3855"), // EGM2008 height
authFactory->createCoordinateReferenceSystem("4979"), // WGS 84
ctxt);
- ASSERT_EQ(list.size(), 2U);
+ ASSERT_EQ(list.size(), 3U);
EXPECT_EQ(
list[1]->exportToPROJString(
PROJStringFormatter::create(
@@ -4889,7 +4889,7 @@ TEST(operation, vertCRS_to_geogCRS_context) {
"3855"), // EGM2008 height
authFactory->createCoordinateReferenceSystem("4979"), // WGS 84
ctxt);
- ASSERT_EQ(list.size(), 2U);
+ ASSERT_EQ(list.size(), 3U);
EXPECT_EQ(
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=pipeline "
@@ -4938,7 +4938,7 @@ TEST(operation, vertCRS_to_geogCRS_context) {
authFactory->createCoordinateReferenceSystem("7839"),
// NZGD2000
authFactory->createCoordinateReferenceSystem("4959"), ctxt);
- ASSERT_EQ(list.size(), 1U);
+ ASSERT_EQ(list.size(), 2U);
EXPECT_EQ(
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=pipeline "
@@ -4964,7 +4964,7 @@ TEST(operation, vertCRS_to_geogCRS_context) {
authFactory->createCoordinateReferenceSystem("8357"),
// ETRS89
authFactory->createCoordinateReferenceSystem("4937"), ctxt);
- ASSERT_EQ(list.size(), 1U);
+ ASSERT_EQ(list.size(), 2U);
EXPECT_EQ(
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
"+proj=pipeline "
@@ -8734,6 +8734,14 @@ TEST(operation, compoundCRS_to_geogCRS_3D_context) {
"+multiplier=1 "
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
"+step +proj=axisswap +order=2,1");
+ EXPECT_EQ(list[0]->remarks(),
+ "For NAD83(NSRS2007) to NAVD88 height (1) (EPSG:9173): Uses "
+ "Geoid09 hybrid model. Replaced by 2012 model (CT code 6326)."
+ "\n"
+ "For NAD83(NSRS2007) to WGS 84 (1) (EPSG:15931): "
+ "Approximation at the +/- 1m level assuming that "
+ "NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy "
+ "of the transformation.");
}
// NAD83 + NAVD88 height --> WGS 84
@@ -8904,7 +8912,7 @@ TEST(operation, compoundCRS_to_geogCRS_2D_promote_to_3D_context) {
ctxt);
// The checked value is not that important, but in case this changes,
// likely due to a EPSG upgrade, worth checking
- EXPECT_EQ(listCompoundToGeog2D.size(), 141U);
+ EXPECT_EQ(listCompoundToGeog2D.size(), 142U);
auto listGeog2DToCompound =
CoordinateOperationFactory::create()->createOperations(dst, nnSrc,
@@ -10025,6 +10033,192 @@ TEST(operation, createOperation_ossfuzz_18587) {
// ---------------------------------------------------------------------------
+TEST(operation, derivedGeographicCRS_with_to_wgs84_to_geographicCRS) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 +o_lat_p=18.0 "
+ "+o_lon_p=-200.0 +ellps=WGS84 +towgs84=1,2,3 +type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=longlat +datum=WGS84 +type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+
+ {
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ std::string pipeline(
+ "+proj=pipeline "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +inv +proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 "
+ "+o_lat_p=18 +o_lon_p=-200 +ellps=WGS84 "
+ "+step +proj=push +v_3 "
+ "+step +proj=cart +ellps=WGS84 "
+ "+step +proj=helmert +x=1 +y=2 +z=3 "
+ "+step +inv +proj=cart +ellps=WGS84 "
+ "+step +proj=pop +v_3 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ pipeline);
+
+ auto op2 = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src),
+ nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326));
+ ASSERT_TRUE(op2 != nullptr);
+ EXPECT_EQ(op2->exportToPROJString(PROJStringFormatter::create().get()),
+ pipeline + " +step +proj=axisswap +order=2,1");
+ }
+
+ {
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(dst), NN_CHECK_ASSERT(src));
+ ASSERT_TRUE(op != nullptr);
+ std::string pipeline(
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=push +v_3 "
+ "+step +proj=cart +ellps=WGS84 "
+ "+step +proj=helmert +x=-1 +y=-2 +z=-3 "
+ "+step +inv +proj=cart +ellps=WGS84 "
+ "+step +proj=pop +v_3 "
+ "+step +proj=ob_tran +o_proj=latlon +lat_0=0 +lon_0=180 "
+ "+o_lat_p=18 +o_lon_p=-200 +ellps=WGS84 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline " + pipeline);
+
+ auto op2 = CoordinateOperationFactory::create()->createOperation(
+ nn_static_pointer_cast<CRS>(GeographicCRS::EPSG_4326),
+ NN_CHECK_ASSERT(src));
+ ASSERT_TRUE(op2 != nullptr);
+ EXPECT_EQ(op2->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline +step +proj=axisswap +order=2,1 " + pipeline);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(operation, geographic_topocentric) {
+ auto wkt =
+ "PROJCRS[\"EPSG topocentric example A\",\n"
+ " BASEGEOGCRS[\"WGS 84\",\n"
+ " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n"
+ " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G730)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G873)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n"
+ " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " ENSEMBLEACCURACY[2.0]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " ID[\"EPSG\",4979]],\n"
+ " CONVERSION[\"EPSG topocentric example A\",\n"
+ " METHOD[\"Geographic/topocentric conversions\",\n"
+ " ID[\"EPSG\",9837]],\n"
+ " PARAMETER[\"Latitude of topocentric origin\",55,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
+ " ID[\"EPSG\",8834]],\n"
+ " PARAMETER[\"Longitude of topocentric origin\",5,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433],\n"
+ " ID[\"EPSG\",8835]],\n"
+ " PARAMETER[\"Ellipsoidal height of topocentric origin\",0,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8836]]],\n"
+ " CS[Cartesian,3],\n"
+ " AXIS[\"topocentric East (U)\",east,\n"
+ " ORDER[1],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric North (V)\",north,\n"
+ " ORDER[2],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric height (W)\",up,\n"
+ " ORDER[3],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " USAGE[\n"
+ " SCOPE[\"Example only (fictitious).\"],\n"
+ " AREA[\"Description of the extent of the CRS.\"],\n"
+ " BBOX[-90,-180,90,180]],\n"
+ " ID[\"EPSG\",5819]]";
+ auto obj = WKTParser().createFromWKT(wkt);
+ auto dst = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(dst != nullptr);
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ GeographicCRS::EPSG_4979, NN_CHECK_ASSERT(dst));
+ 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 +z_in=m +xy_out=rad +z_out=m "
+ "+step +proj=cart +ellps=WGS84 "
+ "+step +proj=topocentric +lat_0=55 +lon_0=5 +h_0=0 +ellps=WGS84");
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(operation, geocentric_topocentric) {
+ auto wkt =
+ "PROJCRS[\"EPSG topocentric example B\",\n"
+ " BASEGEODCRS[\"WGS 84\",\n"
+ " ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n"
+ " MEMBER[\"World Geodetic System 1984 (Transit)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G730)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G873)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1150)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1674)\"],\n"
+ " MEMBER[\"World Geodetic System 1984 (G1762)\"],\n"
+ " ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " ENSEMBLEACCURACY[2.0]],\n"
+ " PRIMEM[\"Greenwich\",0,\n"
+ " ANGLEUNIT[\"degree\",0.0174532925199433]],\n"
+ " ID[\"EPSG\",4978]],\n"
+ " CONVERSION[\"EPSG topocentric example B\",\n"
+ " METHOD[\"Geocentric/topocentric conversions\",\n"
+ " ID[\"EPSG\",9836]],\n"
+ " PARAMETER[\"Geocentric X of topocentric origin\",3771793.97,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8837]],\n"
+ " PARAMETER[\"Geocentric Y of topocentric origin\",140253.34,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8838]],\n"
+ " PARAMETER[\"Geocentric Z of topocentric origin\",5124304.35,\n"
+ " LENGTHUNIT[\"metre\",1],\n"
+ " ID[\"EPSG\",8839]]],\n"
+ " CS[Cartesian,3],\n"
+ " AXIS[\"topocentric East (U)\",east,\n"
+ " ORDER[1],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric North (V)\",north,\n"
+ " ORDER[2],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " AXIS[\"topocentric height (W)\",up,\n"
+ " ORDER[3],\n"
+ " LENGTHUNIT[\"metre\",1]],\n"
+ " USAGE[\n"
+ " SCOPE[\"Example only (fictitious).\"],\n"
+ " AREA[\"Description of the extent of the CRS.\"],\n"
+ " BBOX[-90,-180,90,180]],\n"
+ " ID[\"EPSG\",5820]]";
+ auto dbContext = DatabaseContext::create();
+ // Need a database so that EPSG:4978 is resolved
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto dst = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(dst != nullptr);
+ auto f(NS_PROJ::io::WKTFormatter::create(
+ NS_PROJ::io::WKTFormatter::Convention::WKT2_2019));
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ GeodeticCRS::EPSG_4978, NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=topocentric +X_0=3771793.97 +Y_0=140253.34 "
+ "+Z_0=5124304.35 +ellps=WGS84");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, mercator_variant_A_to_variant_B) {
auto projCRS = ProjectedCRS::create(
PropertyMap(), GeographicCRS::EPSG_4326,
@@ -11096,7 +11290,7 @@ TEST(operation, normalizeForVisualization) {
src,
authFactory->createCoordinateReferenceSystem("4979"), // WGS 84 3D
ctxt);
- ASSERT_EQ(list.size(), 2U);
+ ASSERT_EQ(list.size(), 3U);
auto op = list[1];
auto opNormalized = op->normalizeForVisualization();
EXPECT_FALSE(opNormalized->_isEquivalentTo(op.get()));
diff --git a/travis/after_success.sh b/travis/after_success.sh
index 095bafbd..abe11d91 100755
--- a/travis/after_success.sh
+++ b/travis/after_success.sh
@@ -2,13 +2,6 @@
set -e
-if [ "$BUILD_NAME" != "linux_clang" ]; then
- # coveralls falsely reports .c-files in the build directories as having 100% coverage so we exclude them
- coveralls --build-root src --extension .c --extension .cpp \
- --exclude build_autoconf --exclude build_cmake --exclude test --exclude examples \
- --exclude include/proj/internal/nlohmann
-fi
-
echo "$TRAVIS_SECURE_ENV_VARS"
./travis/build_docs.sh
# Only build and publish docs when changes are made on most recent maintenance branch
diff --git a/travis/csa/before_install.sh b/travis/csa/before_install.sh
deleted file mode 100755
index 0ebc94fb..00000000
--- a/travis/csa/before_install.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-set -e
-
-./travis/before_install_apt.sh
-./travis/before_install_pip.sh
-
-sudo apt-get install -qq sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev
-
-CLANG_LLVM=clang+llvm-9.0.0-x86_64-linux-gnu-ubuntu-16.04
-wget http://releases.llvm.org/9.0.0/$CLANG_LLVM.tar.xz
-tar xJf $CLANG_LLVM.tar.xz
-mv $CLANG_LLVM clang+llvm-9
diff --git a/travis/install.sh b/travis/install.sh
index 8897f823..6426e1b3 100755
--- a/travis/install.sh
+++ b/travis/install.sh
@@ -41,8 +41,9 @@ make >/dev/null
if [ "$(uname)" == "Linux" -a -f src/.libs/libproj.so ]; then
if objdump -TC "src/.libs/libproj.so" | grep "elf64-x86-64">/dev/null; then
echo "Checking exported symbols..."
- $TRAVIS_BUILD_DIR/scripts/dump_exported_symbols.sh src/.libs/libproj.so > /tmp/got_symbols.txt
- diff -u $TRAVIS_BUILD_DIR/scripts/reference_exported_symbols.txt /tmp/got_symbols.txt || (echo "Difference(s) found in exported symbols. If intended, refresh scripts/reference_exported_symbols.txt with 'scripts/dump_exported_symbols.sh src/.libs/libproj.so > scripts/reference_exported_symbols.txt'"; exit 1)
+ cat $TRAVIS_BUILD_DIR/scripts/reference_exported_symbols.txt | sort > /tmp/reference_exported_symbols.txt
+ $TRAVIS_BUILD_DIR/scripts/dump_exported_symbols.sh src/.libs/libproj.so | sort > /tmp/got_symbols.txt
+ diff -u /tmp/reference_exported_symbols.txt /tmp/got_symbols.txt || (echo "Difference(s) found in exported symbols. If intended, refresh scripts/reference_exported_symbols.txt with 'scripts/dump_exported_symbols.sh src/.libs/libproj.so > scripts/reference_exported_symbols.txt'"; exit 1)
fi
fi
@@ -98,7 +99,7 @@ if [ $TRAVIS_OS_NAME != "osx" ]; then
fi
fi
-if [ "$BUILD_NAME" != "linux_gcc8" ]; then
+if [ "$BUILD_NAME" != "linux_gcc8" -a "$BUILD_NAME" != "linux_gcc_32bit" ]; then
# cmake build from generated tarball
mkdir build_cmake
@@ -140,12 +141,4 @@ if [ "$BUILD_NAME" != "linux_gcc8" ]; then
fi
make >/dev/null
make check
-
- if [ "$BUILD_NAME" != "linux_clang" ]; then
- mv src/.libs/*.gc* src
- mv src/conversions/.libs/*.gc* src/conversions
- mv src/iso19111/.libs/*.gc* src/iso19111
- mv src/projections/.libs/*.gc* src/projections
- mv src/transformations/.libs/*.gc* src/transformations
- fi
fi
diff --git a/travis/linux_clang/after_success.sh b/travis/linux_clang/after_success.sh
deleted file mode 100755
index 9618f673..00000000
--- a/travis/linux_clang/after_success.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# nothing
diff --git a/travis/linux_clang/install.sh b/travis/linux_clang/install.sh
deleted file mode 100755
index 50c02882..00000000
--- a/travis/linux_clang/install.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export CCACHE_CPP2=yes
-export PROJ_DB_CACHE_DIR="$HOME/.ccache"
-
-# -fno-use-cxa-atexit is needed to build with -coverage
-CC="ccache clang" CXX="ccache clang++" CFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" CXXFLAGS="-Werror -fsanitize=address -fno-use-cxa-atexit" LDFLAGS="-fsanitize=address" ./travis/install.sh
diff --git a/travis/linux_gcc/before_install.sh b/travis/linux_gcc/before_install.sh
deleted file mode 100755
index 3068794d..00000000
--- a/travis/linux_gcc/before_install.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-set -e
-
-./travis/before_install_apt.sh
-./travis/before_install_pip.sh
-
-sudo apt-get install -qq \
- lcov \
- doxygen graphviz \
- sqlite3 libsqlite3-dev \
- libtiff-dev libcurl4-openssl-dev \
- cppcheck
-
-scripts/cppcheck.sh
-scripts/doxygen.sh
-
-pip3 install --user sphinxcontrib-bibtex
-pip3 install --user cpp-coveralls
-pip3 install --user cmake==3.9.6
-
-./travis/docker.sh
diff --git a/travis/linux_gcc/install.sh b/travis/linux_gcc/install.sh
deleted file mode 100755
index 5dd97f07..00000000
--- a/travis/linux_gcc/install.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export CCACHE_CPP2=yes
-export PROJ_DB_CACHE_DIR="$HOME/.ccache"
-
-CC="ccache $CC" CXX="ccache $CXX" CFLAGS="-std=c99 -Werror" CXXFLAGS="-Werror" ./travis/install.sh
diff --git a/travis/linux_gcc8/after_success.sh b/travis/linux_gcc8/after_success.sh
deleted file mode 100755
index 70c6f5cb..00000000
--- a/travis/linux_gcc8/after_success.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-set -e
-
-#./travis/after_success.sh
diff --git a/travis/linux_gcc8/before_install.sh b/travis/linux_gcc8/before_install.sh
deleted file mode 100755
index ff6c0927..00000000
--- a/travis/linux_gcc8/before_install.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -e
-
-./travis/before_install_apt.sh
-./travis/before_install_pip.sh
-
-sudo aptitude remove -q -y libtiff-dev libcurl4-gnutls-dev
-sudo aptitude install -q -y \
- lcov \
- doxygen graphviz \
- sqlite3 libsqlite3-dev:$ARCH \
- libtiff-dev:$ARCH libcurl4-openssl-dev:$ARCH
-
-#scripts/cppcheck.sh
-#scripts/doxygen.sh
-
-#pip install --user sphinxcontrib-bibtex
-#pip install --user cpp-coveralls
-
-#./travis/docker.sh
diff --git a/travis/linux_gcc8/install.sh b/travis/linux_gcc8/install.sh
deleted file mode 100755
index 7fa8cfa4..00000000
--- a/travis/linux_gcc8/install.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export CCACHE_CPP2=yes
-export PROJ_DB_CACHE_DIR="$HOME/.ccache"
-
-CC="ccache $CC" CXX="ccache $CXX" CFLAGS="-std=c99 -Werror $CFLAGS" CXXFLAGS="-Werror $CXXFLAGS" ./travis/install.sh
diff --git a/travis/mingw32/after_success.sh b/travis/mingw32/after_success.sh
deleted file mode 100755
index 9618f673..00000000
--- a/travis/mingw32/after_success.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# nothing
diff --git a/travis/mingw32/before_install.sh b/travis/mingw32/before_install.sh
deleted file mode 100755
index f33d18ff..00000000
--- a/travis/mingw32/before_install.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-set -e
-
-./travis/before_install_apt.sh
-./travis/before_install_pip.sh
-
-sudo apt-get install -qq \
- wget \
- binutils-mingw-w64-x86-64 \
- gcc-mingw-w64-x86-64 \
- g++-mingw-w64-x86-64 \
- mingw-w64-tools \
- wine1.4-amd64 \
- sqlite3
diff --git a/travis/mingw32/install.sh b/travis/mingw32/install.sh
deleted file mode 100755
index 67873dd1..00000000
--- a/travis/mingw32/install.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/bash
-
-set -e
-
-unset CC
-unset CXX
-
-export CCACHE_CPP2=yes
-export PROJ_DB_CACHE_DIR="$HOME/.ccache"
-
-MINGW_ARCH=x86_64-w64-mingw32
-MINGW_PREFIX=/usr/lib/gcc/$MINGW_ARCH/5.3-posix
-
-# prepare wine environment
-WINE_SYSDIR=$HOME/.wine/drive_c/windows
-wine64 cmd /c dir
-ln -s $MINGW_PREFIX/libstdc++-6.dll $WINE_SYSDIR
-ln -s $MINGW_PREFIX/libgcc_s_seh-1.dll $WINE_SYSDIR
-ln -s $MINGW_PREFIX/libgcc_s_sjlj-1.dll $WINE_SYSDIR
-ln -s /usr/$MINGW_ARCH/lib/libwinpthread-1.dll $WINE_SYSDIR
-
-# build zlib
-wget https://github.com/madler/zlib/archive/v1.2.11.tar.gz
-tar xzf v1.2.11.tar.gz
-(cd zlib-1.2.11 && sudo make install -fwin32/Makefile.gcc SHARED_MODE=1 PREFIX=x86_64-w64-mingw32- DESTDIR=/usr/$MINGW_ARCH/)
-sudo mkdir -p /usr/$MINGW_ARCH/include
-sudo mkdir -p /usr/$MINGW_ARCH/lib
-sudo cp /usr/$MINGW_ARCH/*.h /usr/$MINGW_ARCH/include
-sudo cp /usr/$MINGW_ARCH/libz.* /usr/$MINGW_ARCH/lib
-ln -s /usr/$MINGW_ARCH/zlib1.dll $WINE_SYSDIR
-
-# build libtiff
-wget https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz
-tar xzf tiff-4.1.0.tar.gz
-(cd tiff-4.1.0 && ./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make -j2 && sudo make install)
-ln -s /usr/$MINGW_ARCH/bin/libtiff-5.dll $WINE_SYSDIR
-
-# build sqlite3
-wget https://sqlite.org/2018/sqlite-autoconf-3250100.tar.gz
-tar xzf sqlite-autoconf-3250100.tar.gz
-(cd sqlite-autoconf-3250100 && CC="ccache $MINGW_ARCH-gcc" CXX="ccache $MINGW_ARCH-g++" LD=$MINGW_ARCH-ld
-./configure --host=$MINGW_ARCH --prefix=/usr/$MINGW_ARCH && make -j2 && sudo make install)
-ln -s /usr/$MINGW_ARCH/bin/libsqlite3-0.dll $WINE_SYSDIR
-
-# prepare build files
-./autogen.sh
-# autoconf build
-mkdir build_autoconf
-cd build_autoconf
-CC="ccache $MINGW_ARCH-gcc" CXX="ccache $MINGW_ARCH-g++" LD=$MINGW_ARCH-ld ../configure --host=$MINGW_ARCH --prefix=/tmp/proj_autoconf_install --without-curl
-make -j2
-make install
-make dist-all
-find /tmp/proj_autoconf_install
-(cd test; make -j2)
-cp -r ../data/tests /tmp/proj_autoconf_install/share/proj
-cp ../data/tests/egm96_15_downsampled.gtx /tmp/proj_autoconf_install/share/proj/egm96_15.gtx
-cp ../data/tests/ntv2_0_downsampled.gsb /tmp/proj_autoconf_install/share/proj/ntv2_0.gsb
-test/unit/test_cpp_api.exe
diff --git a/travis/osx/after_success.sh b/travis/osx/after_success.sh
deleted file mode 100755
index 9618f673..00000000
--- a/travis/osx/after_success.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# nothing
diff --git a/travis/osx/before_install.sh b/travis/osx/before_install.sh
deleted file mode 100755
index 5af2fd7a..00000000
--- a/travis/osx/before_install.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-set -e
-
-export PATH=$HOME/Library/Python/3.7/bin:$PATH
-
-#brew unlink python@2
-#brew update
-brew install ccache
-#brew upgrade sqlite3
-#brew upgrade libtiff
-#brew install doxygen graphviz
-#brew install md5sha1sum
-#brew reinstall python
-#brew reinstall wget
-
-./travis/before_install_pip.sh
-
-# pip3 install --user sphinx sphinx-rtd-theme sphinxcontrib-bibtex breathe
-# which sphinx-build
-
-# (cd docs; make html)
diff --git a/travis/linux_gcc/after_success.sh b/travis/publish_doc/after_success.sh
index 6602f6c3..6602f6c3 100755
--- a/travis/linux_gcc/after_success.sh
+++ b/travis/publish_doc/after_success.sh
diff --git a/travis/linux_clang/before_install.sh b/travis/publish_doc/before_install.sh
index c4b8acad..bbb7b35b 100755
--- a/travis/linux_clang/before_install.sh
+++ b/travis/publish_doc/before_install.sh
@@ -4,5 +4,4 @@ set -e
./travis/before_install_apt.sh
./travis/before_install_pip.sh
-
-sudo apt-get install -qq sqlite3 libsqlite3-dev libtiff-dev libcurl4-openssl-dev
+./travis/docker.sh
diff --git a/travis/csa/after_success.sh b/travis/publish_doc/install.sh
index 9618f673..d9628ae7 100755
--- a/travis/csa/after_success.sh
+++ b/travis/publish_doc/install.sh
@@ -1,5 +1,3 @@
#!/bin/bash
set -e
-
-# nothing