aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2017-10-09 21:55:30 +0200
committerKristian Evers <kristianevers@gmail.com>2017-10-09 21:55:30 +0200
commit0d4ce7814091a716fc835eb3abe3ad41d49f3ee1 (patch)
tree2404ee17446b91fe4c776445ad2b30db866ed8ef
parentf8d26297de7f6092e78bcd33876510c7082c3f35 (diff)
parent8fc250a04edbfe81b9b7409187887066baeba29b (diff)
downloadPROJ-0d4ce7814091a716fc835eb3abe3ad41d49f3ee1.tar.gz
PROJ-0d4ce7814091a716fc835eb3abe3ad41d49f3ee1.zip
Merge remote-tracking branch 'osgeo/master' into docs-release-4.10.0
-rw-r--r--.gitignore4
-rw-r--r--AUTHORS1
-rw-r--r--CMakeLists.txt1
-rw-r--r--cmake/CMakeLists.txt14
-rw-r--r--cmake/Proj4InstallPath.cmake30
-rw-r--r--cmake/Proj4SystemInfo.cmake6
-rw-r--r--cmake/policies.cmake1
-rw-r--r--docs/source/download.rst2
-rw-r--r--man/man3/geodesic.34
-rwxr-xr-xnad/testvarious9
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/Makefile.am15
-rw-r--r--src/PJ_aea.c32
-rw-r--r--src/PJ_aeqd.c22
-rw-r--r--src/PJ_airy.c18
-rw-r--r--src/PJ_aitoff.c27
-rw-r--r--src/PJ_august.c9
-rw-r--r--src/PJ_bacon.c22
-rw-r--r--src/PJ_bipc.c16
-rw-r--r--src/PJ_boggs.c10
-rw-r--r--src/PJ_bonne.c25
-rw-r--r--src/PJ_calcofi.c10
-rw-r--r--src/PJ_cart.c61
-rw-r--r--src/PJ_cass.c24
-rw-r--r--src/PJ_cc.c10
-rw-r--r--src/PJ_cea.c30
-rw-r--r--src/PJ_chamb.c24
-rw-r--r--src/PJ_collg.c10
-rw-r--r--src/PJ_comill.c9
-rw-r--r--src/PJ_crast.c11
-rw-r--r--src/PJ_denoy.c10
-rw-r--r--src/PJ_eck1.c15
-rw-r--r--src/PJ_eck2.c10
-rw-r--r--src/PJ_eck3.c27
-rw-r--r--src/PJ_eck4.c12
-rw-r--r--src/PJ_eck5.c14
-rw-r--r--src/PJ_eqc.c26
-rw-r--r--src/PJ_eqdc.c31
-rw-r--r--src/PJ_fahey.c13
-rw-r--r--src/PJ_fouc_s.c27
-rw-r--r--src/PJ_gall.c14
-rw-r--r--src/PJ_geos.c46
-rw-r--r--src/PJ_gins8.c15
-rw-r--r--src/PJ_gn_sinu.c53
-rw-r--r--src/PJ_gnom.c20
-rw-r--r--src/PJ_goode.c45
-rw-r--r--src/PJ_gstmerc.c22
-rw-r--r--src/PJ_hammer.c33
-rw-r--r--src/PJ_hatano.c37
-rw-r--r--src/PJ_healpix.c36
-rw-r--r--src/PJ_helmert.c32
-rw-r--r--src/PJ_hgridshift.c91
-rw-r--r--src/PJ_horner.c57
-rw-r--r--src/PJ_igh.c24
-rw-r--r--src/PJ_imw_p.c25
-rw-r--r--src/PJ_isea.c25
-rw-r--r--src/PJ_krovak.c21
-rw-r--r--src/PJ_labrd.c22
-rw-r--r--src/PJ_laea.c16
-rw-r--r--src/PJ_lagrng.c31
-rw-r--r--src/PJ_larr.c16
-rw-r--r--src/PJ_lask.c15
-rw-r--r--src/PJ_latlong.c (renamed from src/pj_latlong.c)13
-rw-r--r--src/PJ_lcc.c26
-rw-r--r--src/PJ_lcca.c22
-rw-r--r--src/PJ_loxim.c26
-rw-r--r--src/PJ_lsat.c33
-rw-r--r--src/PJ_mbt_fps.c16
-rw-r--r--src/PJ_mbtfpp.c13
-rw-r--r--src/PJ_mbtfpq.c13
-rw-r--r--src/PJ_merc.c12
-rw-r--r--src/PJ_mill.c15
-rw-r--r--src/PJ_minimal.c204
-rw-r--r--src/PJ_misrsom.c26
-rw-r--r--src/PJ_mod_ster.c28
-rw-r--r--src/PJ_moll.c26
-rw-r--r--src/PJ_molodensky.c35
-rw-r--r--src/PJ_natearth.c16
-rw-r--r--src/PJ_natearth2.c16
-rw-r--r--src/PJ_nell.c16
-rw-r--r--src/PJ_nell_h.c16
-rw-r--r--src/PJ_nocol.c16
-rw-r--r--src/PJ_nsper.c29
-rw-r--r--src/PJ_nzmg.c15
-rw-r--r--src/PJ_ob_tran.c192
-rw-r--r--src/PJ_ocea.c19
-rw-r--r--src/PJ_oea.c20
-rw-r--r--src/PJ_omerc.c25
-rw-r--r--src/PJ_ortho.c18
-rw-r--r--src/PJ_patterson.c13
-rw-r--r--src/PJ_pipeline.c58
-rw-r--r--src/PJ_poly.c22
-rw-r--r--src/PJ_putp2.c13
-rw-r--r--src/PJ_putp3.c22
-rw-r--r--src/PJ_putp4p.c22
-rw-r--r--src/PJ_putp5.c23
-rw-r--r--src/PJ_putp6.c22
-rw-r--r--src/PJ_qsc.c22
-rw-r--r--src/PJ_robin.c14
-rw-r--r--src/PJ_rpoly.c19
-rw-r--r--src/PJ_sch.c69
-rw-r--r--src/PJ_sconics.c36
-rw-r--r--src/PJ_somerc.c23
-rw-r--r--src/PJ_stere.c20
-rw-r--r--src/PJ_sterea.c23
-rw-r--r--src/PJ_sts.c26
-rw-r--r--src/PJ_tcc.c10
-rw-r--r--src/PJ_tcea.c10
-rw-r--r--src/PJ_times.c14
-rw-r--r--src/PJ_tmerc.c22
-rw-r--r--src/PJ_tpeqd.c27
-rw-r--r--src/PJ_unitconvert.c63
-rw-r--r--src/PJ_urm5.c26
-rw-r--r--src/PJ_urmfps.c29
-rw-r--r--src/PJ_vandg.c14
-rw-r--r--src/PJ_vandg2.c24
-rw-r--r--src/PJ_vandg4.c14
-rw-r--r--src/PJ_vgridshift.c61
-rw-r--r--src/PJ_wag2.c10
-rw-r--r--src/PJ_wag3.c21
-rw-r--r--src/PJ_wag7.c11
-rw-r--r--src/PJ_wink1.c20
-rw-r--r--src/PJ_wink2.c18
-rw-r--r--src/bin_cct.cmake9
-rw-r--r--src/cct.c324
-rw-r--r--src/geodesic.c40
-rw-r--r--src/geodesic.h26
-rw-r--r--src/geodtest.c42
-rw-r--r--src/lib_proj.cmake2
-rw-r--r--src/makefile.vc10
-rw-r--r--src/multistresstest.c2
-rw-r--r--src/optargpm.h593
-rw-r--r--src/pj_ctx.c33
-rw-r--r--src/pj_fwd.c4
-rw-r--r--src/pj_fwd3d.c4
-rw-r--r--src/pj_geocent.c13
-rw-r--r--src/pj_gridlist.c8
-rw-r--r--src/pj_init.c241
-rw-r--r--src/pj_inv.c2
-rw-r--r--src/pj_inv3d.c2
-rw-r--r--src/pj_malloc.c140
-rw-r--r--src/pj_mlfn.c26
-rw-r--r--src/pj_obs_api.c154
-rw-r--r--src/pj_run_selftests.c3
-rw-r--r--src/pj_strerrno.c26
-rw-r--r--src/pj_transform.c16
-rw-r--r--src/proj.c519
-rw-r--r--src/proj.def4
-rw-r--r--src/proj.h92
-rw-r--r--src/proj_etmerc.c28
-rw-r--r--src/proj_rouss.c19
-rw-r--r--src/proj_strtod.c251
-rw-r--r--src/projects.h95
-rw-r--r--src/test228.c2
-rwxr-xr-xtravis/before_install.sh18
-rwxr-xr-xtravis/install.sh7
-rwxr-xr-xtravis/linux_clang/before_install.sh1
-rwxr-xr-xtravis/linux_clang/install.sh2
-rwxr-xr-xtravis/linux_gcc/before_install.sh6
-rwxr-xr-xtravis/mingw32/before_install.sh2
-rwxr-xr-xtravis/osx/before_install.sh2
161 files changed, 2855 insertions, 3004 deletions
diff --git a/.gitignore b/.gitignore
index ad74f230..e191b441 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
*~
+build.local.bat
+build.local.sh
Makefile
Makefile.in
CMakeFiles
@@ -8,8 +10,10 @@ cmake_install.cmake
install_manifest.txt
cmake/project-config*.cmake
+/.vs*
/*.manifest
/*.swp
+/*build*
/aclocal.m4
/autom4te.cache
/config.cache
diff --git a/AUTHORS b/AUTHORS
index f114a2ea..534ddd22 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,3 +16,4 @@ Karsten Engsager
Knud Poder
Kristian Evers <kreve@sdfe.dk>
Thomas Knudsen <thokn@sdfe.dk>
+Even Rouault <even.rouault@spatialys.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 702eafaf..d6bbe8ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -128,6 +128,7 @@ set(LIBDIR "${DEFAULT_LIBDIR}" CACHE PATH "The directory to install libraries in
set(DATADIR "${DEFAULT_DATADIR}" CACHE PATH "The directory to install data files into.")
set(DOCDIR "${DEFAULT_DOCDIR}" CACHE PATH "The directory to install doc files into.")
set(INCLUDEDIR "${DEFAULT_INCLUDEDIR}" CACHE PATH "The directory to install includes into.")
+set(CMAKECONFIGDIR "${DEFAULT_CMAKEDIR}" CACHE PATH "The directory to install cmake config files into.")
#################################################################################
# Build configured components
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 742da0e9..0fcde0ca 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -2,13 +2,7 @@
# ${INSTALL_CMAKE_DIR} and @PROJECT_ROOT_DIR@ is the relative
# path to the root from there. (Note that the whole install tree can
# be relocated.)
-if (NOT WIN32)
- set (INSTALL_CMAKE_DIR "share/cmake/${PROJECT_NAME}")
- set (PROJECT_ROOT_DIR "../../..")
-else ()
- set (INSTALL_CMAKE_DIR "cmake")
- set (PROJECT_ROOT_DIR "..")
-endif ()
+file(RELATIVE_PATH PROJECT_ROOT_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKECONFIGDIR} ${CMAKE_INSTALL_PREFIX})
string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_LOWER)
configure_file (project-config.cmake.in project-config.cmake @ONLY)
@@ -16,14 +10,14 @@ configure_file (project-config-version.cmake.in
project-config-version.cmake @ONLY)
install (FILES
"${CMAKE_CURRENT_BINARY_DIR}/project-config.cmake"
- DESTINATION "${INSTALL_CMAKE_DIR}"
+ DESTINATION "${CMAKECONFIGDIR}"
RENAME "${PROJECT_NAME_LOWER}-config.cmake")
install (FILES
"${CMAKE_CURRENT_BINARY_DIR}/project-config-version.cmake"
- DESTINATION "${INSTALL_CMAKE_DIR}"
+ DESTINATION "${CMAKECONFIGDIR}"
RENAME "${PROJECT_NAME_LOWER}-config-version.cmake")
# Make information about the cmake targets (the library and the tools)
# available.
install (EXPORT targets
FILE ${PROJECT_NAME_LOWER}-targets.cmake
- DESTINATION "${INSTALL_CMAKE_DIR}")
+ DESTINATION "${CMAKECONFIGDIR}")
diff --git a/cmake/Proj4InstallPath.cmake b/cmake/Proj4InstallPath.cmake
index da1491c0..b06777f4 100644
--- a/cmake/Proj4InstallPath.cmake
+++ b/cmake/Proj4InstallPath.cmake
@@ -15,19 +15,29 @@ endif(UNIX)
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
- SET(CMAKE_INSTALL_PREFIX ${DEFAULT_PROJ_ROOT_DIR} CACHE PATH "Foo install
+ SET(CMAKE_INSTALL_PREFIX ${DEFAULT_PROJ_ROOT_DIR} CACHE PATH "Proj.4 install
prefix" FORCE)
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
-#TODO
+#TODO
# for data install testing the PROJ_LIB envVar
+string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_LOWER)
if(WIN32)
set(DEFAULT_BIN_SUBDIR bin)
set(DEFAULT_LIB_SUBDIR local/lib)
set(DEFAULT_DATA_SUBDIR share)
set(DEFAULT_INCLUDE_SUBDIR local/include)
set(DEFAULT_DOC_SUBDIR share/doc/proj)
+ set(DEFAULT_CMAKE_SUBDIR local/lib/cmake/${PROJECT_NAME_LOWER})
+elseif(UNIX)
+ include(GNUInstallDirs)
+ set(DEFAULT_BIN_SUBDIR ${CMAKE_INSTALL_BINDIR})
+ 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_CMAKE_SUBDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER})
else()
# Common locatoins for Unix and Mac OS X
set(DEFAULT_BIN_SUBDIR bin)
@@ -35,9 +45,11 @@ else()
set(DEFAULT_DATA_SUBDIR share/proj)
set(DEFAULT_DOC_SUBDIR doc/proj)
set(DEFAULT_INCLUDE_SUBDIR include)
+ set(DEFAULT_DOC_SUBDIR share/doc/proj)
+ set(DEFAULT_CMAKE_SUBDIR lib/cmake/${PROJECT_NAME_LOWER})
endif()
-# Locations are changeable by user to customize layout of PDAL installation
+# Locations are changeable by user to customize layout of Proj.4 installation
# (default values are platform-specific)
set(PROJ_BIN_SUBDIR ${DEFAULT_BIN_SUBDIR} CACHE STRING
"Subdirectory where executables will be installed")
@@ -48,20 +60,24 @@ set(PROJ_INCLUDE_SUBDIR ${DEFAULT_INCLUDE_SUBDIR} CACHE STRING
set(PROJ_DATA_SUBDIR ${DEFAULT_DATA_SUBDIR} CACHE STRING
"Subdirectory where data will be installed")
set(PROJ_DOC_SUBDIR ${DEFAULT_DOC_SUBDIR} CACHE STRING
- "Subdirectory where data will be installed")
+ "Subdirectory where doc will be installed")
+set(PROJ_CMAKE_SUBDIR ${DEFAULT_CMAKE_SUBDIR} CACHE STRING
+ "Subdirectory where cmake proj4-config file will be installed")
# Mark *DIR variables as advanced and dedicated to use by power-users only.
mark_as_advanced(PROJ_ROOT_DIR
PROJ_BIN_SUBDIR
- PROJ_LIB_SUBDIR
- PROJ_INCLUDE_SUBDIR
+ PROJ_LIB_SUBDIR
+ PROJ_INCLUDE_SUBDIR
PROJ_DATA_SUBDIR
- PROJ_DOC_SUBDIR )
+ PROJ_DOC_SUBDIR
+ PROJ_CMAKE_SUBDIR )
set(DEFAULT_BINDIR "${PROJ_BIN_SUBDIR}")
set(DEFAULT_LIBDIR "${PROJ_LIB_SUBDIR}")
set(DEFAULT_DATADIR "${PROJ_DATA_SUBDIR}")
set(DEFAULT_DOCDIR "${PROJ_DOC_SUBDIR}")
set(DEFAULT_INCLUDEDIR "${PROJ_INCLUDE_SUBDIR}")
+set(DEFAULT_CMAKEDIR "${PROJ_CMAKE_SUBDIR}")
diff --git a/cmake/Proj4SystemInfo.cmake b/cmake/Proj4SystemInfo.cmake
index 294a50b2..fda57edb 100644
--- a/cmake/Proj4SystemInfo.cmake
+++ b/cmake/Proj4SystemInfo.cmake
@@ -50,6 +50,12 @@ if(WIN32)
if(MSVC_VERSION EQUAL 1800)
set(PROJ_COMPILER_NAME "msvc-12.0") #Visual Studio 2013
endif()
+ if(MSVC_VERSION EQUAL 1900) # CMake 3.1+
+ set(PROJ_COMPILER_NAME "msvc-14.0") #Visual Studio 2015
+ endif()
+ if(MSVC_VERSION GREATER 1900 AND MSVC_VERSION LESS 1920) # CMake 3.8+
+ set(PROJ_COMPILER_NAME "msvc-14.1") #Visual Studio 2017
+ endif()
endif(MSVC)
if(MINGW)
diff --git a/cmake/policies.cmake b/cmake/policies.cmake
index c16fbc12..e1bfd53b 100644
--- a/cmake/policies.cmake
+++ b/cmake/policies.cmake
@@ -1,5 +1,4 @@
if (CMAKE_MAJOR_VERSION GREATER 2)
- cmake_policy(SET CMP0022 OLD) # interface link libraries
cmake_policy(SET CMP0042 NEW) # osx rpath
cmake_policy(SET CMP0011 NEW) # policy setting
endif()
diff --git a/docs/source/download.rst b/docs/source/download.rst
index 7db468c6..4b9cbb92 100644
--- a/docs/source/download.rst
+++ b/docs/source/download.rst
@@ -46,7 +46,7 @@ Docker
................................................................................
A `Docker`_ image with just PROJ.4 binaries and a full compliment of grid shift
-files is available on `DockerHub`:
+files is available on `DockerHub`_:
.. _`Docker`: https://docker.org
.. _`DockerHub`: https://hub.docker.com/r/osgeo/proj.4/
diff --git a/man/man3/geodesic.3 b/man/man3/geodesic.3
index 310fc3d5..938eed68 100644
--- a/man/man3/geodesic.3
+++ b/man/man3/geodesic.3
@@ -53,7 +53,7 @@ measure angles (latitudes, longitudes, and azimuths) in degrees, unlike
the rest of the \fBproj\fR library, which uses radians. The
documentation for this library is included in geodesic.h. A formatted
version of the documentation is available at
-https://geographiclib.sourceforge.io/1.48/C
+https://geographiclib.sourceforge.io/1.49/C
.SH EXAMPLE
The following program reads in lines with the coordinates for two points
in decimal degrees (\fIlat1\fR, \fIlon1\fR, \fIlat2\fR, \fIlon2\fR) and
@@ -87,7 +87,7 @@ libproj.a \- library of projections and support procedures
.SH SEE ALSO
Full online documentation for \fBgeodesic(3)\fR,
.br
-https://geographiclib.sourceforge.io/1.48/C
+https://geographiclib.sourceforge.io/1.49/C
.PP
.B geod(1)
.PP
diff --git a/nad/testvarious b/nad/testvarious
index f11bc806..4ca20a63 100755
--- a/nad/testvarious
+++ b/nad/testvarious
@@ -642,14 +642,14 @@ EOF
echo "##############################################################" >> ${OUT}
echo "Check inverse error handling with ob_tran (#225)" >> ${OUT}
$EXE +proj=ob_tran \
- +o_proj=moll +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 +ellps=WGS84 \
+ +o_proj=moll +a=6378137 +es=0 +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 \
-E >>${OUT} <<EOF
300000 400000
20000000 30000000
EOF
echo "Test inverse handling" >> ${OUT}
$EXE -I +proj=ob_tran \
- +o_proj=moll +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 +ellps=WGS84 \
+ +o_proj=moll +a=6378137 +es=0 +o_lon_p=LON_POLE +o_lat_p=LAT_POLE +lon_0=180 \
-E >>${OUT} <<EOF
10 20
EOF
@@ -894,6 +894,11 @@ if [ $? -ne 0 ] ; then
echo "PROBLEMS HAVE OCCURRED"
echo "test file ${OUT} saved"
echo
+ echo "----------------------------------------------------------"
+ echo "${OUT}"
+ echo "----------------------------------------------------------"
+ cat ${OUT}
+ echo "----------------------------------------------------------"
exit 100
else
echo "TEST OK"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index eec7ddec..788273a9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,6 +3,7 @@
include(lib_proj.cmake)
# configure executable build
+option(BUILD_CCT "Build cct (coordinate conversion and transformation tool)" ON)
option(BUILD_CS2CS "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON)
option(BUILD_PROJ "Build proj (cartographic projection tool : latlong <-> projected coordinates" ON)
option(BUILD_GEOD "Build geod (computation of geodesic lines)" ON)
@@ -22,6 +23,11 @@ if(NOT MSVC)
endif ()
endif ()
+if(BUILD_CCT)
+ include(bin_cct.cmake)
+ set(BIN_TARGETS ${BIN_TARGETS} cct)
+endif(BUILD_CCT)
+
if(BUILD_CS2CS)
include(bin_cs2cs.cmake)
set(BIN_TARGETS ${BIN_TARGETS} cs2cs)
diff --git a/src/Makefile.am b/src/Makefile.am
index dbfefe9c..25b7456c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,31 +1,38 @@
AM_CFLAGS = @C_WFLAGS@
-bin_PROGRAMS = proj nad2bin geod cs2cs
+bin_PROGRAMS = proj nad2bin geod cs2cs cct
EXTRA_PROGRAMS = multistresstest test228
+TESTS = geodtest
+check_PROGRAMS = geodtest
+
AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \
-DMUTEX_@MUTEX_SETTING@ @JNI_INCLUDE@
include_HEADERS = proj.h proj_api.h projects.h geodesic.h \
org_proj4_Projections.h org_proj4_PJ.h
-EXTRA_DIST = makefile.vc proj.def bin_cs2cs.cmake \
+EXTRA_DIST = makefile.vc proj.def bin_cct.cmake bin_cs2cs.cmake \
bin_geod.cmake bin_nad2bin.cmake bin_proj.cmake \
lib_proj.cmake CMakeLists.txt bin_geodtest.cmake geodtest.c
proj_SOURCES = proj.c gen_cheb.c p_series.c
cs2cs_SOURCES = cs2cs.c gen_cheb.c p_series.c
+cct_SOURCES = cct.c proj_strtod.c optargpm.h
nad2bin_SOURCES = nad2bin.c
geod_SOURCES = geod.c geod_set.c geod_interface.c geod_interface.h
multistresstest_SOURCES = multistresstest.c
test228_SOURCES = test228.c
+geodtest_SOURCES = geodtest.c
proj_LDADD = libproj.la
cs2cs_LDADD = libproj.la
+cct_LDADD = libproj.la
nad2bin_LDADD = libproj.la
geod_LDADD = libproj.la
multistresstest_LDADD = libproj.la @THREAD_LIB@
test228_LDADD = libproj.la @THREAD_LIB@
+geodtest_LDADD = libproj.la
lib_LTLIBRARIES = libproj.la
@@ -44,7 +51,7 @@ libproj_la_SOURCES = \
PJ_tcc.c PJ_tcea.c PJ_times.c PJ_tmerc.c \
PJ_airy.c PJ_aitoff.c PJ_august.c PJ_bacon.c \
PJ_chamb.c PJ_hammer.c PJ_lagrng.c PJ_larr.c \
- PJ_lask.c PJ_nocol.c PJ_ob_tran.c PJ_oea.c \
+ PJ_lask.c PJ_latlong.c PJ_nocol.c PJ_ob_tran.c PJ_oea.c \
PJ_tpeqd.c PJ_vandg.c PJ_vandg2.c PJ_vandg4.c \
PJ_wag7.c PJ_lcca.c PJ_geos.c proj_etmerc.c \
PJ_boggs.c PJ_collg.c PJ_comill.c PJ_crast.c PJ_denoy.c \
@@ -55,7 +62,7 @@ libproj_la_SOURCES = \
PJ_nell.c PJ_nell_h.c PJ_patterson.c PJ_putp2.c PJ_putp3.c \
PJ_putp4p.c PJ_putp5.c PJ_putp6.c PJ_qsc.c PJ_robin.c \
PJ_sch.c PJ_sts.c PJ_urm5.c PJ_urmfps.c PJ_wag2.c \
- PJ_wag3.c PJ_wink1.c PJ_wink2.c pj_latlong.c pj_geocent.c \
+ PJ_wag3.c PJ_wink1.c PJ_wink2.c pj_geocent.c \
aasincos.c adjlon.c bch2bps.c bchgen.c \
biveval.c dmstor.c mk_cheby.c pj_auth.c \
pj_deriv.c pj_ell_set.c pj_ellps.c pj_errno.c \
diff --git a/src/PJ_aea.c b/src/PJ_aea.c
index 7d0e935d..228d3afd 100644
--- a/src/PJ_aea.c
+++ b/src/PJ_aea.c
@@ -29,6 +29,7 @@
#define PJ_LIB__
#include <proj.h>
+#include <errno.h>
#include "projects.h"
# define EPS10 1.e-10
@@ -79,23 +80,19 @@ struct pj_opaque {
};
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
+ return pj_default_destructor (P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
+
static XY e_forward (LP lp, PJ *P) { /* Ellipsoid/spheroid, forward */
@@ -154,17 +151,16 @@ static PJ *setup(PJ *P) {
P->inv = e_inverse;
P->fwd = e_forward;
- if (fabs(Q->phi1 + Q->phi2) < EPS10) {
- proj_errno_set(P, PJD_ERR_CONIC_LAT_EQUAL);
- return freeup_new(P);
- }
+ if (fabs(Q->phi1 + Q->phi2) < EPS10)
+ return destructor(P, PJD_ERR_CONIC_LAT_EQUAL);
Q->n = sinphi = sin(Q->phi1);
cosphi = cos(Q->phi1);
secant = fabs(Q->phi1 - Q->phi2) >= EPS10;
if( (Q->ellips = (P->es > 0.))) {
double ml1, m1;
- if (!(Q->en = pj_enfn(P->es))) return freeup_new(P);
+ if (!(Q->en = pj_enfn(P->es)))
+ return destructor(P, 0);
m1 = pj_msfn(sinphi, cosphi, P->es);
ml1 = pj_qsfn(sinphi, P->e, P->one_es);
if (secant) { /* secant cone */
@@ -175,9 +171,8 @@ static PJ *setup(PJ *P) {
m2 = pj_msfn(sinphi, cosphi, P->es);
ml2 = pj_qsfn(sinphi, P->e, P->one_es);
if (ml2 == ml1)
- {
- return freeup_new(P);
- }
+ return destructor(P, 0);
+
Q->n = (m1 * m1 - m2 * m2) / (ml2 - ml1);
}
Q->ec = 1. - .5 * P->one_es * log((1. - P->e) /
@@ -201,8 +196,9 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(aea) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f;
@@ -213,7 +209,7 @@ PJ *PROJECTION(aea) {
PJ *PROJECTION(leac) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->phi2 = pj_param(P->ctx, P->params, "rlat_1").f;
diff --git a/src/PJ_aeqd.c b/src/PJ_aeqd.c
index 4a46cf1c..c6fa9e06 100644
--- a/src/PJ_aeqd.c
+++ b/src/PJ_aeqd.c
@@ -28,6 +28,7 @@
#define PJ_LIB__
#include "geodesic.h"
#include <proj.h>
+#include <errno.h>
#include "projects.h"
struct pj_opaque {
@@ -54,23 +55,18 @@ PROJ_HEAD(aeqd, "Azimuthal Equidistant") "\n\tAzi, Sph&Ell\n\tlat_0 guam";
#define OBLIQ 3
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
- if (P->opaque->en)
- pj_dealloc(P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
+ pj_dealloc (P->opaque->en);
+ return pj_default_destructor (P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
static XY e_guam_fwd(LP lp, PJ *P) { /* Guam elliptical */
XY xy = {0.0,0.0};
@@ -268,8 +264,9 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
PJ *PROJECTION(aeqd) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
geod_init(&Q->g, P->a, P->es / (1 + sqrt(P->one_es)));
P->phi0 = pj_param(P->ctx, P->params, "rlat_0").f;
@@ -290,7 +287,8 @@ PJ *PROJECTION(aeqd) {
P->inv = s_inverse;
P->fwd = s_forward;
} else {
- if (!(Q->en = pj_enfn(P->es))) return freeup_new(P);
+ if (!(Q->en = pj_enfn(P->es)))
+ return pj_default_destructor (P, 0);
if (pj_param(P->ctx, P->params, "bguam").i) {
Q->M1 = pj_mlfn(P->phi0, Q->sinph0, Q->cosph0, Q->en);
P->inv = e_guam_inv;
diff --git a/src/PJ_airy.c b/src/PJ_airy.c
index 2c58bb79..d832b9b7 100644
--- a/src/PJ_airy.c
+++ b/src/PJ_airy.c
@@ -28,6 +28,7 @@
#define PJ_LIB__
#include <proj.h>
+#include <errno.h>
#include "projects.h"
PROJ_HEAD(airy, "Airy") "\n\tMisc Sph, no inv.\n\tno_cut lat_b=";
@@ -104,28 +105,13 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(airy) {
double beta;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/PJ_aitoff.c b/src/PJ_aitoff.c
index 8b1d7f94..3455fa71 100644
--- a/src/PJ_aitoff.c
+++ b/src/PJ_aitoff.c
@@ -30,6 +30,7 @@
#define PJ_LIB__
#include <proj.h>
+#include <errno.h>
#include "projects.h"
@@ -152,22 +153,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
static PJ *setup(PJ *P) {
P->inv = s_inverse;
P->fwd = s_forward;
@@ -179,7 +164,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(aitoff) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
Q->mode = 0;
@@ -190,15 +175,13 @@ PJ *PROJECTION(aitoff) {
PJ *PROJECTION(wintri) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
Q->mode = 1;
if (pj_param(P->ctx, P->params, "tlat_1").i) {
- if ((Q->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.) {
- proj_errno_set(P, PJD_ERR_LAT_LARGER_THAN_90);
- return freeup_new(P);
- }
+ if ((Q->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f)) == 0.)
+ return pj_default_destructor (P, PJD_ERR_LAT_LARGER_THAN_90);
}
else /* 50d28' or acos(2/pi) */
Q->cosphi1 = 0.636619772367581343;
diff --git a/src/PJ_august.c b/src/PJ_august.c
index f5028938..d81644bf 100644
--- a/src/PJ_august.c
+++ b/src/PJ_august.c
@@ -23,15 +23,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(august) {
P->inv = 0;
diff --git a/src/PJ_bacon.c b/src/PJ_bacon.c
index a9c6da44..cb7286be 100644
--- a/src/PJ_bacon.c
+++ b/src/PJ_bacon.c
@@ -1,6 +1,7 @@
# define HLFPI2 2.46740110027233965467 /* (pi/2)^2 */
# define EPS 1e-10
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
@@ -34,26 +35,11 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(bacon) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->bacn = 1;
@@ -67,7 +53,7 @@ PJ *PROJECTION(bacon) {
PJ *PROJECTION(apian) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->bacn = Q->ortl = 0;
@@ -80,7 +66,7 @@ PJ *PROJECTION(apian) {
PJ *PROJECTION(ortel) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->bacn = 0;
diff --git a/src/PJ_bipc.c b/src/PJ_bipc.c
index 97284fcc..0019d614 100644
--- a/src/PJ_bipc.c
+++ b/src/PJ_bipc.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
#include <proj.h>
+#include <errno.h>
#include "projects.h"
PROJ_HEAD(bipc, "Bipolar conic of western hemisphere") "\n\tConic Sph.";
@@ -156,23 +157,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(bipc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->noskew = pj_param(P->ctx, P->params, "bns").i;
diff --git a/src/PJ_boggs.c b/src/PJ_boggs.c
index 8ede9f16..e6efd7d3 100644
--- a/src/PJ_boggs.c
+++ b/src/PJ_boggs.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+# include <errno.h>
# include <projects.h>
PROJ_HEAD(boggs, "Boggs Eumorphic") "\n\tPCyl., no inv., Sph.";
# define NITER 20
@@ -33,15 +34,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(boggs) {
P->es = 0.;
diff --git a/src/PJ_bonne.c b/src/PJ_bonne.c
index 2a576c60..368829c5 100644
--- a/src/PJ_bonne.c
+++ b/src/PJ_bonne.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -83,20 +84,16 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor (P, errlev);
}
@@ -104,14 +101,14 @@ PJ *PROJECTION(bonne) {
double c;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
- if (fabs(Q->phi1) < EPS10) {
- proj_errno_set(P, PJD_ERR_LAT1_IS_ZERO);
- return freeup_new(P);
- }
+ if (fabs(Q->phi1) < EPS10)
+ return destructor (P, PJD_ERR_LAT1_IS_ZERO);
+
if (P->es != 0.0) {
Q->en = pj_enfn(P->es);
Q->m1 = pj_mlfn(Q->phi1, Q->am1 = sin(Q->phi1),
diff --git a/src/PJ_calcofi.c b/src/PJ_calcofi.c
index 25521eed..b188f7e9 100644
--- a/src/PJ_calcofi.c
+++ b/src/PJ_calcofi.c
@@ -149,16 +149,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc (P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(calcofi) {
P->opaque = 0;
diff --git a/src/PJ_cart.c b/src/PJ_cart.c
index 1373e870..914fa94b 100644
--- a/src/PJ_cart.c
+++ b/src/PJ_cart.c
@@ -108,11 +108,6 @@ PROJ_HEAD(cart, "Geodetic/cartesian conversions");
**************************************************************/
-static void freeup (PJ *P) {
- pj_freeup_plain (P);
- return;
-}
-
/*********************************************************************/
static double normal_radius_of_curvature (double a, double es, double phi) {
/*********************************************************************/
@@ -245,6 +240,11 @@ int pj_cart_selftest (void) {
PJ_DERIVS derivs;
PJ_FACTORS factors;
+ const PJ_OPERATIONS *oper_list;
+ const PJ_ELLPS *ellps_list;
+ const PJ_UNITS *unit_list;
+ const PJ_PRIME_MERIDIANS *pm_list;
+
int err;
size_t n, sz;
double dist, h, t;
@@ -253,7 +253,7 @@ int pj_cart_selftest (void) {
char buf[40];
/* An utm projection on the GRS80 ellipsoid */
- P = proj_create (0, arg);
+ P = proj_create (PJ_DEFAULT_CTX, arg);
if (0==P)
return 1;
@@ -262,7 +262,7 @@ int pj_cart_selftest (void) {
proj_destroy (P);
/* Same projection, now using argc/argv style initialization */
- P = proj_create_argv (0, 3, args);
+ P = proj_create_argv (PJ_DEFAULT_CTX, 3, args);
if (0==P)
return 2;
@@ -306,7 +306,7 @@ int pj_cart_selftest (void) {
proj_destroy (P);
/* Now do some 3D transformations */
- P = proj_create (0, "+proj=cart +ellps=GRS80");
+ P = proj_create (PJ_DEFAULT_CTX, "+proj=cart +ellps=GRS80");
if (0==P)
return 6;
@@ -320,8 +320,8 @@ int pj_cart_selftest (void) {
b = proj_trans_obs (P, PJ_FWD, a);
/* Check roundtrip precision for 10000 iterations each way */
- dist = proj_roundtrip (P, PJ_FWD, 10000, a);
- dist = proj_roundtrip (P, PJ_INV, 10000, b);
+ dist = proj_roundtrip (P, PJ_FWD, 10000, a.coo);
+ dist = proj_roundtrip (P, PJ_INV, 10000, b.coo);
if (dist > 2e-9)
return 7;
@@ -333,7 +333,7 @@ int pj_cart_selftest (void) {
a.coo.lpz.z = 100;
/* Forward projection: Ellipsoidal-to-3D-Cartesian */
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 1e-12)
return 8;
@@ -344,7 +344,7 @@ int pj_cart_selftest (void) {
a.coo.lpz.z = 100;
/* Forward projection: Ellipsoidal-to-3D-Cartesian */
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 1e-12)
return 9;
@@ -374,7 +374,7 @@ int pj_cart_selftest (void) {
/* Testing the proj_transform nightmare */
/* An utm projection on the GRS80 ellipsoid */
- P = proj_create (0, "+proj=utm +zone=32 +ellps=GRS80");
+ P = proj_create (PJ_DEFAULT_CTX, "+proj=utm +zone=32 +ellps=GRS80");
if (0==P)
return 13;
@@ -457,7 +457,7 @@ int pj_cart_selftest (void) {
proj_destroy (P);
/* test proj_create_crs_to_crs() */
- P = proj_create_crs_to_crs(0, "epsg:25832", "epsg:25833");
+ P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "epsg:25832", "epsg:25833");
if (P==0)
return 50;
@@ -472,7 +472,7 @@ int pj_cart_selftest (void) {
proj_destroy(P);
/* let's make sure that only entries in init-files results in a usable PJ */
- P = proj_create_crs_to_crs(0, "proj=utm +zone=32 +datum=WGS84", "proj=utm +zone=33 +datum=WGS84");
+ P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "proj=utm +zone=32 +datum=WGS84", "proj=utm +zone=33 +datum=WGS84");
if (P != 0) {
proj_destroy(P);
return 52;
@@ -486,20 +486,20 @@ int pj_cart_selftest (void) {
/* proj_info() */
/* this one is difficult to test, since the output changes with the setup */
info = proj_info();
- if (info.version) {
+ if (info.version[0] != '\0' ) {
char tmpstr[64];
sprintf(tmpstr, "%d.%d.%d", info.major, info.minor, info.patch);
if (strcmp(info.version, tmpstr)) return 55;
}
- if (!info.release) return 56;
- if (!info.searchpath) return 57;
+ if (info.release[0] == '\0') return 56;
+ if (info.searchpath[0] == '\0') return 57;
/* proj_pj_info() */
- P = proj_create(0, "+proj=august"); /* august has no inverse */
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=august"); /* august has no inverse */
if (proj_pj_info(P).has_inverse) { proj_destroy(P); return 60; }
proj_destroy(P);
- P = proj_create(0, arg);
+ P = proj_create(PJ_DEFAULT_CTX, arg);
pj_info = proj_pj_info(P);
if ( !pj_info.has_inverse ) { proj_destroy(P); return 61; }
if ( strcmp(pj_info.definition, arg) ) { proj_destroy(P); return 62; }
@@ -518,7 +518,8 @@ int pj_cart_selftest (void) {
if ( strlen(init_info.filename) != 0 ) return 67;
init_info = proj_init_info("epsg");
- if ( strcmp(init_info.origin, "EPSG") ) return 69;
+ /* Need to allow for "Unknown" until all commonly distributed EPSG-files comes with a metadata section */
+ if ( strcmp(init_info.origin, "EPSG") && strcmp(init_info.origin, "Unknown") ) return 69;
if ( strcmp(init_info.name, "epsg") ) return 68;
@@ -539,7 +540,7 @@ int pj_cart_selftest (void) {
/* test proj_derivatives_retrieve() and proj_factors_retrieve() */
- P = proj_create(0, "+proj=merc");
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=merc");
a = proj_obs_null;
a.coo.lp.lam = PJ_TORAD(12);
a.coo.lp.phi = PJ_TORAD(55);
@@ -566,6 +567,22 @@ int pj_cart_selftest (void) {
proj_destroy(P);
+ /* Check that proj_list_* functions work by looping through them */
+ n = 0;
+ for (oper_list = proj_list_operations(); oper_list->id; ++oper_list) n++;
+ if (n == 0) return 90;
+
+ n = 0;
+ for (ellps_list = proj_list_ellps(); ellps_list->id; ++ellps_list) n++;
+ if (n == 0) return 91;
+
+ n = 0;
+ for (unit_list = proj_list_units(); unit_list->id; ++unit_list) n++;
+ if (n == 0) return 92;
+
+ n = 0;
+ for (pm_list = proj_list_prime_meridians(); pm_list->id; ++pm_list) n++;
+ if (n == 0) return 93;
return 0;
}
diff --git a/src/PJ_cass.c b/src/PJ_cass.c
index 85280205..6955146e 100644
--- a/src/PJ_cass.c
+++ b/src/PJ_cass.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-# include <projects.h>
+# include <errno.h>
+# include "projects.h"
PROJ_HEAD(cass, "Cassini") "\n\tCyl, Sph&Ell";
@@ -77,22 +78,18 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
return lp;
}
-
-static void *freeup_new(PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
- pj_dealloc(P->opaque->en);
- pj_dealloc(P->opaque);
- return pj_dealloc(P);
+ pj_dealloc (P->opaque->en);
+ return pj_default_destructor (P, errlev);
}
-static void freeup(PJ *P) { /* Destructor */
- freeup_new (P);
- return;
-}
+
PJ *PROJECTION(cass) {
@@ -106,11 +103,12 @@ PJ *PROJECTION(cass) {
/* otherwise it's ellipsoidal */
P->opaque = pj_calloc (1, sizeof (struct pj_opaque));
if (0==P->opaque)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
+ P->destructor = destructor;
P->opaque->en = pj_enfn (P->es);
if (0==P->opaque->en)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque->m0 = pj_mlfn (P->phi0, sin (P->phi0), cos (P->phi0), P->opaque->en);
P->inv = e_inverse;
diff --git a/src/PJ_cc.c b/src/PJ_cc.c
index d43f5a88..9ba51386 100644
--- a/src/PJ_cc.c
+++ b/src/PJ_cc.c
@@ -27,16 +27,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(cc) {
P->es = 0.;
diff --git a/src/PJ_cea.c b/src/PJ_cea.c
index 20f03547..0ec7376c 100644
--- a/src/PJ_cea.c
+++ b/src/PJ_cea.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -52,46 +53,39 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
return (lp);
}
-
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->apa);
- pj_dealloc (P->opaque);
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
PJ *PROJECTION(cea) {
double t = 0.0;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
if (pj_param(P->ctx, P->params, "tlat_ts").i) {
P->k0 = cos(t = pj_param(P->ctx, P->params, "rlat_ts").f);
- if (P->k0 < 0.) {
- proj_errno_set(P, PJD_ERR_LAT_TS_LARGER_THAN_90);
- freeup_new(P);
- return 0;
- }
+ if (P->k0 < 0.)
+ return pj_default_destructor (P, PJD_ERR_LAT_TS_LARGER_THAN_90);
}
if (P->es != 0.0) {
t = sin(t);
P->k0 /= sqrt(1. - P->es * t * t);
P->e = sqrt(P->es);
- if (!(Q->apa = pj_authset(P->es))) {
- return freeup_new(P);
- }
+ if (!(Q->apa = pj_authset(P->es)))
+ return pj_default_destructor(P, ENOMEM);
+
Q->qp = pj_qsfn(1., P->e, P->one_es);
P->inv = e_inverse;
P->fwd = e_forward;
diff --git a/src/PJ_chamb.c b/src/PJ_chamb.c
index c6028a7a..9edb699f 100644
--- a/src/PJ_chamb.c
+++ b/src/PJ_chamb.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -93,28 +94,13 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(chamb) {
int i, j;
char line[10];
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -131,10 +117,8 @@ PJ *PROJECTION(chamb) {
j = i == 2 ? 0 : i + 1;
Q->c[i].v = vect(P->ctx,Q->c[j].phi - Q->c[i].phi, Q->c[i].cosphi, Q->c[i].sinphi,
Q->c[j].cosphi, Q->c[j].sinphi, Q->c[j].lam - Q->c[i].lam);
- if (Q->c[i].v.r == 0.0) {
- proj_errno_set(P, PJD_ERR_CONTROL_POINT_NO_DIST);
- return freeup_new(P);
- }
+ if (Q->c[i].v.r == 0.0)
+ return pj_default_destructor (P, PJD_ERR_CONTROL_POINT_NO_DIST);
/* co-linearity problem ignored for now */
}
Q->beta_0 = lc(P->ctx,Q->c[0].v.r, Q->c[2].v.r, Q->c[1].v.r);
diff --git a/src/PJ_collg.c b/src/PJ_collg.c
index c646d99a..01c65cd0 100644
--- a/src/PJ_collg.c
+++ b/src/PJ_collg.c
@@ -41,16 +41,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(collg) {
P->es = 0.0;
P->inv = s_inverse;
diff --git a/src/PJ_comill.c b/src/PJ_comill.c
index 1a4508b1..a329c0ac 100644
--- a/src/PJ_comill.c
+++ b/src/PJ_comill.c
@@ -70,15 +70,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
return lp;
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(comill) {
P->es = 0;
diff --git a/src/PJ_crast.c b/src/PJ_crast.c
index 09c4f1e4..b47b0e55 100644
--- a/src/PJ_crast.c
+++ b/src/PJ_crast.c
@@ -29,17 +29,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(crast) {
P->es = 0.0;
P->inv = s_inverse;
diff --git a/src/PJ_denoy.c b/src/PJ_denoy.c
index 9eb818b9..3964c7da 100644
--- a/src/PJ_denoy.c
+++ b/src/PJ_denoy.c
@@ -22,16 +22,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(denoy) {
P->es = 0.0;
P->fwd = s_forward;
diff --git a/src/PJ_eck1.c b/src/PJ_eck1.c
index da159017..bd5c1916 100644
--- a/src/PJ_eck1.c
+++ b/src/PJ_eck1.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(eck1, "Eckert I") "\n\tPCyl., Sph.";
#define FC 0.92131773192356127802
@@ -28,23 +28,14 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(eck1) {
P->es = 0.0;
P->inv = s_inverse;
P->fwd = s_forward;
- return P ;
+ return P
+;
}
diff --git a/src/PJ_eck2.c b/src/PJ_eck2.c
index 6ef2a96c..3b2e4e49 100644
--- a/src/PJ_eck2.c
+++ b/src/PJ_eck2.c
@@ -43,16 +43,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc (P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(eck2) {
P->es = 0.;
diff --git a/src/PJ_eck3.c b/src/PJ_eck3.c
index 3fe5c49f..8dc72c7c 100644
--- a/src/PJ_eck3.c
+++ b/src/PJ_eck3.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(eck3, "Eckert III") "\n\tPCyl, Sph.";
PROJ_HEAD(putp1, "Putnins P1") "\n\tPCyl, Sph.";
@@ -36,22 +37,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ *setup(PJ *P) {
P->es = 0.;
P->inv = s_inverse;
@@ -63,7 +48,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(eck3) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->C_x = 0.42223820031577120149;
@@ -78,7 +63,7 @@ PJ *PROJECTION(eck3) {
PJ *PROJECTION(kav7) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
/* Defined twice in original code - Using 0.866...,
@@ -96,7 +81,7 @@ PJ *PROJECTION(kav7) {
PJ *PROJECTION(wag6) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->C_x = Q->C_y = 0.94745;
@@ -110,7 +95,7 @@ PJ *PROJECTION(wag6) {
PJ *PROJECTION(putp1) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->C_x = 1.89490;
diff --git a/src/PJ_eck4.c b/src/PJ_eck4.c
index 358c0224..0ad9ec43 100644
--- a/src/PJ_eck4.c
+++ b/src/PJ_eck4.c
@@ -51,18 +51,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(eck4) {
P->es = 0.0;
P->inv = s_inverse;
diff --git a/src/PJ_eck5.c b/src/PJ_eck5.c
index 5fbdf7db..13617c1d 100644
--- a/src/PJ_eck5.c
+++ b/src/PJ_eck5.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(eck5, "Eckert V") "\n\tPCyl, Sph.";
@@ -28,18 +28,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(eck5) {
P->es = 0.0;
P->inv = s_inverse;
diff --git a/src/PJ_eqc.c b/src/PJ_eqc.c
index 576e0e3a..4f471df1 100644
--- a/src/PJ_eqc.c
+++ b/src/PJ_eqc.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -32,33 +33,14 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(eqc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
- if ((Q->rc = cos(pj_param(P->ctx, P->params, "rlat_ts").f)) <= 0.) {
- proj_errno_set(P, PJD_ERR_LAT_TS_LARGER_THAN_90);
- return freeup_new(P);
- }
+ if ((Q->rc = cos(pj_param(P->ctx, P->params, "rlat_ts").f)) <= 0.)
+ return pj_default_destructor (P, PJD_ERR_LAT_TS_LARGER_THAN_90);
P->inv = s_inverse;
P->fwd = s_forward;
P->es = 0.;
diff --git a/src/PJ_eqdc.c b/src/PJ_eqdc.c
index eaf4db0b..6b3449f7 100644
--- a/src/PJ_eqdc.c
+++ b/src/PJ_eqdc.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -66,23 +67,15 @@ static void special(LP lp, PJ *P, struct FACTORS *fac) {
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- if (P->opaque->en)
- pj_dealloc (P->opaque->en);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
+ if (0==P->opaque)
+ return pj_default_destructor (P, errlev);
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ pj_dealloc (P->opaque->en);
+ return pj_default_destructor (P, errlev);
}
@@ -92,20 +85,18 @@ PJ *PROJECTION(eqdc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
Q->phi2 = pj_param(P->ctx, P->params, "rlat_2").f;
- if (fabs(Q->phi1 + Q->phi2) < EPS10) {
- proj_errno_set(P, PJD_ERR_CONIC_LAT_EQUAL);
- freeup_new(P);
- return 0;
- }
+ if (fabs(Q->phi1 + Q->phi2) < EPS10)
+ pj_default_destructor (P, PJD_ERR_CONIC_LAT_EQUAL);
if (!(Q->en = pj_enfn(P->es)))
- return freeup_new(P);
+ return pj_default_destructor(P, ENOMEM);
Q->n = sinphi = sin(Q->phi1);
cosphi = cos(Q->phi1);
diff --git a/src/PJ_fahey.c b/src/PJ_fahey.c
index 4f4b92a4..42318f8f 100644
--- a/src/PJ_fahey.c
+++ b/src/PJ_fahey.c
@@ -29,19 +29,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(fahey) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_fouc_s.c b/src/PJ_fouc_s.c
index 32eeeb4f..343e5878 100644
--- a/src/PJ_fouc_s.c
+++ b/src/PJ_fouc_s.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -48,34 +49,16 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(fouc_s) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = pj_param(P->ctx, P->params, "dn").f;
- if (Q->n < 0. || Q->n > 1.) {
- proj_errno_set(P, PJD_ERR_N_OUT_OF_RANGE);
- return freeup_new(P);
- }
+ if (Q->n < 0. || Q->n > 1.)
+ return pj_default_destructor (P, PJD_ERR_N_OUT_OF_RANGE);
+
Q->n1 = 1. - Q->n;
P->es = 0;
P->inv = s_inverse;
diff --git a/src/PJ_gall.c b/src/PJ_gall.c
index bca36bc7..01a56e33 100644
--- a/src/PJ_gall.c
+++ b/src/PJ_gall.c
@@ -31,20 +31,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(gall) {
P->es = 0.0;
diff --git a/src/PJ_geos.c b/src/PJ_geos.c
index b929c06b..5fd3e56b 100644
--- a/src/PJ_geos.c
+++ b/src/PJ_geos.c
@@ -28,6 +28,7 @@
*/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -39,7 +40,6 @@ struct pj_opaque {
double radius_g;
double radius_g_1;
double C;
- char *sweep_axis;
int flip_axis;
};
@@ -189,47 +189,27 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(geos) {
+ char *sweep_axis;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
- if ((Q->h = pj_param(P->ctx, P->params, "dh").f) <= 0.){
- proj_errno_set(P, PJD_ERR_H_LESS_THAN_ZERO);
- return freeup_new(P);
- }
+ if ((Q->h = pj_param(P->ctx, P->params, "dh").f) <= 0.)
+ return pj_default_destructor (P, PJD_ERR_H_LESS_THAN_ZERO);
- if (P->phi0 != 0.0) {
- proj_errno_set(P, PJD_ERR_UNKNOWN_PRIME_MERIDIAN);
- return freeup_new(P);
- }
+ if (P->phi0 != 0.0)
+ return pj_default_destructor (P, PJD_ERR_UNKNOWN_PRIME_MERIDIAN);
- Q->sweep_axis = pj_param(P->ctx, P->params, "ssweep").s;
- if (Q->sweep_axis == NULL)
+ sweep_axis = pj_param(P->ctx, P->params, "ssweep").s;
+ if (sweep_axis == NULL)
Q->flip_axis = 0;
else {
- if (Q->sweep_axis[1] != '\0' || (Q->sweep_axis[0] != 'x' && Q->sweep_axis[0] != 'y')) {
- proj_errno_set(P, PJD_ERR_INVALID_SWEEP_AXIS);
- return freeup_new(P);
- }
- if (Q->sweep_axis[0] == 'x')
+ if (sweep_axis[1] != '\0' || (sweep_axis[0] != 'x' && sweep_axis[0] != 'y'))
+ return pj_default_destructor (P, PJD_ERR_INVALID_SWEEP_AXIS);
+
+ if (sweep_axis[0] == 'x')
Q->flip_axis = 1;
else
Q->flip_axis = 0;
diff --git a/src/PJ_gins8.c b/src/PJ_gins8.c
index 48bdf3a5..b27ec092 100644
--- a/src/PJ_gins8.c
+++ b/src/PJ_gins8.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(gins8, "Ginsburg VIII (TsNIIGAiK)") "\n\tPCyl, Sph., no inv.";
@@ -22,19 +22,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(gins8) {
P->es = 0.0;
P->inv = 0;
diff --git a/src/PJ_gn_sinu.c b/src/PJ_gn_sinu.c
index 57bbecc8..d13f2834 100644
--- a/src/PJ_gn_sinu.c
+++ b/src/PJ_gn_sinu.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -86,40 +87,18 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_msg (PJ *P, int errlev) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
if (0==P->opaque)
- return pj_dealloc (P);
-
- if (P->opaque->en)
- pj_dalloc(P->opaque->en);
+ return pj_default_destructor (P, errlev);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
+ pj_dealloc (P->opaque->en);
+ return pj_default_destructor (P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
/* for spheres, only */
static void setup(PJ *P) {
@@ -135,12 +114,13 @@ static void setup(PJ *P) {
PJ *PROJECTION(sinu) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
if (!(Q->en = pj_enfn(P->es)))
- return freeup_new(P);
-
+ return pj_default_destructor (P, ENOMEM);
+
if (P->es != 0.0) {
P->inv = e_inverse;
P->fwd = e_forward;
@@ -156,8 +136,9 @@ PJ *PROJECTION(sinu) {
PJ *PROJECTION(eck6) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->m = 1.;
Q->n = 2.570796326794896619231321691;
@@ -170,8 +151,9 @@ PJ *PROJECTION(eck6) {
PJ *PROJECTION(mbtfps) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->m = 0.5;
Q->n = 1.785398163397448309615660845;
@@ -184,16 +166,17 @@ PJ *PROJECTION(mbtfps) {
PJ *PROJECTION(gn_sinu) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
if (pj_param(P->ctx, P->params, "tn").i && pj_param(P->ctx, P->params, "tm").i) {
Q->n = pj_param(P->ctx, P->params, "dn").f;
Q->m = pj_param(P->ctx, P->params, "dm").f;
- if (Q->n < 0 || Q->m < 0)
- return freeup_msg(P, PJD_ERR_INVALID_M_OR_N);
+ if (Q->n <= 0 || Q->m < 0)
+ return destructor (P, PJD_ERR_INVALID_M_OR_N);
} else
- return freeup_msg(P, PJD_ERR_INVALID_M_OR_N);
+ return destructor (P, PJD_ERR_INVALID_M_OR_N);
setup(P);
diff --git a/src/PJ_gnom.c b/src/PJ_gnom.c
index 099f32fb..1d3f3386 100644
--- a/src/PJ_gnom.c
+++ b/src/PJ_gnom.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -111,27 +112,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(gnom) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
if (fabs(fabs(P->phi0) - M_HALFPI) < EPS10) {
diff --git a/src/PJ_goode.c b/src/PJ_goode.c
index fff12a78..3bfeb21f 100644
--- a/src/PJ_goode.c
+++ b/src/PJ_goode.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -43,42 +44,34 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
if (0==P->opaque)
- return pj_dealloc(P);
- if (P->opaque->sinu)
- pj_dealloc(P->opaque->sinu);
- if (P->opaque->moll)
- pj_dealloc(P->opaque->moll);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-
+ return pj_default_destructor (P, errlev);
+ pj_free (P->opaque->sinu);
+ pj_free (P->opaque->moll);
+ return pj_default_destructor (P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(goode) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
P->es = 0.;
if (!(Q->sinu = pj_sinu(0)) || !(Q->moll = pj_moll(0)))
- return freeup_new(P);
+ return destructor (P, ENOMEM);
Q->sinu->es = 0.;
- Q->sinu->ctx = P->ctx;
- Q->moll->ctx = P->ctx;
+ Q->sinu->ctx = P->ctx;
+ Q->moll->ctx = P->ctx;
if (!(Q->sinu = pj_sinu(Q->sinu)) || !(Q->moll = pj_moll(Q->moll)))
- return freeup_new(P);
-
+ return destructor (P, ENOMEM);
+
P->fwd = s_forward;
P->inv = s_inverse;
@@ -104,7 +97,11 @@ int pj_goode_selftest (void) {
};
XY s_fwd_expect[] = {
- { 223368.11902663155, 111701.07212763709}, { 223368.11902663155, -111701.07212763709}, {-223368.11902663155, 111701.07212763709}, {-223368.11902663155, -111701.07212763709}, };
+ { 223368.11902663155, 111701.07212763709},
+ { 223368.11902663155, -111701.07212763709},
+ {-223368.11902663155, 111701.07212763709},
+ {-223368.11902663155, -111701.07212763709},
+ };
XY inv_in[] = {
{ 200, 100},
@@ -114,7 +111,11 @@ int pj_goode_selftest (void) {
};
LP s_inv_expect[] = {
- { 0.0017904931100023887, 0.00089524655489191132}, { 0.0017904931100023887, -0.00089524655489191132}, {-0.0017904931100023887, 0.00089524655489191132}, {-0.0017904931100023887, -0.00089524655489191132}, };
+ { 0.0017904931100023887, 0.00089524655489191132},
+ { 0.0017904931100023887, -0.00089524655489191132},
+ {-0.0017904931100023887, 0.00089524655489191132},
+ {-0.0017904931100023887, -0.00089524655489191132},
+ };
return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect);
}
diff --git a/src/PJ_gstmerc.c b/src/PJ_gstmerc.c
index a550ab2c..c2846761 100644
--- a/src/PJ_gstmerc.c
+++ b/src/PJ_gstmerc.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(gstmerc, "Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion)")
"\n\tCyl, Sph&Ell\n\tlat_0= lon_0= k_0=";
@@ -46,27 +47,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(gstmerc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->lamc = P->lam0;
diff --git a/src/PJ_hammer.c b/src/PJ_hammer.c
index 58182398..c18c9a69 100644
--- a/src/PJ_hammer.c
+++ b/src/PJ_hammer.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -8,7 +9,7 @@ PROJ_HEAD(hammer, "Hammer & Eckert-Greifendorff")
#define EPS 1.0e-10
struct pj_opaque {
- double w; \
+ double w;
double m, rm;
};
@@ -43,40 +44,20 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(hammer) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
if (pj_param(P->ctx, P->params, "tW").i) {
- if ((Q->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.) {
- proj_errno_set(P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
- return freeup_new(P);
- }
+ if ((Q->w = fabs(pj_param(P->ctx, P->params, "dW").f)) <= 0.)
+ return pj_default_destructor (P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
} else
Q->w = .5;
if (pj_param(P->ctx, P->params, "tM").i) {
- if ((Q->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.) {
- proj_errno_set(P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
- return freeup_new(P);
- }
+ if ((Q->m = fabs(pj_param(P->ctx, P->params, "dM").f)) <= 0.)
+ return pj_default_destructor (P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
} else
Q->m = 1.;
diff --git a/src/PJ_hatano.c b/src/PJ_hatano.c
index d75a96a3..be95fe73 100644
--- a/src/PJ_hatano.c
+++ b/src/PJ_hatano.c
@@ -71,19 +71,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(hatano) {
P->es = 0.;
P->inv = s_inverse;
@@ -110,10 +97,14 @@ int pj_hatano_selftest (void) {
};
XY s_fwd_expect[] = {
- { 189878.87894652804, 131409.8024406255 },
- { 189881.08195244463, -131409.14227607418 },
- {-189878.87894652804, 131409.8024406255 },
- {-189881.08195244463, -131409.14227607418 },
+ { 189878.87894652804, 131409.8024406255
+},
+ { 189881.08195244463, -131409.14227607418
+},
+ {-189878.87894652804, 131409.8024406255
+},
+ {-189881.08195244463, -131409.14227607418
+},
};
XY inv_in[] = {
@@ -124,10 +115,14 @@ int pj_hatano_selftest (void) {
};
LP s_inv_expect[] = {
- { 0.0021064624821817597, 0.00076095689425791926 },
- { 0.0021064624821676096, -0.00076095777439265377 },
- {-0.0021064624821817597, 0.00076095689425791926 },
- {-0.0021064624821676096, -0.00076095777439265377 },
+ { 0.0021064624821817597, 0.00076095689425791926
+},
+ { 0.0021064624821676096, -0.00076095777439265377
+},
+ {-0.0021064624821817597, 0.00076095689425791926
+},
+ {-0.0021064624821676096, -0.00076095777439265377
+},
};
return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect);
diff --git a/src/PJ_healpix.c b/src/PJ_healpix.c
index ef53e58f..241d7ef4 100644
--- a/src/PJ_healpix.c
+++ b/src/PJ_healpix.c
@@ -29,6 +29,7 @@
* SOFTWARE.
*****************************************************************************/
# define PJ_LIB__
+# include <errno.h>
# include <proj.h>
# include "projects.h"
@@ -598,30 +599,24 @@ static LP e_rhealpix_inverse(XY xy, PJ *P) { /* ellipsoid */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- if (P->opaque->apa)
- pj_dealloc(P->opaque->apa);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
+ if (0==P->opaque)
+ return pj_default_destructor (P, errlev);
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ pj_dealloc (P->opaque->apa);
+ return pj_default_destructor (P, errlev);
}
PJ *PROJECTION(healpix) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
if (P->es != 0.0) {
Q->apa = pj_authset(P->es); /* For auth_lat(). */
@@ -642,21 +637,18 @@ PJ *PROJECTION(healpix) {
PJ *PROJECTION(rhealpix) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
Q->north_square = pj_param(P->ctx, P->params,"inorth_square").i;
Q->south_square = pj_param(P->ctx, P->params,"isouth_square").i;
/* Check for valid north_square and south_square inputs. */
- if (Q->north_square < 0 || Q->north_square > 3) {
- proj_errno_set(P, PJD_ERR_AXIS);
- return freeup_new(P);
- }
- if (Q->south_square < 0 || Q->south_square > 3) {
- proj_errno_set(P, PJD_ERR_AXIS);
- return freeup_new(P);
- }
+ if (Q->north_square < 0 || Q->north_square > 3)
+ return destructor (P, PJD_ERR_AXIS);
+ if (Q->south_square < 0 || Q->south_square > 3)
+ return destructor (P, PJD_ERR_AXIS);
if (P->es != 0.0) {
Q->apa = pj_authset(P->es); /* For auth_lat(). */
Q->qp = pj_qsfn(1.0, P->e, P->one_es); /* For auth_lat(). */
diff --git a/src/PJ_helmert.c b/src/PJ_helmert.c
index e291c189..ffbdd01a 100644
--- a/src/PJ_helmert.c
+++ b/src/PJ_helmert.c
@@ -43,12 +43,12 @@ Last update: 2017-05-15
***********************************************************************/
#define PJ_LIB__
-#include "proj_internal.h"
-#include <projects.h>
-#include <geocent.h>
#include <assert.h>
#include <stddef.h>
#include <errno.h>
+#include "proj_internal.h"
+#include "projects.h"
+#include "geocent.h"
PROJ_HEAD(helmert, "3(6)-, 4(8)- and 7(14)-parameter Helmert shift");
static XYZ helmert_forward_3d (LPZ lpz, PJ *P);
@@ -56,28 +56,6 @@ static LPZ helmert_reverse_3d (XYZ xyz, PJ *P);
-static void *freeup_msg (PJ *P, int errlev) { /* Destructor */
- if (0==P)
- return 0;
-
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-/* Adapts pipeline_freeup to the format defined for the PJ object */
-static void freeup (PJ *P) {
- freeup_msg (P, 0);
- return;
-}
-
-
/***********************************************************************/
struct pj_opaque_helmert {
/************************************************************************
@@ -484,7 +462,7 @@ PJ *PROJECTION(helmert) {
/***********************************************************************/
struct pj_opaque_helmert *Q = pj_calloc (1, sizeof (struct pj_opaque_helmert));
if (0==Q)
- return freeup_msg (P, ENOMEM);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = (void *) Q;
P->fwdobs = helmert_forward_obs;
@@ -527,7 +505,7 @@ PJ *PROJECTION(helmert) {
if (pj_param (P->ctx, P->params, "ts").i) {
Q->scale_0 = pj_param (P->ctx, P->params, "ds").f;
if (pj_param (P->ctx, P->params, "ttheta").i && Q->scale_0 == 0.0)
- return freeup_msg(P, -PJD_ERR_INVALID_SCALE);
+ return pj_default_destructor (P, PJD_ERR_INVALID_SCALE);
}
/* Translation rates */
diff --git a/src/PJ_hgridshift.c b/src/PJ_hgridshift.c
index 41c2b629..0adc9e00 100644
--- a/src/PJ_hgridshift.c
+++ b/src/PJ_hgridshift.c
@@ -1,25 +1,9 @@
#define PJ_LIB__
#include "proj_internal.h"
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(hgridshift, "Horizontal grid shift");
-static void *freeup_msg (PJ *P, int errlev) {
- if (0==P)
- return 0;
-
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_msg (P, 0);
- return;
-}
-
static XYZ forward_3d(LPZ lpz, PJ *P) {
PJ_TRIPLET point;
@@ -67,23 +51,30 @@ static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) {
}
-PJ *PROJECTION(hgridshift) {
- if (!pj_param(P->ctx, P->params, "tgrids").i) {
- proj_log_error(P, "hgridshift: +grids parameter missing.");
- return freeup_msg(P, -1);
- }
+#if 0
+static XY forward_xy(LP lp, PJ *P) {
+ PJ_TRIPLET point;
+ point.lp = lp;
+ point.lpz.z = 0;
+ point.xyz = forward_3d (point.lpz, P);
+ return point.xy;
+}
- /* Build gridlist. P->gridlist can be empty if +grids only ask for optional grids. */
- P->gridlist = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, "sgrids").s,
- &(P->gridlist_count) );
- /* Was gridlist compiled properly? */
- if ( pj_ctx_get_errno(P->ctx) ) {
- proj_log_error(P, "hgridshift: could not find required grid(s).");
- return freeup_msg(P, -38);
- }
+static LP reverse_lp(XY xy, PJ *P) {
+ PJ_TRIPLET point;
+ point.xy = xy;
+ point.xyz.z = 0;
+ point.lpz = reverse_3d (point.xyz, P);
+ return point.lp;
+}
+#endif
+
+
+PJ *PROJECTION(hgridshift) {
+
P->fwdobs = forward_obs;
P->invobs = reverse_obs;
P->fwd3d = forward_3d;
@@ -94,6 +85,21 @@ PJ *PROJECTION(hgridshift) {
P->left = PJ_IO_UNITS_RADIANS;
P->right = PJ_IO_UNITS_RADIANS;
+ if (0==pj_param(P->ctx, P->params, "tgrids").i) {
+ proj_log_error(P, "hgridshift: +grids parameter missing.");
+ return pj_default_destructor (P, PJD_ERR_NO_ARGS);
+ }
+
+ /* Build gridlist. P->gridlist can be empty if +grids only ask for optional grids. */
+ P->gridlist = pj_gridlist_from_nadgrids( P->ctx, pj_param(P->ctx, P->params, "sgrids").s,
+ &(P->gridlist_count) );
+
+ /* Was gridlist compiled properly? */
+ if ( pj_ctx_get_errno(pj_get_ctx(P)) ) {
+ proj_log_error(P, "hgridshift: could not find required grid(s).");
+ return pj_default_destructor (P, PJD_ERR_FAILED_TO_LOAD_GRID);
+ }
+
return P;
}
@@ -108,26 +114,29 @@ int pj_hgridshift_selftest (void) {
double dist;
/* fail on purpose: +grids parameter is mandatory*/
- P = proj_create(0, "+proj=hgridshift");
- if (0!=P)
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift");
+ if (0!=P) {
+ proj_destroy (P);
return 99;
-
+ }
+
/* fail on purpose: open non-existing grid */
- P = proj_create(0, "+proj=hgridshift +grids=nonexistinggrid.gsb");
- if (0!=P)
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift +grids=@nonexistinggrid.gsb,anothernonexistinggrid.gsb");
+ if (0!=P) {
+ proj_destroy (P);
return 999;
-
-
+ }
+
/* Failure most likely means the grid is missing */
- P = proj_create (0, "+proj=hgridshift +grids=nzgd2kgrid0005.gsb +ellps=GRS80");
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=hgridshift +grids=nzgd2kgrid0005.gsb +ellps=GRS80");
if (0==P)
return 10;
-
+
a = proj_obs_null;
a.coo.lpz.lam = PJ_TORAD(173);
a.coo.lpz.phi = PJ_TORAD(-45);
-
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 0.00000001)
return 1;
diff --git a/src/PJ_horner.c b/src/PJ_horner.c
index 56980f72..d6d2c51c 100644
--- a/src/PJ_horner.c
+++ b/src/PJ_horner.c
@@ -1,6 +1,6 @@
#define PJ_LIB__
#include "proj_internal.h"
-#include <projects.h>
+#include "projects.h"
#include <assert.h>
#include <stddef.h>
#include <math.h>
@@ -94,7 +94,7 @@ PROJ_HEAD(horner, "Horner polynomial evaluation");
struct horner;
typedef struct horner HORNER;
-static UV horner (const HORNER *transformation, enum proj_direction, UV position);
+static UV horner (const HORNER *transformation, PJ_DIRECTION direction, UV position);
static HORNER *horner_alloc (size_t order, int complex_polynomia);
static void horner_free (HORNER *h);
@@ -128,6 +128,8 @@ static void horner_free (HORNER *h) {
horner_dealloc (h->fwd_u);
horner_dealloc (h->fwd_c);
horner_dealloc (h->inv_c);
+ horner_dealloc (h->fwd_origin);
+ horner_dealloc (h->inv_origin);
horner_dealloc (h);
}
@@ -176,7 +178,7 @@ static HORNER *horner_alloc (size_t order, int complex_polynomia) {
/**********************************************************************/
-static UV horner (const HORNER *transformation, enum proj_direction direction, UV position) {
+static UV horner (const HORNER *transformation, PJ_DIRECTION direction, UV position) {
/***********************************************************************
A reimplementation of the classic Engsager/Poder 2D Horner polynomial
@@ -301,7 +303,7 @@ static PJ_OBS horner_reverse_obs (PJ_OBS point, PJ *P) {
/**********************************************************************/
-static UV complex_horner (const HORNER *transformation, enum proj_direction direction, UV position) {
+static UV complex_horner (const HORNER *transformation, PJ_DIRECTION direction, UV position) {
/***********************************************************************
A reimplementation of a classic Engsager/Poder Horner complex
@@ -380,18 +382,14 @@ static PJ_OBS complex_horner_reverse_obs (PJ_OBS point, PJ *P) {
}
-static void *horner_freeup (PJ *P) { /* Destructor */
+static void *horner_freeup (PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
horner_free ((HORNER *) P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- horner_freeup (P);
- return;
+ P->opaque = 0;
+ return pj_default_destructor (P, errlev);
}
@@ -406,8 +404,10 @@ static int parse_coefs (PJ *P, double *coefs, char *param, int ncoefs) {
}
sprintf (buf, "t%s", param);
- if (0==pj_param (P->ctx, P->params, buf).i)
+ if (0==pj_param (P->ctx, P->params, buf).i) {
+ pj_dealloc (buf);
return 0;
+ }
sprintf (buf, "s%s", param);
init = pj_param(P->ctx, P->params, buf).s;
pj_dealloc (buf);
@@ -438,13 +438,14 @@ PJ *PROJECTION(horner) {
P->fwd = 0;
P->inv = 0;
P->left = P->right = PJ_IO_UNITS_METERS;
+ P->destructor = horner_freeup;
/* Polynomial degree specified? */
if (pj_param (P->ctx, P->params, "tdeg").i) /* degree specified? */
degree = pj_param(P->ctx, P->params, "ideg").i;
else {
proj_log_debug (P, "Horner: Must specify polynomial degree, (+deg=n)");
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
}
if (pj_param (P->ctx, P->params, "tfwd_c").i || pj_param (P->ctx, P->params, "tinv_c").i) /* complex polynomium? */
@@ -452,17 +453,15 @@ PJ *PROJECTION(horner) {
Q = horner_alloc (degree, complex_horner);
if (Q == 0)
- {
- return horner_freeup (P);
- }
+ return horner_freeup (P, ENOMEM);
P->opaque = (void *) Q;
if (complex_horner) {
n = 2*degree + 2;
if (0==parse_coefs (P, Q->fwd_c, "fwd_c", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, Q->inv_c, "inv_c", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
P->fwdobs = complex_horner_forward_obs;
P->invobs = complex_horner_reverse_obs;
@@ -470,19 +469,19 @@ PJ *PROJECTION(horner) {
else {
n = horner_number_of_coefficients (degree);
if (0==parse_coefs (P, Q->fwd_u, "fwd_u", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, Q->fwd_v, "fwd_v", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, Q->inv_u, "inv_u", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, Q->inv_v, "inv_v", n))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
}
if (0==parse_coefs (P, (double *)(Q->fwd_origin), "fwd_origin", 2))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, (double *)(Q->inv_origin), "inv_origin", 2))
- return horner_freeup (P);
+ return horner_freeup (P, PJD_ERR_MISSING_ARGS);
if (0==parse_coefs (P, &Q->range, "range", 1))
Q->range = 500000;
@@ -525,7 +524,7 @@ int pj_horner_selftest (void) {
double dist;
/* Real polynonia relating the technical coordinate system TC32 to "System 45 Bornholm" */
- P = proj_create (0, tc32_utm32);
+ P = proj_create (PJ_DEFAULT_CTX, tc32_utm32);
if (0==P)
return 10;
@@ -534,12 +533,12 @@ int pj_horner_selftest (void) {
a.coo.uv.u = 878354.8539;
/* Check roundtrip precision for 1 iteration each way, starting in forward direction */
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 0.01)
return 1;
/* The complex polynomial transformation between the "System Storebaelt" and utm32/ed50 */
- P = proj_create (0, sb_utm32);
+ P = proj_create (PJ_DEFAULT_CTX, sb_utm32);
if (0==P)
return 11;
@@ -563,7 +562,7 @@ int pj_horner_selftest (void) {
return 3;
/* Check roundtrip precision for 1 iteration each way */
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 0.01)
return 4;
diff --git a/src/PJ_igh.c b/src/PJ_igh.c
index 9b5f7075..33cdde22 100644
--- a/src/PJ_igh.c
+++ b/src/PJ_igh.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include "projects.h"
PROJ_HEAD(igh, "Interrupted Goode Homolosine") "\n\tPCyl, Sph.";
@@ -130,26 +131,20 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
int i;
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
for (i = 0; i < 12; ++i) {
if (P->opaque->pj[i])
- P->opaque->pj[i]->pfree(P->opaque->pj[i]);
+ P->opaque->pj[i]->destructor(P->opaque->pj[i], errlev);
}
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor(P, errlev);
}
@@ -175,8 +170,8 @@ static void freeup (PJ *P) {
*/
#define SETUP(n, proj, x_0, y_0, lon_0) \
- if (!(Q->pj[n-1] = pj_##proj(0))) return freeup_new(P); \
- if (!(Q->pj[n-1] = pj_##proj(Q->pj[n-1]))) return freeup_new(P); \
+ if (!(Q->pj[n-1] = pj_##proj(0))) return destructor(P, ENOMEM); \
+ if (!(Q->pj[n-1] = pj_##proj(Q->pj[n-1]))) return destructor(P, ENOMEM); \
Q->pj[n-1]->ctx = P->ctx; \
Q->pj[n-1]->x0 = x_0; \
Q->pj[n-1]->y0 = y_0; \
@@ -188,7 +183,7 @@ PJ *PROJECTION(igh) {
LP lp = { 0, d4044118 };
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -220,6 +215,7 @@ PJ *PROJECTION(igh) {
P->inv = s_inverse;
P->fwd = s_forward;
+ P->destructor = destructor;
P->es = 0.;
return P;
diff --git a/src/PJ_imw_p.c b/src/PJ_imw_p.c
index 0b2a6602..29ed3457 100644
--- a/src/PJ_imw_p.c
+++ b/src/PJ_imw_p.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -130,36 +131,31 @@ static void xy(PJ *P, double phi, double *x, double *y, double *sp, double *R) {
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
if( P->opaque->en )
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor(P, errlev);
}
PJ *PROJECTION(imw_p) {
double del, sig, s, t, x1, x2, T2, y1, m1, m2, y2;
- int i;
+ int err;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
- if (!(Q->en = pj_enfn(P->es))) return freeup_new(P);
- if( (i = phi12(P, &del, &sig)) != 0) {
- proj_errno_set(P, i);
- return freeup_new(P);
+ if (!(Q->en = pj_enfn(P->es))) return pj_default_destructor (P, ENOMEM);
+ if( (err = phi12(P, &del, &sig)) != 0) {
+ return destructor(P, err);
}
if (Q->phi_2 < Q->phi_1) { /* make sure P->phi_1 most southerly */
del = Q->phi_1;
@@ -204,6 +200,7 @@ PJ *PROJECTION(imw_p) {
P->fwd = e_forward;
P->inv = e_inverse;
+ P->destructor = destructor;
return P;
}
diff --git a/src/PJ_isea.c b/src/PJ_isea.c
index deaecb0f..223d8f28 100644
--- a/src/PJ_isea.c
+++ b/src/PJ_isea.c
@@ -1034,6 +1034,7 @@ isea_forward(struct isea_dgg *g, struct isea_geo *in)
*/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -1062,27 +1063,11 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(isea) {
char *opt;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -1100,8 +1085,7 @@ PJ *PROJECTION(isea) {
} else if (!strcmp(opt, "pole")) {
isea_orient_pole(&Q->dgg);
} else {
- proj_errno_set(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
}
}
@@ -1140,8 +1124,7 @@ PJ *PROJECTION(isea) {
}
else {
/* TODO verify error code. Possibly eliminate magic */
- proj_errno_set(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
}
}
diff --git a/src/PJ_krovak.c b/src/PJ_krovak.c
index bee66b07..640ce07f 100644
--- a/src/PJ_krovak.c
+++ b/src/PJ_krovak.c
@@ -77,7 +77,8 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(krovak, "Krovak") "\n\tPCyl., Ellps.";
@@ -173,27 +174,11 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc(P);
-
- pj_dealloc(P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(krovak) {
double u0, n0, g;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
/* we want Bessel as fixed ellipsoid */
diff --git a/src/PJ_labrd.c b/src/PJ_labrd.c
index dfc54478..4b5d93a5 100644
--- a/src/PJ_labrd.c
+++ b/src/PJ_labrd.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(labrd, "Laborde") "\n\tCyl, Sph\n\tSpecial for Madagascar";
#define EPS 1.e-10
@@ -95,28 +96,11 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(labrd) {
double Az, sinp, R, N, t;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->rot = pj_param(P->ctx, P->params, "bno_rot").i == 0;
diff --git a/src/PJ_laea.c b/src/PJ_laea.c
index 0a638fb0..ddca63d9 100644
--- a/src/PJ_laea.c
+++ b/src/PJ_laea.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -219,20 +220,16 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->apa);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor(P, errlev);
}
@@ -240,8 +237,9 @@ PJ *PROJECTION(laea) {
double t;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
+ P->destructor = destructor;
t = fabs(P->phi0);
if (fabs(t - M_HALFPI) < EPS10)
diff --git a/src/PJ_lagrng.c b/src/PJ_lagrng.c
index 98500900..e30f6a36 100644
--- a/src/PJ_lagrng.c
+++ b/src/PJ_lagrng.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -35,42 +36,22 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(lagrng) {
double phi1;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->rw = pj_param(P->ctx, P->params, "dW").f;
- if (Q->rw <= 0) {
- proj_errno_set(P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
- return freeup_new(P);
- }
+ if (Q->rw <= 0)
+ return pj_default_destructor(P, PJD_ERR_W_OR_M_ZERO_OR_LESS);
Q->rw = 1. / Q->rw;
Q->hrw = 0.5 * Q->rw;
phi1 = sin(pj_param(P->ctx, P->params, "rlat_1").f);
- if (fabs(fabs(phi1) - 1.) < TOL) {
- proj_errno_set(P, PJD_ERR_LAT_LARGER_THAN_90);
- return freeup_new(P);
- }
+ if (fabs(fabs(phi1) - 1.) < TOL)
+ return pj_default_destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
Q->a1 = pow((1. - phi1)/(1. + phi1), Q->hrw);
diff --git a/src/PJ_larr.c b/src/PJ_larr.c
index dba2534c..cd6e6c8a 100644
--- a/src/PJ_larr.c
+++ b/src/PJ_larr.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(larr, "Larrivee") "\n\tMisc Sph, no inv.";
@@ -16,20 +16,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(larr) {
P->es = 0;
diff --git a/src/PJ_lask.c b/src/PJ_lask.c
index 9aa96206..d0efeb7d 100644
--- a/src/PJ_lask.c
+++ b/src/PJ_lask.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(lask, "Laskowski") "\n\tMisc Sph, no inv.";
@@ -28,19 +28,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
return xy;
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(lask) {
diff --git a/src/pj_latlong.c b/src/PJ_latlong.c
index 761eadc5..dec69b70 100644
--- a/src/pj_latlong.c
+++ b/src/PJ_latlong.c
@@ -53,19 +53,6 @@ static LP inverse(XY xy, PJ *P) {
}
-static void *freeup_new (PJ *P) {
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(latlong) {
P->is_latlong = 1;
P->x0 = 0.0;
diff --git a/src/PJ_lcc.c b/src/PJ_lcc.c
index 905f7086..78c227b8 100644
--- a/src/PJ_lcc.c
+++ b/src/PJ_lcc.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -88,29 +89,13 @@ static void special(LP lp, PJ *P, struct FACTORS *fac) {
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(lcc) {
double cosphi, sinphi;
int secant;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
@@ -122,10 +107,9 @@ PJ *PROJECTION(lcc) {
if (!pj_param(P->ctx, P->params, "tlat_0").i)
P->phi0 = Q->phi1;
}
- if (fabs(Q->phi1 + Q->phi2) < EPS10) {
- proj_errno_set(P, PJD_ERR_CONIC_LAT_EQUAL);
- return freeup_new(P);
- }
+ if (fabs(Q->phi1 + Q->phi2) < EPS10)
+ return pj_default_destructor(P, PJD_ERR_CONIC_LAT_EQUAL);
+
Q->n = sinphi = sin(Q->phi1);
cosphi = cos(Q->phi1);
secant = fabs(Q->phi1 - Q->phi2) >= EPS10;
diff --git a/src/PJ_lcca.c b/src/PJ_lcca.c
index 77704375..7d1355b9 100644
--- a/src/PJ_lcca.c
+++ b/src/PJ_lcca.c
@@ -1,6 +1,7 @@
/* PROJ.4 Cartographic Projection System
*/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -69,20 +70,15 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor (P, errlev);
}
@@ -90,16 +86,15 @@ PJ *PROJECTION(lcca) {
double s2p0, N0, R0, tan0;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
(Q->en = pj_enfn(P->es));
if (!Q->en)
- return freeup_new(P);
+ return pj_default_destructor (P, ENOMEM);
if (P->phi0 == 0.) {
- proj_errno_set(P, PJD_ERR_LAT_0_IS_ZERO);
- return freeup_new(P);
+ return destructor(P, PJD_ERR_LAT_0_IS_ZERO);
}
Q->l = sin(P->phi0);
Q->M0 = pj_mlfn(P->phi0, Q->l, cos(P->phi0), Q->en);
@@ -113,6 +108,7 @@ PJ *PROJECTION(lcca) {
P->inv = e_inverse;
P->fwd = e_forward;
+ P->destructor = destructor;
return P;
}
diff --git a/src/PJ_loxim.c b/src/PJ_loxim.c
index 6cd56eef..a4ae074b 100644
--- a/src/PJ_loxim.c
+++ b/src/PJ_loxim.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -49,34 +50,17 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(loxim) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->phi1 = pj_param(P->ctx, P->params, "rlat_1").f;
Q->cosphi1 = cos(Q->phi1);
- if (Q->cosphi1 < EPS) {
- proj_errno_set(P, PJD_ERR_LAT_LARGER_THAN_90);
- return freeup_new(P);
- }
+ if (Q->cosphi1 < EPS)
+ return pj_default_destructor(P, PJD_ERR_LAT_LARGER_THAN_90);
+
Q->tanphi1 = tan(M_FORTPI + 0.5 * Q->phi1);
diff --git a/src/PJ_lsat.c b/src/PJ_lsat.c
index 15009d61..1b3778d6 100644
--- a/src/PJ_lsat.c
+++ b/src/PJ_lsat.c
@@ -1,5 +1,6 @@
/* based upon Snyder and Linck, USGS-NMD */
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -148,40 +149,22 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(lsat) {
int land, path;
double lam, alf, esc, ess;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
land = pj_param(P->ctx, P->params, "ilsat").i;
- if (land <= 0 || land > 5) {
- proj_errno_set(P, PJD_ERR_LSAT_NOT_IN_RANGE);
- return freeup_new(P);
- }
+ if (land <= 0 || land > 5)
+ return pj_default_destructor(P, PJD_ERR_LSAT_NOT_IN_RANGE);
+
path = pj_param(P->ctx, P->params, "ipath").i;
- if (path <= 0 || path > (land <= 3 ? 251 : 233)) {
- proj_errno_set(P, PJD_ERR_PATH_NOT_IN_RANGE);
- return freeup_new(P);
- }
+ if (path <= 0 || path > (land <= 3 ? 251 : 233))
+ pj_default_destructor(P, PJD_ERR_PATH_NOT_IN_RANGE);
+
if (land <= 3) {
P->lam0 = DEG_TO_RAD * 128.87 - M_TWOPI / 251. * path;
Q->p22 = 103.2669323;
diff --git a/src/PJ_mbt_fps.c b/src/PJ_mbt_fps.c
index 5a3f3774..c35da04c 100644
--- a/src/PJ_mbt_fps.c
+++ b/src/PJ_mbt_fps.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(mbt_fps, "McBryde-Thomas Flat-Pole Sine (No. 2)") "\n\tCyl., Sph.";
@@ -44,20 +44,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(mbt_fps) {
P->es = 0;
diff --git a/src/PJ_mbtfpp.c b/src/PJ_mbtfpp.c
index f8a5e807..2bbb16b1 100644
--- a/src/PJ_mbtfpp.c
+++ b/src/PJ_mbtfpp.c
@@ -52,19 +52,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(mbtfpp) {
P->es = 0.;
diff --git a/src/PJ_mbtfpq.c b/src/PJ_mbtfpq.c
index b6910a45..4901401e 100644
--- a/src/PJ_mbtfpq.c
+++ b/src/PJ_mbtfpq.c
@@ -61,19 +61,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(mbtfpq) {
P->es = 0.;
diff --git a/src/PJ_merc.c b/src/PJ_merc.c
index 04e5dc21..d17a2d50 100644
--- a/src/PJ_merc.c
+++ b/src/PJ_merc.c
@@ -49,22 +49,14 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void freeup(PJ *P) { /* Destructor */
- pj_dealloc(P);
-}
-
-
PJ *PROJECTION(merc) {
double phits=0.0;
int is_phits;
if( (is_phits = pj_param(P->ctx, P->params, "tlat_ts").i) ) {
phits = fabs(pj_param(P->ctx, P->params, "rlat_ts").f);
- if (phits >= M_HALFPI) {
- proj_errno_set(P, PJD_ERR_LAT_TS_LARGER_THAN_90);
- freeup(P);
- return 0;
- }
+ if (phits >= M_HALFPI)
+ return pj_default_destructor(P, PJD_ERR_LAT_TS_LARGER_THAN_90);
}
if (P->es != 0.0) { /* ellipsoid */
diff --git a/src/PJ_mill.c b/src/PJ_mill.c
index 17763410..829bc3be 100644
--- a/src/PJ_mill.c
+++ b/src/PJ_mill.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(mill, "Miller Cylindrical") "\n\tCyl, Sph";
@@ -25,19 +25,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(mill) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_minimal.c b/src/PJ_minimal.c
deleted file mode 100644
index 1108c4fa..00000000
--- a/src/PJ_minimal.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/***********************************************************************
-
- A minimal example of a new proj.4 projection implementation
-
- ...and a verbose justification for some highly intrusive code
- surgery
-
-************************************************************************
-
-**The brief version:**
-
-In an attempt to make proj.4 code slightly more secure and much easier
-to read and maintain, I'm trying to eliminate a few unfortunate design
-decisions from the early days of proj.4
-
-The work will be *very* intrusive, especially in the PJ_xxx segment of
-the code tree, but great care has been taken to design a process that
-can be implemented stepwise and localized, one projection at a time,
-then finalized with a relatively small and concentrated work package.
-
-**The (very) long version:**
-
-Gerald I. Evenden's original design for the proj.4 projection system
-is a beautiful example of software architecture, where a very limited
-set of policy rules leads to a well defined hierarchical structure and
-a high degree of both encapsulation and internal interoperability.
-
-In the proj.4 code, the policy rules are *enforced* by a system of
-preprocessor macros for building the scaffolding for implementation
-of a new projection.
-
-While this system of macros undeniably possesses the property of both
-reducing repetitive code and enforcing policy, unfortunately it also
-possesses two much less desirable properties:
-
-First, while enforcing policy, it also *hides* policy: The "beauty in
-simplicity" of Gerald's design is hidden behind layers of macros,
-whose architectural clarity do not match that of proj.4 in general.
-
-Second (and related), the macros make the source code look like
-something only vaguely related to C, making it hard to read (an effect
-that gets amplified to the tune of syntax highlighters getting confused
-by the macros).
-
-While the policy rule enforcement macros can be eliminated in relatively
-non-intrusive ways, a more fundamental flaw in the proj.4 use of macros
-is found in the PJ_xxx.c files implementing the individual projections:
-The use of internal redefinition of PJ, the fundamental proj data object,
-through the use of the PROJ_PARMS__ macro, makes the sizeof (PJ)
-fundamentally unknown to the calling pj_init function.
-
-This leads to code that is probably not in full conformance with the
-C standard.
-
-It is also a memory management catastrophe waiting to happen.
-
-But first and foremost, it leads to some very clumsy initialization code,
-where pj_init (the constructor function), needs to start the constsruction
-process by asking the PJ_xxx function to do the memory allocation (because
-pj_init does not know the size of the PROJ_PARMS-mangled PJ object being
-instantiated).
-
-Then, after doing some initialization work, pj_init returns control to
-PJ_xxx, asking it to finalize the initialization with the projection
-specific parameters specified by the PROJ_PARMS__ macro.
-
-Behind the scenes, hidden by two layers of macros, what happens is even
-worse, as a lot of the initialization code is duplicated in every PJ_xxx
-file, rather than being centralized in the pj_init function.
-
-**Solution procedure:**
-
-Evidently, the way to eliminate this clumsyness will be to introduce an
-opaque object, that is managed by tne individual PJ_xxx projection code,
-and represented as a simple void-pointer in the PJ object.
-
-This can be done one projection code file at a time, working through the
-code base as time permits (it will take at least a month).
-
-When a PJ_xxx file is on the surgical bench, it will also have its
-ENTRYA/ENTRY0/ENTRY1/ENTRY2/ENDENTRY/etc. etc. macro-guts torn out and
-replaced by the PROJECTION macro (introduced in projects.h).
-
-This leads to code that looks a lot more like real C, and hence is much
-less confusing to both syntax higlighters and humans. It also leads
-to code that, after all projections have been processed, with a final
-sweep over the code base can be brought into the style of the code in
-PJ_minimal.c
-
-In my humble opinion the result wil be a code base that is not only easier
-to maintain, but also more welcoming to new contributors.
-
-And if proj is to expand its strong basis in projections into the fields
-of geodetic transformations and general geometric geodesy, we will need
-to be able to attract quite a few expert geodesist contributors.
-
-And since expert geodesists are not necessarily expert coders, a welcoming
-code base is a real asset (to put the icing on the cake of the already
-welcoming user- and developer community).
-
-Note that the entire process does not touch the algorithmic/mathematical
-parts of the code at all - it is actuallly an attempt to make this part
-stand out more clearly.
-
----
-
-The attached material is an attempt to show what happens if we remove
-the layers of macros, and introduce a more centralized approach to
-memory allocation and initialization.
-
-Please note, however, that the level of cantralization achieved here
-is not yet fully supported by the proj.4 infrastructure: It is an
-example, intended to show what can be achieved through a smooth,
-gradual and safe refactoring of the existing layered macro system.
-
-In my humble opinion, this version makes the beauty of Gerald's design
-much more evident than the current layered-macro-version.
-
-Thomas Knudsen, thokn@sdfe.dk, 2016-03-31
-
-***********************************************************************/
-
-#define PJ_LIB__
-#include <projects.h>
-#include <assert.h>
-PROJ_HEAD(minimal, "Minimal example (brief description goes here)");
-
-
-/* Projection specific elements for the PJ object */
-struct pj_opaque {
- double a;
- int b;
-};
-
-
-static XY e_forward (LP lp, PJ *P) { /* Ellipsoidal, forward */
- XY xy = {0.0,0.0};
- /* Actual ellipsoidal forward code goes here */
- xy.y = lp.lam + P->es;
- xy.x = lp.phi + 42;
- return xy;
-}
-
-
-static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
- XY xy = {0.0,0.0};
- /* Actual spheroidal forward code goes here */
- xy.y = lp.lam + P->es;
- xy.x = lp.phi + 42;
- return xy;
-}
-
-
-static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
- LP lp = {0.0,0.0};
- /* Actual ellipsoidal forward code goes here */
- lp.lam = xy.x - P->es;
- lp.phi = xy.y - P->opaque->b;
- return lp;
-}
-
-
-static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
- LP lp = {0.0,0.0};
- /* Actual spheroidal forward code goes here */
- lp.lam = xy.x - P->es;
- lp.phi = xy.y - P->opaque->b;
- return lp;
-}
-
-
-static void freeup(PJ *P) { /* Destructor */
- if (P==0)
- return;
- /* Projection specific deallocation goes here */
- pj_dealloc (P->opaque);
- pj_dealloc (P);
- return;
-}
-
-
-PJ *pj_projection_specific_setup_minimal (PJ *P) {
- pj_prepare (P, des_minimal, freeup, sizeof (struct pj_opaque));
- if (0==P->opaque) {
- freeup (P);
- return 0;
- }
-
- P->opaque->a = 42.42;
- P->opaque->b = 42;
-
- /* Spheroidal? */
- if (0==P->es) {
- P->fwd = s_forward;
- P->inv = s_inverse;
- return P;
- }
-
- /* Otherwise it's ellipsoidal */
- P->fwd = e_forward;
- P->inv = e_inverse;
-
- return P;
-}
diff --git a/src/PJ_misrsom.c b/src/PJ_misrsom.c
index 49be1669..5c5a226f 100644
--- a/src/PJ_misrsom.c
+++ b/src/PJ_misrsom.c
@@ -21,6 +21,7 @@
*****************************************************************************/
/* based upon Snyder and Linck, USGS-NMD */
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -164,36 +165,19 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(misrsom) {
int path;
double lam, alf, esc, ess;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
path = pj_param(P->ctx, P->params, "ipath").i;
- if (path <= 0 || path > 233) {
- proj_errno_set(P, PJD_ERR_PATH_NOT_IN_RANGE);
- return freeup_new(P);
- }
+ if (path <= 0 || path > 233)
+ return pj_default_destructor(P, PJD_ERR_PATH_NOT_IN_RANGE);
+
P->lam0 = DEG_TO_RAD * 129.3056 - M_TWOPI / 233. * path;
alf = 98.30382 * DEG_TO_RAD;
Q->p22 = 98.88 / 1440.0;
diff --git a/src/PJ_mod_ster.c b/src/PJ_mod_ster.c
index f8c90bc4..767863c1 100644
--- a/src/PJ_mod_ster.c
+++ b/src/PJ_mod_ster.c
@@ -1,6 +1,7 @@
/* based upon Snyder and Linck, USGS-NMD */
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(mil_os, "Miller Oblated Stereographic") "\n\tAzi(mod)";
PROJ_HEAD(lee_os, "Lee Oblated Stereographic") "\n\tAzi(mod)";
@@ -98,21 +99,6 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
static PJ *setup(PJ *P) { /* general initialization */
struct pj_opaque *Q = P->opaque;
double esphi, chio;
@@ -142,7 +128,7 @@ PJ *PROJECTION(mil_os) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = 2;
@@ -165,7 +151,7 @@ PJ *PROJECTION(lee_os) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = 2;
@@ -190,7 +176,7 @@ PJ *PROJECTION(gs48) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = 4;
@@ -225,7 +211,7 @@ PJ *PROJECTION(alsk) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = 5;
@@ -273,7 +259,7 @@ PJ *PROJECTION(gs50) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->n = 9;
diff --git a/src/PJ_moll.c b/src/PJ_moll.c
index b975cc73..8470bb3e 100644
--- a/src/PJ_moll.c
+++ b/src/PJ_moll.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(moll, "Mollweide") "\n\tPCyl., Sph.";
PROJ_HEAD(wag4, "Wagner IV") "\n\tPCyl., Sph.";
@@ -51,23 +52,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ * setup(PJ *P, double p) {
struct pj_opaque *Q = P->opaque;
double r, sp, p2 = p + p;
@@ -89,7 +73,7 @@ static PJ * setup(PJ *P, double p) {
PJ *PROJECTION(moll) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
return setup(P, M_HALFPI);
@@ -99,7 +83,7 @@ PJ *PROJECTION(moll) {
PJ *PROJECTION(wag4) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
return setup(P, M_PI/3.);
@@ -108,7 +92,7 @@ PJ *PROJECTION(wag4) {
PJ *PROJECTION(wag5) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
P->es = 0;
diff --git a/src/PJ_molodensky.c b/src/PJ_molodensky.c
index 49e27763..f09f07cd 100644
--- a/src/PJ_molodensky.c
+++ b/src/PJ_molodensky.c
@@ -63,27 +63,6 @@ struct pj_opaque_molodensky {
};
-static void *freeup_msg(PJ *P, int errlev) {
- if (0==P)
- return 0;
-
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
-
- return pj_dealloc(P);
-}
-
-static void freeup(PJ *P) {
- freeup_msg (P, 0);
- return;
-}
-
-
static double RN (double a, double es, double phi) {
/**********************************************************
N(phi) - prime vertical radius of curvature
@@ -287,7 +266,7 @@ static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) {
PJ *PROJECTION(molodensky) {
struct pj_opaque_molodensky *Q = pj_calloc(1, sizeof(struct pj_opaque_molodensky));
if (0==Q)
- return freeup_msg(P, ENOMEM);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = (void *) Q;
P->fwdobs = forward_obs;
@@ -320,10 +299,10 @@ PJ *PROJECTION(molodensky) {
/* We want all parameters (except +abridged) to be set */
if ((Q->dx == 0) && (Q->dy == 0) && (Q->dz == 0) && (Q->da == 0) && (Q->df == 0))
- return freeup_msg(P, PJD_ERR_NO_ARGS);
+ return pj_default_destructor(P, PJD_ERR_NO_ARGS);
if ((Q->dx == 0) || (Q->dy == 0) || (Q->dz == 0) || (Q->da == 0) || (Q->df == 0))
- return freeup_msg(P, PJD_ERR_MISSING_ARGS);
+ return pj_default_destructor(P, PJD_ERR_MISSING_ARGS);
return P;
}
@@ -338,7 +317,7 @@ int pj_molodensky_selftest (void) {
PJ *P;
/* Test the abridged Molodensky first. Example from appendix 3 of Deakin (2004). */
- P = proj_create(0,
+ P = proj_create(PJ_DEFAULT_CTX,
"+proj=molodensky +a=6378160 +rf=298.25 "
"+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 "
"+abridged "
@@ -362,7 +341,7 @@ int pj_molodensky_selftest (void) {
}
/* let's try a roundtrip */
- if (proj_roundtrip(P, PJ_FWD, 100, in) > 1) {
+ if (proj_roundtrip(P, PJ_FWD, 100, in.coo) > 1) {
proj_destroy(P);
return 12;
}
@@ -376,7 +355,7 @@ int pj_molodensky_selftest (void) {
/* Test the abridged Molodensky first. Example from appendix 3 of Deaking (2004). */
- P = proj_create(0,
+ P = proj_create(PJ_DEFAULT_CTX,
"+proj=molodensky +a=6378160 +rf=298.25 "
"+da=-23 +df=-8.120449e-8 +dx=-134 +dy=-48 +dz=149 "
);
@@ -391,7 +370,7 @@ int pj_molodensky_selftest (void) {
}
/* let's try a roundtrip */
- if (proj_roundtrip(P, PJ_FWD, 100, in) > 1) {
+ if (proj_roundtrip(P, PJ_FWD, 100, in.coo) > 1) {
proj_destroy(P);
return 22;
}
diff --git a/src/PJ_natearth.c b/src/PJ_natearth.c
index 8d0dae08..9c40f3da 100644
--- a/src/PJ_natearth.c
+++ b/src/PJ_natearth.c
@@ -13,7 +13,7 @@ and designed in collaboration with Tom Patterson.
Port to PROJ.4 by Bernhard Jenny, 6 June 2011
*/
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(natearth, "Natural Earth") "\n\tPCyl., Sph.";
@@ -88,20 +88,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(natearth) {
P->es = 0;
P->inv = s_inverse;
diff --git a/src/PJ_natearth2.c b/src/PJ_natearth2.c
index aab9f9ac..95bb8646 100644
--- a/src/PJ_natearth2.c
+++ b/src/PJ_natearth2.c
@@ -6,7 +6,7 @@ and Atmospheric Sciences, Oregon State University.
Port to PROJ.4 by Bojan Savric, 4 April 2016
*/
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(natearth2, "Natural Earth 2") "\n\tPCyl., Sph.";
@@ -85,20 +85,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(natearth2) {
P->es = 0;
P->inv = s_inverse;
diff --git a/src/PJ_nell.c b/src/PJ_nell.c
index 1b6af010..ac071fc9 100644
--- a/src/PJ_nell.c
+++ b/src/PJ_nell.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(nell, "Nell") "\n\tPCyl., Sph.";
@@ -38,20 +38,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(nell) {
P->es = 0;
diff --git a/src/PJ_nell_h.c b/src/PJ_nell_h.c
index dfad72b2..fe9a75c6 100644
--- a/src/PJ_nell_h.c
+++ b/src/PJ_nell_h.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(nell_h, "Nell-Hammer") "\n\tPCyl., Sph.";
@@ -41,20 +41,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(nell_h) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_nocol.c b/src/PJ_nocol.c
index 88836a10..934ba7ab 100644
--- a/src/PJ_nocol.c
+++ b/src/PJ_nocol.c
@@ -1,5 +1,5 @@
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(nicol, "Nicolosi Globular") "\n\tMisc Sph, no inv.";
@@ -43,20 +43,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(nicol) {
P->es = 0.;
P->fwd = s_forward;
diff --git a/src/PJ_nsper.c b/src/PJ_nsper.c
index 589b6203..4975bb17 100644
--- a/src/PJ_nsper.c
+++ b/src/PJ_nsper.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -134,29 +135,12 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ *setup(PJ *P) {
struct pj_opaque *Q = P->opaque;
- if ((Q->height = pj_param(P->ctx, P->params, "dh").f) <= 0.) {
- proj_errno_set(P, PJD_ERR_H_LESS_THAN_ZERO);
- return freeup_new(P);
- }
+ if ((Q->height = pj_param(P->ctx, P->params, "dh").f) <= 0.)
+ return pj_default_destructor(P, PJD_ERR_H_LESS_THAN_ZERO);
+
if (fabs(fabs(P->phi0) - M_HALFPI) < EPS10)
Q->mode = P->phi0 < 0. ? S_POLE : N_POLE;
else if (fabs(P->phi0) < EPS10)
@@ -174,6 +158,7 @@ static PJ *setup(PJ *P) {
P->inv = s_inverse;
P->fwd = s_forward;
P->es = 0.;
+
return P;
}
@@ -181,7 +166,7 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(nsper) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->tilt = 0;
@@ -195,7 +180,7 @@ PJ *PROJECTION(tpers) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
omega = pj_param(P->ctx, P->params, "dtilt").f * DEG_TO_RAD;
diff --git a/src/PJ_nzmg.c b/src/PJ_nzmg.c
index 6c705502..b489e32f 100644
--- a/src/PJ_nzmg.c
+++ b/src/PJ_nzmg.c
@@ -26,7 +26,7 @@
* DEALINGS IN THE SOFTWARE.
*****************************************************************************/
#define PJ_LIB__
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(nzmg, "New Zealand Map Grid") "\n\tfixed Earth";
@@ -103,19 +103,6 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(nzmg) {
/* force to International major axis */
P->ra = 1. / (P->a = 6378388.0);
diff --git a/src/PJ_ob_tran.c b/src/PJ_ob_tran.c
index 238dba67..d35bb1b3 100644
--- a/src/PJ_ob_tran.c
+++ b/src/PJ_ob_tran.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
#include <string.h>
@@ -80,89 +81,127 @@ static LP t_inverse(XY xy, PJ *P) { /* spheroid */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor(PJ *P, int errlev) {
if (0==P)
return 0;
if (0==P->opaque)
- return pj_dealloc (P);
-
+ return pj_default_destructor (P, errlev);
+
if (P->opaque->link)
- P->opaque->link->pfree(P->opaque->link);
+ P->opaque->link->destructor (P->opaque->link, errlev);
+
+ return pj_default_destructor(P, errlev);
+}
+
+
+
+
+/***********************************************************************
+
+These functions are modified versions of the functions "argc_params"
+and "argv_params" from PJ_pipeline.c
+
+Basically, they do the somewhat backwards stunt of turning the paralist
+representation of the +args back into the original +argv, +argc
+representation accepted by pj_init_ctx().
+
+This, however, also begs the question of whether we really need the
+paralist linked list representation, or if we could do with a simpler
+null-terminated argv style array? This would simplfy some code, and
+keep memory allocations more localized.
+
+***********************************************************************/
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
+typedef struct {int argc; char **argv;} ARGS;
+
+/* count the number of args in the linked list <params> */
+static size_t paralist_params_argc (paralist *params) {
+ size_t argc = 0;
+ for (; params != 0; params = params->next)
+ argc++;
+ return argc;
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+/* turn paralist into argc/argv style argument list */
+static ARGS ob_tran_target_params (paralist *params) {
+ int i = 0;
+ ARGS args = {0, 0};
+ size_t argc = paralist_params_argc (params);
+ if (argc < 2)
+ return args;
+
+ /* all args except the proj_ob_tran */
+ args.argv = pj_calloc (argc - 1, sizeof (char *));
+ if (0==args.argv)
+ return args;
+
+ /* Copy all args *except* the proj=ob_tran arg to the argv array */
+ for (i = 0; params != 0; params = params->next) {
+ if (0==strcmp (params->param, "proj=ob_tran"))
+ continue;
+ args.argv[i++] = params->param;
+ }
+ args.argc = i;
+
+ /* Then convert the o_proj=xxx element to proj=xxx */
+ for (i = 0; i < args.argc; i++) {
+ if (0!=strncmp (args.argv[i], "o_proj=", 7))
+ continue;
+ args.argv[i] += 2;
+ break;
+ }
+
+ return args;
}
+
PJ *PROJECTION(ob_tran) {
- int i;
double phip;
- char *name, *s;
+ char *name;
+ ARGS args;
+ PJ *R; /* projection to rotate */
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return destructor(P, ENOMEM);
+
P->opaque = Q;
+ P->destructor = destructor;
+
+#if 0
+ if (0 != P->es)
+ return destructor(P, PJD_ERR_ELLIPSOIDAL_UNSUPPORTED);
+#endif
/* get name of projection to be translated */
- if (!(name = pj_param(P->ctx, P->params, "so_proj").s)) {
- proj_errno_set(P, PJD_ERR_NO_ROTATION_PROJ);
- return freeup_new(P);
- }
+ if (!(name = pj_param(P->ctx, P->params, "so_proj").s))
+ return destructor(P, PJD_ERR_NO_ROTATION_PROJ);
+
/* avoid endless recursion */
- if( strcmp(name, "ob_tran") == 0 ) {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
- }
- for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ;
- if (!s || !(Q->link = (*pj_list[i].proj)(0))) {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
- }
- /* copy existing header into new */
- P->es = 0.; /* force to spherical */
- Q->link->params = P->params;
- Q->link->ctx = P->ctx;
- Q->link->over = P->over;
- Q->link->geoc = P->geoc;
- Q->link->a = P->a;
- Q->link->es = P->es;
- Q->link->ra = P->ra;
- Q->link->lam0 = P->lam0;
- Q->link->phi0 = P->phi0;
- Q->link->x0 = P->x0;
- Q->link->y0 = P->y0;
- Q->link->k0 = P->k0;
- /* force spherical earth */
- Q->link->one_es = Q->link->rone_es = 1.;
- Q->link->es = Q->link->e = 0.;
- if (!(Q->link = pj_list[i].proj(Q->link))) {
- return freeup_new(P);
- }
- if( Q->link->fwd == 0 ) {
- return freeup_new(P);
- }
+ if( strcmp(name, "ob_tran") == 0 )
+ return destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
+
+ /* Create the target projection object to rotate */
+ args = ob_tran_target_params (P->params);
+ R = pj_init_ctx (pj_get_ctx(P), args.argc, args.argv);
+ pj_dealloc (args.argv);
+
+ if (0==R)
+ return destructor (P, PJD_ERR_UNKNOWN_PROJECTION_ID);
+ Q->link = R;
+
if (pj_param(P->ctx, P->params, "to_alpha").i) {
double lamc, phic, alpha;
lamc = pj_param(P->ctx, P->params, "ro_lon_c").f;
phic = pj_param(P->ctx, P->params, "ro_lat_c").f;
alpha = pj_param(P->ctx, P->params, "ro_alpha").f;
-/*
- if (fabs(phic) <= TOL ||
- fabs(fabs(phic) - HALFPI) <= TOL ||
- fabs(fabs(alpha) - HALFPI) <= TOL)
-*/
- if (fabs(fabs(phic) - M_HALFPI) <= TOL) {
- proj_errno_set(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
- return freeup_new(P);
- }
+
+ if (fabs(fabs(phic) - M_HALFPI) <= TOL)
+ return destructor(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
+
Q->lamp = lamc + aatan2(-cos(alpha), -sin(alpha) * sin(phic));
phip = aasin(P->ctx,cos(phic) * sin(alpha));
} else if (pj_param(P->ctx, P->params, "to_lat_p").i) { /* specified new pole */
@@ -176,16 +215,16 @@ PJ *PROJECTION(ob_tran) {
lam2 = pj_param(P->ctx, P->params, "ro_lon_2").f;
phi2 = pj_param(P->ctx, P->params, "ro_lat_2").f;
if (fabs(phi1 - phi2) <= TOL || (con = fabs(phi1)) <= TOL ||
- fabs(con - M_HALFPI) <= TOL || fabs(fabs(phi2) - M_HALFPI) <= TOL) {
- proj_errno_set(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
- return freeup_new(P);
- }
+ fabs(con - M_HALFPI) <= TOL || fabs(fabs(phi2) - M_HALFPI) <= TOL)
+ return destructor(P, PJD_ERR_LAT_1_OR_2_ZERO_OR_90);
+
Q->lamp = atan2(cos(phi1) * sin(phi2) * cos(lam1) -
sin(phi1) * cos(phi2) * cos(lam2),
sin(phi1) * cos(phi2) * sin(lam2) -
cos(phi1) * sin(phi2) * sin(lam1));
phip = atan(-cos(Q->lamp - lam1) / tan(phi1));
}
+
if (fabs(phip) > TOL) { /* oblique */
Q->cphip = cos(phip);
Q->sphip = sin(phip);
@@ -206,8 +245,11 @@ int pj_ob_tran_selftest (void) {return 0;}
int pj_ob_tran_selftest (void) {
double tolerance_lp = 1e-10;
double tolerance_xy = 1e-7;
+ double d;
+ PJ *P;
+ PJ_COORD a, b;
- char s_args[] = {"+proj=ob_tran +a=6400000 +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"};
+ char s_args[] = {"+proj=ob_tran +R=6400000 +o_proj=latlon +o_lon_p=20 +o_lat_p=20 +lon_0=180"};
LP fwd_in[] = {
{ 2, 1},
@@ -237,7 +279,31 @@ int pj_ob_tran_selftest (void) {
{-65.862385598848391, 51.830295078417215},
};
+ /* -- Tests from nad/testvarious -------------------------------------------- */
+ P = proj_create (0, "+proj=ob_tran +o_proj=moll +R=6378137.0 +o_lon_p=0 +o_lat_p=0 +lon_0=180");
+ if (0==P)
+ return 1;
+
+ a = proj_coord (300000, 400000, 0, 0);
+ b.lpz.lam = -proj_torad (42 + (45 + 22.377/60)/60);
+ b.lpz.phi = proj_torad (85 + (35 + 28.083/60)/60);
+ a = proj_trans_coord (P, -1, a);
+ d = proj_lp_dist (P, a.lp, b.lp);
+ if (d > 1e-3)
+ return 2;
+
+ a = proj_coord (proj_torad(10), proj_torad(20), 0, 0);
+ b = proj_coord (-1384841.18787, 7581707.88240, 0, 0);
+ a = proj_trans_coord (P, 1, a);
+ d = proj_xy_dist (a.xy, b.xy);
+ if (d > 1e-3)
+ return 3;
+
+ proj_destroy (P);
+ /* -------------------------------------------------------------------------- */
+
+
return pj_generic_selftest (0, s_args, tolerance_xy, tolerance_lp, 4, 4, fwd_in, 0, s_fwd_expect, inv_in, 0, s_inv_expect);
}
-#endif
+#endif \ No newline at end of file
diff --git a/src/PJ_ocea.c b/src/PJ_ocea.c
index 1fbe2768..d3fe9fe7 100644
--- a/src/PJ_ocea.c
+++ b/src/PJ_ocea.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
PROJ_HEAD(ocea, "Oblique Cylindrical Equal Area") "\n\tCyl, Sph"
@@ -44,28 +45,12 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(ocea) {
double phi_0=0.0, phi_1, phi_2, lam_1, lam_2, lonz, alpha;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->rok = 1. / P->k0;
diff --git a/src/PJ_oea.c b/src/PJ_oea.c
index 2ba7917f..800a266e 100644
--- a/src/PJ_oea.c
+++ b/src/PJ_oea.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -52,32 +53,17 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
PJ *PROJECTION(oea) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
if (((Q->n = pj_param(P->ctx, P->params, "dn").f) <= 0.) ||
((Q->m = pj_param(P->ctx, P->params, "dm").f) <= 0.)) {
- proj_errno_set(P, PJD_ERR_INVALID_M_OR_N);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_INVALID_M_OR_N);
} else {
Q->theta = pj_param(P->ctx, P->params, "rtheta").f;
Q->sp0 = sin(P->phi0);
diff --git a/src/PJ_omerc.c b/src/PJ_omerc.c
index 0d86e460..f0b4b439 100644
--- a/src/PJ_omerc.c
+++ b/src/PJ_omerc.c
@@ -22,6 +22,7 @@
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -111,22 +112,6 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(omerc) {
double con, com, cosph0, D, F, H, L, sinph0, p, J, gamma=0,
gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0;
@@ -134,7 +119,7 @@ PJ *PROJECTION(omerc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->no_rot = pj_param(P->ctx, P->params, "tno_rot").i;
@@ -164,10 +149,8 @@ PJ *PROJECTION(omerc) {
(con = fabs(phi1)) <= TOL ||
fabs(con - M_HALFPI) <= TOL ||
fabs(fabs(P->phi0) - M_HALFPI) <= TOL ||
- fabs(fabs(phi2) - M_HALFPI) <= TOL) {
- proj_errno_set(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
- return freeup_new(P);
- }
+ fabs(fabs(phi2) - M_HALFPI) <= TOL)
+ return pj_default_destructor(P, PJD_ERR_LAT_0_OR_ALPHA_EQ_90);
}
com = sqrt(P->one_es);
if (fabs(P->phi0) > EPS) {
diff --git a/src/PJ_ortho.c b/src/PJ_ortho.c
index bb150f05..3179189b 100644
--- a/src/PJ_ortho.c
+++ b/src/PJ_ortho.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -104,26 +105,11 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(ortho) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
if (fabs(fabs(P->phi0) - M_HALFPI) <= EPS10)
diff --git a/src/PJ_patterson.c b/src/PJ_patterson.c
index 952b63ea..40b90010 100644
--- a/src/PJ_patterson.c
+++ b/src/PJ_patterson.c
@@ -105,19 +105,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(patterson) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_pipeline.c b/src/PJ_pipeline.c
index 6e42c0cb..9352b4fd 100644
--- a/src/PJ_pipeline.c
+++ b/src/PJ_pipeline.c
@@ -260,29 +260,17 @@ static LP pipeline_reverse (XY xy, PJ *P) {
return point.coo.lp;
}
-static void freeup(PJ *P) { /* Destructor */
- if (P==0)
- return;
- /* Projection specific deallocation goes here */
- pj_dealloc (P->opaque);
- pj_dealloc (P);
- return;
-}
-
-static void *pipeline_freeup (PJ *P, int errlev) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
int i;
if (0==P)
return 0;
- if (errlev)
- proj_errno_set (P, errlev);
-
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
for (i = 0; i < P->opaque->steps; i++)
- pj_free (P->opaque->pipeline[i+1]);
+ pj_default_destructor (P->opaque->pipeline[i+1], errlev);
pj_dealloc (P->opaque->reverse_step);
pj_dealloc (P->opaque->omit_forward);
@@ -291,15 +279,7 @@ static void *pipeline_freeup (PJ *P, int errlev) { /* Destructor */
pj_dealloc (P->opaque->current_argv);
pj_dealloc (P->opaque->pipeline);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-/* Adapts pipeline_freeup to the format defined for the PJ object */
-static void pipeline_freeup_wrapper (PJ *P) {
- pipeline_freeup (P, 0);
- return;
+ return pj_default_destructor(P, errlev);
}
@@ -364,27 +344,27 @@ PJ *PROJECTION(pipeline) {
P->inv3d = pipeline_reverse_3d;
P->fwd = pipeline_forward;
P->inv = pipeline_reverse;
- P->pfree = pipeline_freeup_wrapper;
+ P->destructor = destructor;
P->opaque = pj_calloc (1, sizeof(struct pj_opaque));
if (0==P->opaque)
- return 0;
+ return pj_default_destructor(P, ENOMEM);
argc = (int)argc_params (P->params);
P->opaque->argv = argv = argv_params (P->params, argc);
if (0==argv)
- return pipeline_freeup (P, ENOMEM);
+ return destructor (P, ENOMEM);
P->opaque->current_argv = current_argv = pj_calloc (argc, sizeof (char *));
if (0==current_argv)
- return pipeline_freeup (P, ENOMEM);
+ return destructor (P, ENOMEM);
/* Do some syntactical sanity checking */
for (i = 0; i < argc; i++) {
if (0==strcmp ("step", argv[i])) {
if (-1==i_pipeline) {
proj_log_error (P, "Pipeline: +step before +proj=pipeline");
- return pipeline_freeup (P, -50);
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE);
}
if (0==nsteps)
i_first_step = i;
@@ -395,7 +375,7 @@ PJ *PROJECTION(pipeline) {
if (0==strcmp ("proj=pipeline", argv[i])) {
if (-1 != i_pipeline) {
proj_log_error (P, "Pipeline: Nesting invalid");
- return pipeline_freeup (P, -50); /* ERROR: nested pipelines */
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: nested pipelines */
}
i_pipeline = i;
}
@@ -404,14 +384,14 @@ PJ *PROJECTION(pipeline) {
P->opaque->steps = nsteps;
if (-1==i_pipeline)
- return pipeline_freeup (P, -50); /* ERROR: no pipeline def */
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */
if (0==nsteps)
- return pipeline_freeup (P, -50); /* ERROR: no pipeline def */
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */
/* Make room for the pipeline and execution indicators */
if (0==pj_create_pipeline (P, nsteps))
- return pipeline_freeup (P, ENOMEM);
+ return destructor (P, ENOMEM);
/* Now loop over all steps, building a new set of arguments for each init */
for (i_current_step = i_first_step, i = 0; i < nsteps; i++) {
@@ -454,7 +434,7 @@ PJ *PROJECTION(pipeline) {
proj_log_trace (P, "Pipeline: Step %d at %p", i, next_step);
if (0==next_step) {
proj_log_error (P, "Pipeline: Bad step definition: %s", current_argv[0]);
- return pipeline_freeup (P, -50); /* ERROR: bad pipeline def */
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: bad pipeline def */
}
P->opaque->pipeline[i+1] = next_step;
proj_log_trace (P, "Pipeline: step done");
@@ -470,7 +450,7 @@ PJ *PROJECTION(pipeline) {
break;
if (i==nsteps) {
proj_log_error (P, "Pipeline: No forward steps");
- return pipeline_freeup (P, -50);
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE);
}
if (P->opaque->reverse_step[i + 1])
@@ -493,7 +473,7 @@ PJ *PROJECTION(pipeline) {
break;
if (i==-1) {
proj_log_error (P, "Pipeline: No reverse steps");
- return pipeline_freeup (P, -50);
+ return destructor (P, PJD_ERR_MALFORMED_PIPELINE);
}
if (P->opaque->reverse_step[i + 1])
@@ -526,7 +506,7 @@ int pj_pipeline_selftest (void) {
double dist;
/* forward-reverse geo->utm->geo */
- P = proj_create (0, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +step +proj=utm +ellps=GRS80 +inv");
+ P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +step +proj=utm +ellps=GRS80 +inv");
if (0==P)
return 1000;
/* zero initialize everything, then set (longitude, latitude, height) to (12, 55, 0) */
@@ -548,7 +528,7 @@ int pj_pipeline_selftest (void) {
proj_destroy (P);
/* And now the back-to-back situation utm->geo->utm */
- P = proj_create (0, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +inv +step +proj=utm +ellps=GRS80");
+ P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 +inv +step +proj=utm +ellps=GRS80");
if (0==P)
return 2000;
@@ -572,7 +552,7 @@ int pj_pipeline_selftest (void) {
/* Finally testing a corner case: A rather pointless one-step pipeline geo->utm */
- P = proj_create (0, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 ");
+ P = proj_create (PJ_DEFAULT_CTX, "+proj=pipeline +zone=32 +step +proj=utm +ellps=GRS80 ");
if (0==P)
return 3000;
diff --git a/src/PJ_poly.c b/src/PJ_poly.c
index f5af36ac..209669c0 100644
--- a/src/PJ_poly.c
+++ b/src/PJ_poly.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -126,32 +127,31 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor(PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
+
if (P->opaque->en)
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor(P, errlev);
}
PJ *PROJECTION(poly) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
+
P->opaque = Q;
+ P->destructor = destructor;
if (P->es != 0.0) {
- if (!(Q->en = pj_enfn(P->es))) return freeup_new(P);
+ if (!(Q->en = pj_enfn(P->es)))
+ return pj_default_destructor (P, ENOMEM);
Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en);
P->inv = e_inverse;
P->fwd = e_forward;
diff --git a/src/PJ_putp2.c b/src/PJ_putp2.c
index 052d95bb..83aa5f45 100644
--- a/src/PJ_putp2.c
+++ b/src/PJ_putp2.c
@@ -49,19 +49,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(putp2) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_putp3.c b/src/PJ_putp3.c
index 93720915..cb216370 100644
--- a/src/PJ_putp3.c
+++ b/src/PJ_putp3.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
struct pj_opaque {
@@ -32,27 +33,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(putp3) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->A = 4. * RPISQ;
@@ -67,7 +51,7 @@ PJ *PROJECTION(putp3) {
PJ *PROJECTION(putp3p) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->A = 2. * RPISQ;
diff --git a/src/PJ_putp4p.c b/src/PJ_putp4p.c
index f8b65cee..197f24c4 100644
--- a/src/PJ_putp4p.c
+++ b/src/PJ_putp4p.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
struct pj_opaque {
@@ -36,27 +37,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(putp4p) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->C_x = 0.874038744;
@@ -73,7 +57,7 @@ PJ *PROJECTION(putp4p) {
PJ *PROJECTION(weren) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->C_x = 1.;
diff --git a/src/PJ_putp5.c b/src/PJ_putp5.c
index 87b7af74..f8b431b1 100644
--- a/src/PJ_putp5.c
+++ b/src/PJ_putp5.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
struct pj_opaque {
double A, B;
@@ -34,27 +35,11 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(putp5) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->A = 2.;
@@ -71,7 +56,7 @@ PJ *PROJECTION(putp5) {
PJ *PROJECTION(putp5p) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->A = 1.5;
diff --git a/src/PJ_putp6.c b/src/PJ_putp6.c
index 6c4fc246..50859f14 100644
--- a/src/PJ_putp6.c
+++ b/src/PJ_putp6.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
struct pj_opaque {
@@ -51,27 +52,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(putp6) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
Q->C_x = 1.01346;
@@ -91,7 +75,7 @@ PJ *PROJECTION(putp6) {
PJ *PROJECTION(putp6p) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
Q->C_x = 0.44329;
diff --git a/src/PJ_qsc.c b/src/PJ_qsc.c
index e5fee0ea..f8c760a9 100644
--- a/src/PJ_qsc.c
+++ b/src/PJ_qsc.c
@@ -39,7 +39,8 @@
*/
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
struct pj_opaque {
int face;
@@ -361,27 +362,10 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(qsc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
P->inv = e_inverse;
diff --git a/src/PJ_robin.c b/src/PJ_robin.c
index 60a52324..d3f92cd9 100644
--- a/src/PJ_robin.c
+++ b/src/PJ_robin.c
@@ -145,20 +145,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(robin) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_rpoly.c b/src/PJ_rpoly.c
index d0ff8319..8f7b16c6 100644
--- a/src/PJ_rpoly.c
+++ b/src/PJ_rpoly.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <projects.h>
struct pj_opaque {
@@ -34,27 +35,11 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(rpoly) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
if ((Q->mode = (Q->phi1 = fabs(pj_param(P->ctx, P->params, "rlat_ts").f)) > EPS)) {
diff --git a/src/PJ_sch.c b/src/PJ_sch.c
index 6c97a4f3..dc8cc770 100644
--- a/src/PJ_sch.c
+++ b/src/PJ_sch.c
@@ -33,6 +33,7 @@
****************************************************************************/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
#include "geocent.h"
@@ -86,11 +87,6 @@ static LPZ inverse3d(XYZ xyz, PJ *P) {
lpz.phi = temp[0] ;
lpz.z = temp[2];
-#if 0
- printf("INVERSE: \n");
- printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z);
- printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z);
-#endif
return lpz;
}
@@ -129,30 +125,10 @@ static XYZ forward3d(LPZ lpz, PJ *P) {
xyz.y = temp[0] * Q->rcurv / P->a;
xyz.z = temp[2];
-#if 0
- printf("FORWARD: \n");
- printf("LPZ: %f %f %f \n", lpz.lam, lpz.phi, lpz.z);
- printf("XYZ: %f %f %f \n", xyz.x, xyz.y, xyz.z);
-#endif
return xyz;
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
static PJ *setup(PJ *P) { /* general initialization */
struct pj_opaque *Q = P->opaque;
double reast, rnorth;
@@ -165,10 +141,8 @@ static PJ *setup(PJ *P) { /* general initialization */
temp = P->a * sqrt(1.0 - P->es);
/* Setup original geocentric system */
- if ( pj_Set_Geocentric_Parameters(&(Q->elp_0), P->a, temp) != 0) {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
- }
+ if ( pj_Set_Geocentric_Parameters(&(Q->elp_0), P->a, temp) != 0)
+ return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
clt = cos(Q->plat);
slt = sin(Q->plat);
@@ -185,17 +159,10 @@ static PJ *setup(PJ *P) { /* general initialization */
Q->rcurv = Q->h0 + (reast*rnorth)/(reast * chdg * chdg + rnorth * shdg * shdg);
-#if 0
- printf("North Radius: %f \n", rnorth);
- printf("East Radius: %f \n", reast);
- printf("Effective Radius: %f \n", Q->rcurv);
-#endif
-
/* Set up local sphere at the given peg point */
- if ( pj_Set_Geocentric_Parameters(&(Q->sph), Q->rcurv, Q->rcurv) != 0) {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
- }
+ if ( pj_Set_Geocentric_Parameters(&(Q->sph), Q->rcurv, Q->rcurv) != 0)
+ return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
+
/* Set up the transformation matrices */
Q->transMat[0] = clt * clo;
Q->transMat[1] = -shdg*slo - slt*clo * chdg;
@@ -210,20 +177,13 @@ static PJ *setup(PJ *P) { /* general initialization */
if( pj_Convert_Geodetic_To_Geocentric( &(Q->elp_0), Q->plat, Q->plon, Q->h0,
pxyz, pxyz+1, pxyz+2 ) != 0 )
- {
- proj_errno_set(P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
- return freeup_new(P);
- }
+ return pj_default_destructor(P, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
Q->xyzoff[0] = pxyz[0] - (Q->rcurv) * clt * clo;
Q->xyzoff[1] = pxyz[1] - (Q->rcurv) * clt * slo;
Q->xyzoff[2] = pxyz[2] - (Q->rcurv) * slt;
-#if 0
- printf("Offset: %f %f %f \n", Q->xyzoff[0], Q->xyzoff[1], Q->xyzoff[2]);
-#endif
-
P->fwd3d = forward3d;
P->inv3d = inverse3d;
return P;
@@ -233,7 +193,7 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(sch) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
Q->h0 = 0.0;
@@ -242,24 +202,21 @@ PJ *PROJECTION(sch) {
if (pj_param(P->ctx, P->params, "tplat_0").i)
Q->plat = pj_param(P->ctx, P->params, "rplat_0").f;
else {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
}
/* Check if peg longitude was defined */
if (pj_param(P->ctx, P->params, "tplon_0").i)
Q->plon = pj_param(P->ctx, P->params, "rplon_0").f;
else {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
}
/* Check if peg latitude is defined */
if (pj_param(P->ctx, P->params, "tphdg_0").i)
Q->phdg = pj_param(P->ctx, P->params, "rphdg_0").f;
else {
- proj_errno_set(P, PJD_ERR_FAILED_TO_FIND_PROJ);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_FAILED_TO_FIND_PROJ);
}
@@ -267,10 +224,6 @@ PJ *PROJECTION(sch) {
if (pj_param(P->ctx, P->params, "th_0").i)
Q->h0 = pj_param(P->ctx, P->params, "dh_0").f;
- /* Completed reading in the projection parameters */
-#if 0
- printf("PSA: Lat = %f Lon = %f Hdg = %f \n", Q->plat, Q->plon, Q->phdg);
-#endif
return setup(P);
}
diff --git a/src/PJ_sconics.c b/src/PJ_sconics.c
index 8759c66e..7f6e094c 100644
--- a/src/PJ_sconics.c
+++ b/src/PJ_sconics.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -105,35 +106,19 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, (and ellipsoidal?) inverse
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ *setup(PJ *P, int type) {
double del, cs;
- int i;
+ int err;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->type = type;
- i = phi12 (P, &del);
- if(i) {
- proj_errno_set(P, i);
- return freeup_new(P);
- }
+ err = phi12 (P, &del);
+ if(err)
+ return pj_default_destructor (P, err);
+
switch (Q->type) {
case TISSOT:
@@ -172,10 +157,9 @@ static PJ *setup(PJ *P, int type) {
Q->n = sin (Q->sig);
Q->c2 = cos (del);
Q->c1 = 1./tan (Q->sig);
- if (fabs (del = P->phi0 - Q->sig) - EPS10 >= M_HALFPI) {
- proj_errno_set(P, PJD_ERR_LAT_0_HALF_PI_FROM_MEAN);
- return freeup_new(P);
- }
+ if (fabs (del = P->phi0 - Q->sig) - EPS10 >= M_HALFPI)
+ return pj_default_destructor(P, PJD_ERR_LAT_0_HALF_PI_FROM_MEAN);
+
Q->rho_0 = Q->c2 * (Q->c1 - tan (del));
break;
diff --git a/src/PJ_somerc.c b/src/PJ_somerc.c
index 751d0c77..7324d48a 100644
--- a/src/PJ_somerc.c
+++ b/src/PJ_somerc.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -63,31 +64,11 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-#if 0
-FREEUP; if (P) pj_dalloc(P); }
-#endif
-
-
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(somerc) {
double cp, phip0, sp;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
diff --git a/src/PJ_stere.c b/src/PJ_stere.c
index befca308..02b73507 100644
--- a/src/PJ_stere.c
+++ b/src/PJ_stere.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -213,19 +214,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ *setup(PJ *P) { /* general initialization */
double t;
struct pj_opaque *Q = P->opaque;
@@ -291,7 +279,7 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(stere) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->phits = pj_param (P->ctx, P->params, "tlat_ts").i ?
@@ -304,14 +292,14 @@ PJ *PROJECTION(stere) {
PJ *PROJECTION(ups) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
/* International Ellipsoid */
P->phi0 = pj_param(P->ctx, P->params, "bsouth").i ? - M_HALFPI: M_HALFPI;
if (P->es == 0.0) {
proj_errno_set(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
- return freeup_new(P);
+ return pj_default_destructor (P, ENOMEM);
}
P->k0 = .994;
P->x0 = 2000000.;
diff --git a/src/PJ_sterea.c b/src/PJ_sterea.c
index 73c6b48c..e0ff15e7 100644
--- a/src/PJ_sterea.c
+++ b/src/PJ_sterea.c
@@ -24,7 +24,8 @@
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include <projects.h>
struct pj_opaque {
@@ -78,21 +79,15 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor (P, errlev);
}
@@ -101,12 +96,12 @@ PJ *PROJECTION(sterea) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->en = pj_gauss_ini(P->e, P->phi0, &(Q->phic0), &R);
if (0==Q->en)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
Q->sinc0 = sin (Q->phic0);
Q->cosc0 = cos (Q->phic0);
@@ -114,6 +109,8 @@ PJ *PROJECTION(sterea) {
P->inv = e_inverse;
P->fwd = e_forward;
+ P->destructor = destructor;
+
return P;
}
diff --git a/src/PJ_sts.c b/src/PJ_sts.c
index b6b6dc43..3e6168bd 100644
--- a/src/PJ_sts.c
+++ b/src/PJ_sts.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-# include <projects.h>
+#include <errno.h>
+#include "projects.h"
PROJ_HEAD(kav5, "Kavraisky V") "\n\tPCyl., Sph.";
PROJ_HEAD(qua_aut, "Quartic Authalic") "\n\tPCyl., Sph.";
@@ -8,7 +9,7 @@ PROJ_HEAD(mbt_s, "McBryde-Thomas Flat-Polar Sine (No. 1)") "\n\tPCyl., Sph.";
struct pj_opaque {
- double C_x, C_y, C_p; \
+ double C_x, C_y, C_p;
int tan_mode;
};
@@ -50,19 +51,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
static PJ *setup(PJ *P, double p, double q, int mode) {
P->es = 0.;
P->inv = s_inverse;
@@ -81,7 +69,7 @@ static PJ *setup(PJ *P, double p, double q, int mode) {
PJ *PROJECTION(fouc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
return setup(P, 2., 2., 1);
}
@@ -151,7 +139,7 @@ int pj_fouc_selftest (void) {
PJ *PROJECTION(kav5) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
return setup(P, 1.50488, 1.35439, 0);
@@ -221,7 +209,7 @@ int pj_kav5_selftest (void) {
PJ *PROJECTION(qua_aut) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
return setup(P, 2., 2., 0);
}
@@ -289,7 +277,7 @@ int pj_qua_aut_selftest (void) {
PJ *PROJECTION(mbt_s) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
return setup(P, 1.48875, 1.36509, 0);
}
diff --git a/src/PJ_tcc.c b/src/PJ_tcc.c
index 80bb6bc8..26cf67b6 100644
--- a/src/PJ_tcc.c
+++ b/src/PJ_tcc.c
@@ -22,16 +22,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(tcc) {
P->es = 0.;
P->fwd = s_forward;
diff --git a/src/PJ_tcea.c b/src/PJ_tcea.c
index d219928d..65b3c604 100644
--- a/src/PJ_tcea.c
+++ b/src/PJ_tcea.c
@@ -25,16 +25,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(tcea) {
P->inv = s_inverse;
P->fwd = s_forward;
diff --git a/src/PJ_times.c b/src/PJ_times.c
index 5d3b0391..a8d6e67a 100644
--- a/src/PJ_times.c
+++ b/src/PJ_times.c
@@ -66,20 +66,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(times) {
P->es = 0.0;
diff --git a/src/PJ_tmerc.c b/src/PJ_tmerc.c
index 04afc64c..b3ec0030 100644
--- a/src/PJ_tmerc.c
+++ b/src/PJ_tmerc.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -160,26 +161,24 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor(PJ *P, int errlev) { /* Destructor */
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor(P, errlev);
+
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
+ return pj_default_destructor(P, errlev);
}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
static PJ *setup(PJ *P) { /* general initialization */
struct pj_opaque *Q = P->opaque;
if (P->es != 0.0) {
if (!(Q->en = pj_enfn(P->es)))
- return freeup_new(P);
+ return pj_default_destructor(P, ENOMEM);
+
Q->ml0 = pj_mlfn(P->phi0, sin(P->phi0), cos(P->phi0), Q->en);
Q->esp = P->es / (1. - P->es);
P->inv = e_inverse;
@@ -197,8 +196,11 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(tmerc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
+
P->opaque = Q;
+ P->destructor = destructor;
+
return setup(P);
}
diff --git a/src/PJ_tpeqd.c b/src/PJ_tpeqd.c
index 90dd7568..6bea3968 100644
--- a/src/PJ_tpeqd.c
+++ b/src/PJ_tpeqd.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -7,7 +8,7 @@ PROJ_HEAD(tpeqd, "Two Point Equidistant")
"\n\tMisc Sph\n\tlat_1= lon_1= lat_2= lon_2=";
struct pj_opaque {
- double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2; \
+ double cp1, sp1, cp2, sp2, ccs, cs, sc, r2z0, z02, dlam2;
double hz0, thz0, rhshz0, ca, sa, lp, lamc;
};
@@ -55,26 +56,11 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(tpeqd) {
double lam_1, lam_2, phi_1, phi_2, A12, pp;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
@@ -84,10 +70,9 @@ PJ *PROJECTION(tpeqd) {
phi_2 = pj_param(P->ctx, P->params, "rlat_2").f;
lam_2 = pj_param(P->ctx, P->params, "rlon_2").f;
- if (phi_1 == phi_2 && lam_1 == lam_2) {
- proj_errno_set(P, PJD_ERR_CONTROL_POINT_NO_DIST);
- return freeup_new(P);
- }
+ if (phi_1 == phi_2 && lam_1 == lam_2)
+ return pj_default_destructor(P, PJD_ERR_CONTROL_POINT_NO_DIST);
+
P->lam0 = adjlon (0.5 * (lam_1 + lam_2));
Q->dlam2 = adjlon (lam_2 - lam_1);
diff --git a/src/PJ_unitconvert.c b/src/PJ_unitconvert.c
index 27672c8d..c5cf93ae 100644
--- a/src/PJ_unitconvert.c
+++ b/src/PJ_unitconvert.c
@@ -65,9 +65,9 @@ Last update: 2017-05-16
#define PJ_LIB__
#include <time.h>
-#include "proj_internal.h"
-#include <projects.h>
#include <errno.h>
+#include "proj_internal.h"
+#include "projects.h"
PROJ_HEAD(unitconvert, "Unit conversion");
@@ -112,9 +112,16 @@ static double decimalyear_to_mjd(double decimalyear) {
/***********************************************************************
Epoch of modified julian date is 1858-11-16 00:00
************************************************************************/
- int year = (int)floor(decimalyear);
- double fractional_year = decimalyear - year;
- double mjd = (year - 1859)*365 + 14 + 31;
+ int year;
+ double fractional_year;
+ double mjd;
+
+ if( decimalyear < -10000 || decimalyear > 10000 )
+ return 0;
+
+ year = (int)floor(decimalyear);
+ fractional_year = decimalyear - year;
+ mjd = (year - 1859)*365 + 14 + 31;
mjd += fractional_year*days_in_year(year);
/* take care of leap days */
@@ -192,26 +199,6 @@ struct pj_opaque_unitconvert {
/***********************************************************************/
-static void *freeup_msg (PJ *P, int errlev) {
-/***********************************************************************/
- if (0==P)
- return 0;
-
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- return pj_dealloc(P);
-}
-
-
-/***********************************************************************/
-static void freeup (PJ *P) {
-/***********************************************************************/
- freeup_msg (P, 0);
- return;
-}
-
-/***********************************************************************/
static XY forward_2d(LP lp, PJ *P) {
/************************************************************************
Forward unit conversions in the plane
@@ -309,9 +296,9 @@ static PJ_OBS reverse_obs(PJ_OBS obs, PJ *P) {
/* delegate unit conversion of physical dimensions to the 3D function */
out.coo.lpz = reverse_3d(obs.coo.xyz, P);
- if (Q->t_in_id >= 0)
- out.coo.xyzt.t = time_units[Q->t_out_id].t_in( obs.coo.xyzt.t );
if (Q->t_out_id >= 0)
+ out.coo.xyzt.t = time_units[Q->t_out_id].t_in( obs.coo.xyzt.t );
+ if (Q->t_in_id >= 0)
out.coo.xyzt.t = time_units[Q->t_in_id].t_out( out.coo.xyzt.t );
return out;
@@ -326,7 +313,7 @@ PJ *PROJECTION(unitconvert) {
int i;
if (0==Q)
- return freeup_msg (P, ENOMEM);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = (void *) Q;
P->fwdobs = forward_obs;
@@ -346,7 +333,7 @@ PJ *PROJECTION(unitconvert) {
if ((name = pj_param (P->ctx, P->params, "sxy_in").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) return freeup_msg(P, -8); /* unknown unit conversion id */
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID);
Q->xy_in_id = i;
proj_log_debug(P, "xy_in unit: %s", pj_units[i].name);
@@ -355,7 +342,7 @@ PJ *PROJECTION(unitconvert) {
if ((name = pj_param (P->ctx, P->params, "sxy_out").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) return freeup_msg(P, -8); /* unknown unit conversion id */
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID);
Q->xy_out_id = i;
proj_log_debug(P, "xy_out unit: %s", pj_units[i].name);
@@ -364,7 +351,7 @@ PJ *PROJECTION(unitconvert) {
if ((name = pj_param (P->ctx, P->params, "sz_in").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) return freeup_msg(P, -8); /* unknown unit conversion id */
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID); /* unknown unit conversion id */
Q->z_in_id = i;
proj_log_debug(P, "z_in unit: %s", pj_units[i].name);
@@ -373,7 +360,7 @@ PJ *PROJECTION(unitconvert) {
if ((name = pj_param (P->ctx, P->params, "sz_out").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) return freeup_msg(P, -8); /* unknown unit conversion id */
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID); /* unknown unit conversion id */
Q->z_out_id = i;
proj_log_debug(P, "z_out unit: %s", pj_units[i].name);
@@ -383,7 +370,7 @@ PJ *PROJECTION(unitconvert) {
if ((name = pj_param (P->ctx, P->params, "st_in").s) != NULL) {
for (i = 0; (s = time_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) return freeup_msg(P, -8); /* unknown unit conversion id */
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID); /* unknown unit conversion id */
Q->t_in_id = i;
proj_log_debug(P, "t_in unit: %s", time_units[i].name);
@@ -392,9 +379,9 @@ PJ *PROJECTION(unitconvert) {
s = 0;
if ((name = pj_param (P->ctx, P->params, "st_out").s) != NULL) {
for (i = 0; (s = time_units[i].id) && strcmp(name, s) ; ++i);
- if (!s) {
- return freeup_msg(P, -8); /* unknown unit conversion id */
- }
+
+ if (!s) return pj_default_destructor(P, PJD_ERR_UNKNOW_UNIT_ID); /* unknown unit conversion id */
+
Q->t_out_id = i;
proj_log_debug(P, "t_out unit: %s", time_units[i].name);
}
@@ -410,7 +397,7 @@ int pj_unitconvert_selftest (void) {return 0;}
static int test_time(char* args, double tol, double t_in, double t_exp) {
PJ_OBS in, out;
- PJ *P = proj_create(0, args);
+ PJ *P = proj_create(PJ_DEFAULT_CTX, args);
int ret = 0;
if (P == 0)
@@ -436,7 +423,7 @@ static int test_time(char* args, double tol, double t_in, double t_exp) {
static int test_xyz(char* args, double tol, PJ_TRIPLET in, PJ_TRIPLET exp) {
PJ_OBS out, obs_in;
- PJ *P = proj_create(0, args);
+ PJ *P = proj_create(PJ_DEFAULT_CTX, args);
int ret = 0;
if (P == 0)
diff --git a/src/PJ_urm5.c b/src/PJ_urm5.c
index 9d904fc7..bd073459 100644
--- a/src/PJ_urm5.c
+++ b/src/PJ_urm5.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -22,36 +23,19 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (P->opaque)
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(urm5) {
double alpha, t;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
if (pj_param(P->ctx, P->params, "tn").i) {
Q->n = pj_param(P->ctx, P->params, "dn").f;
- if (Q->n <= 0. || Q->n > 1.) {
- proj_errno_set(P, PJD_ERR_N_OUT_OF_RANGE);
- return freeup_new(0);
- }
+ if (Q->n <= 0. || Q->n > 1.)
+ return pj_default_destructor(P, PJD_ERR_N_OUT_OF_RANGE);
} else {
- proj_errno_set(P, PJD_ERR_N_OUT_OF_RANGE);
- return freeup_new(0);
+ return pj_default_destructor(P, PJD_ERR_N_OUT_OF_RANGE);
}
Q->q3 = pj_param(P->ctx, P->params, "dq").f / 3.;
alpha = pj_param(P->ctx, P->params, "ralpha").f;
diff --git a/src/PJ_urmfps.c b/src/PJ_urmfps.c
index fcc7b853..64eb5c80 100644
--- a/src/PJ_urmfps.c
+++ b/src/PJ_urmfps.c
@@ -1,4 +1,5 @@
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -31,20 +32,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
static PJ *setup(PJ *P) {
P->opaque->C_y = Cy / P->opaque->n;
P->es = 0.;
@@ -57,18 +44,16 @@ static PJ *setup(PJ *P) {
PJ *PROJECTION(urmfps) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
+
P->opaque = Q;
if (pj_param(P->ctx, P->params, "tn").i) {
P->opaque->n = pj_param(P->ctx, P->params, "dn").f;
- if (P->opaque->n <= 0. || P->opaque->n > 1.) {
- proj_errno_set(P, PJD_ERR_N_OUT_OF_RANGE);
- return freeup_new(P);
- }
+ if (P->opaque->n <= 0. || P->opaque->n > 1.)
+ return pj_default_destructor(P, PJD_ERR_N_OUT_OF_RANGE);
} else {
- proj_errno_set(P, PJD_ERR_N_OUT_OF_RANGE);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_N_OUT_OF_RANGE);
}
return setup(P);
@@ -78,7 +63,7 @@ PJ *PROJECTION(urmfps) {
PJ *PROJECTION(wag1) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
P->opaque->n = 0.8660254037844386467637231707;
diff --git a/src/PJ_vandg.c b/src/PJ_vandg.c
index 282eb661..e19d01b8 100644
--- a/src/PJ_vandg.c
+++ b/src/PJ_vandg.c
@@ -97,20 +97,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(vandg) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_vandg2.c b/src/PJ_vandg2.c
index fac7e85d..3f11e289 100644
--- a/src/PJ_vandg2.c
+++ b/src/PJ_vandg2.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
-#include <projects.h>
+#include <errno.h>
+#include "projects.h"
struct pj_opaque {
int vdg3;
@@ -44,27 +45,10 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(vandg2) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->vdg3 = 0;
@@ -76,7 +60,7 @@ PJ *PROJECTION(vandg2) {
PJ *PROJECTION(vandg3) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
Q->vdg3 = 1;
diff --git a/src/PJ_vandg4.c b/src/PJ_vandg4.c
index 2dbb0713..f7f48b43 100644
--- a/src/PJ_vandg4.c
+++ b/src/PJ_vandg4.c
@@ -44,20 +44,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(vandg4) {
P->es = 0.;
P->fwd = s_forward;
diff --git a/src/PJ_vgridshift.c b/src/PJ_vgridshift.c
index e790cd4d..ededd544 100644
--- a/src/PJ_vgridshift.c
+++ b/src/PJ_vgridshift.c
@@ -1,25 +1,9 @@
#define PJ_LIB__
#include "proj_internal.h"
-#include <projects.h>
+#include "projects.h"
PROJ_HEAD(vgridshift, "Vertical grid shift");
-static void *freeup_msg (PJ *P, int errlev) {
- if (0==P)
- return 0;
-
- if (0!=P->ctx)
- pj_ctx_set_errno (P->ctx, errlev);
-
- return pj_dealloc(P);
-}
-
-
-static void freeup (PJ *P) {
- freeup_msg (P, 0);
- return;
-}
-
static XYZ forward_3d(LPZ lpz, PJ *P) {
PJ_TRIPLET point;
@@ -74,7 +58,7 @@ PJ *PROJECTION(vgridshift) {
if (!pj_param(P->ctx, P->params, "tgrids").i) {
proj_log_error(P, "vgridshift: +grids parameter missing.");
- return freeup_msg(P, -1);
+ return pj_default_destructor(P, PJD_ERR_NO_ARGS);
}
/* Build gridlist. P->gridlist can be empty if +grids only ask for optional grids. */
@@ -84,9 +68,7 @@ PJ *PROJECTION(vgridshift) {
/* Was gridlist compiled properly? */
if ( pj_ctx_get_errno(P->ctx) ) {
proj_log_error(P, "vgridshift: could not find required grid(s).");
- pj_dalloc(P->gridlist);
- P->gridlist = NULL;
- return freeup_msg(P, -38);
+ return pj_default_destructor(P, -38);
}
P->fwdobs = forward_obs;
@@ -111,19 +93,24 @@ int pj_vgridshift_selftest (void) {
PJ *P;
PJ_OBS expect, a, b;
double dist;
+ int failures = 0;
- /* fail on purpose: +grids parameter it mandatory*/
- P = proj_create(0, "+proj=vgridshift");
- if (0!=P)
+ /* fail on purpose: +grids parameter is mandatory*/
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift");
+ if (0!=P) {
+ proj_destroy (P);
return 99;
+ }
/* fail on purpose: open non-existing grid */
- P = proj_create(0, "+proj=vgridshift +grids=nonexistinggrid.gtx");
- if (0!=P)
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift +grids=nonexistinggrid.gtx");
+ if (0!=P) {
+ proj_destroy (P);
return 999;
+ }
/* Failure most likely means the grid is missing */
- P = proj_create (0, "+proj=vgridshift +grids=egm96_15.gtx +ellps=GRS80");
+ P = proj_create(PJ_DEFAULT_CTX, "+proj=vgridshift +grids=egm96_15.gtx +ellps=GRS80");
if (0==P)
return 10;
@@ -131,18 +118,26 @@ int pj_vgridshift_selftest (void) {
a.coo.lpz.lam = PJ_TORAD(12.5);
a.coo.lpz.phi = PJ_TORAD(55.5);
- dist = proj_roundtrip (P, PJ_FWD, 1, a);
+ dist = proj_roundtrip (P, PJ_FWD, 1, a.coo);
if (dist > 0.00000001)
return 1;
expect = a;
- expect.coo.lpz.z = -36.021305084228515625;
+ /* Appears there is a difference between the egm96_15.gtx distributed by OSGeo4W, */
+ /* and the one from http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx */
+ /* Was: expect.coo.lpz.z = -36.021305084228515625; (download.osgeo.org) */
+ /* Was: expect.coo.lpz.z = -35.880001068115234000; (OSGeo4W) */
+ /* This is annoying, but must be handled elsewhere. So for now, we check for both. */
+ expect.coo.lpz.z = -36.021305084228516;
+ failures = 0;
b = proj_trans_obs(P, PJ_FWD, a);
- if (proj_xyz_dist(expect.coo.xyz, b.coo.xyz) > 1e-10)
+ if (proj_xyz_dist(expect.coo.xyz, b.coo.xyz) > 1e-4) failures++;
+ expect.coo.lpz.z = -35.880001068115234000;
+ if (proj_xyz_dist(expect.coo.xyz, b.coo.xyz) > 1e-4) failures++;
+ if (failures > 1)
return 2;
-
-
- pj_free(P);
+
+ proj_destroy (P);
return 0;
}
diff --git a/src/PJ_wag2.c b/src/PJ_wag2.c
index 9a41ab63..0588167e 100644
--- a/src/PJ_wag2.c
+++ b/src/PJ_wag2.c
@@ -25,16 +25,6 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(wag2) {
P->es = 0.;
P->inv = s_inverse;
diff --git a/src/PJ_wag3.c b/src/PJ_wag3.c
index 7f5aa4ad..7f300add 100644
--- a/src/PJ_wag3.c
+++ b/src/PJ_wag3.c
@@ -1,6 +1,9 @@
#define PJ_LIB__
-# include <projects.h>
+#include <projects.h>
+#include <errno.h>
+
PROJ_HEAD(wag3, "Wagner III") "\n\tPCyl., Sph.\n\tlat_ts=";
+
#define TWOTHIRD 0.6666666666666666666667
struct pj_opaque {
@@ -16,11 +19,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-#if 0
-INVERSE(s_inverse); /* spheroid */
-#endif
-
-
static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
LP lp = {0.0,0.0};
lp.phi = xy.y;
@@ -28,20 +26,13 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
return lp;
}
-static void freeup (PJ *P) {
- pj_freeup_plain (P);
- return;
-}
-
PJ *PROJECTION(wag3) {
double ts;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- {
- freeup(P);
- return 0;
- }
+ return pj_default_destructor(P, ENOMEM);
+
P->opaque = Q;
ts = pj_param (P->ctx, P->params, "rlat_ts").f;
diff --git a/src/PJ_wag7.c b/src/PJ_wag7.c
index d24f4e1a..9152fdea 100644
--- a/src/PJ_wag7.c
+++ b/src/PJ_wag7.c
@@ -19,17 +19,6 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
-
PJ *PROJECTION(wag7) {
P->fwd = s_forward;
P->inv = 0;
diff --git a/src/PJ_wink1.c b/src/PJ_wink1.c
index 320a4fb6..c1e2e909 100644
--- a/src/PJ_wink1.c
+++ b/src/PJ_wink1.c
@@ -1,7 +1,8 @@
#define PJ_LIB__
#include <projects.h>
-PROJ_HEAD(wink1, "Winkel I") "\n\tPCyl., Sph.\n\tlat_ts=";
+#include <errno.h>
+PROJ_HEAD(wink1, "Winkel I") "\n\tPCyl., Sph.\n\tlat_ts=";
struct pj_opaque {
double cosphi1;
@@ -25,25 +26,10 @@ static LP s_inverse (XY xy, PJ *P) { /* Spheroidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(wink1) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
P->opaque->cosphi1 = cos (pj_param(P->ctx, P->params, "rlat_ts").f);
diff --git a/src/PJ_wink2.c b/src/PJ_wink2.c
index 4b82e423..43b6cfce 100644
--- a/src/PJ_wink2.c
+++ b/src/PJ_wink2.c
@@ -1,5 +1,6 @@
#define PJ_LIB__
# include <projects.h>
+#include <errno.h>
PROJ_HEAD(wink2, "Winkel II") "\n\tPCyl., Sph., no inv.\n\tlat_1=";
@@ -33,25 +34,10 @@ static XY s_forward (LP lp, PJ *P) { /* Spheroidal, forward */
}
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
-
PJ *PROJECTION(wink2) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
P->opaque->cosphi1 = cos(pj_param(P->ctx, P->params, "rlat_1").f);
diff --git a/src/bin_cct.cmake b/src/bin_cct.cmake
new file mode 100644
index 00000000..a204e7e7
--- /dev/null
+++ b/src/bin_cct.cmake
@@ -0,0 +1,9 @@
+set(CCT_SRC cct.c proj_strtod.c)
+set(CCT_INCLUDE optargpm.h)
+
+source_group("Source Files\\Bin" FILES ${CCT_SRC})
+
+add_executable(cct ${CCT_SRC} ${CCT_INCLUDE})
+target_link_libraries(cct ${PROJ_LIBRARIES})
+install(TARGETS cct
+ RUNTIME DESTINATION ${BINDIR})
diff --git a/src/cct.c b/src/cct.c
new file mode 100644
index 00000000..83a0b0a3
--- /dev/null
+++ b/src/cct.c
@@ -0,0 +1,324 @@
+/***********************************************************************
+
+ The cct 4D Transformation program
+
+************************************************************************
+
+cct is a 4D equivalent to the "proj" projection program.
+
+cct is an acronym meaning "Coordinate Conversion and Transformation".
+
+The acronym refers to definitions given in the OGC 08-015r2/ISO-19111
+standard "Geographical Information -- Spatial Referencing by Coordinates",
+which defines two different classes of coordinate operations:
+
+*Coordinate Conversions*, which are coordinate operations where input
+and output datum are identical (e.g. conversion from geographical to
+cartesian coordinates) and
+
+*Coordinate Transformations*, which are coordinate operations where
+input and output datums differ (e.g. change of reference frame).
+
+cct, however, also refers to Carl Christian Tscherning (1942--2014),
+professor of Geodesy at the University of Copenhagen, mentor and advisor
+for a generation of Danish geodesists, colleague and collaborator for
+two generations of global geodesists, Secretary General for the
+International Association of Geodesy, IAG (1995--2007), fellow of the
+Amercan Geophysical Union (1991), recipient of the IAG Levallois Medal
+(2007), the European Geosciences Union Vening Meinesz Medal (2008), and
+of numerous other honours.
+
+cct, or Christian, as he was known to most of us, was recognized for his
+good mood, his sharp wit, his tireless work, and his great commitment to
+the development of geodesy - both through his scientific contributions,
+comprising more than 250 publications, and by his mentoring and teaching
+of the next generations of geodesists.
+
+As Christian was an avid Fortran programmer, and a keen Unix connoiseur,
+he would have enjoyed to know that his initials would be used to name a
+modest Unix style transformation filter, hinting at the tireless aspect
+of his personality, which was certainly one of the reasons he accomplished
+so much, and meant so much to so many people.
+
+Hence, in honour of cct (the geodesist) this is cct (the program).
+
+************************************************************************
+
+Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-09-19
+
+************************************************************************
+
+* Copyright (c) 2016, 2017 Thomas Knudsen
+* Copyright (c) 2017, SDFE
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+
+***********************************************************************/
+
+#include "optargpm.h"
+#include <proj.h>
+#include <projects.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+
+double proj_strtod(const char *str, char **endptr);
+double proj_atof(const char *str);
+
+char *column (char *buf, int n);
+PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time);
+int print_output_line (FILE *fout, char *buf, PJ_COORD point);
+int main(int argc, char **argv);
+
+
+
+static const char usage[] = {
+ "--------------------------------------------------------------------------------\n"
+ "Usage: %s [-options]... [+operator_specs]... infile...\n"
+ "--------------------------------------------------------------------------------\n"
+ "Options:\n"
+ "--------------------------------------------------------------------------------\n"
+ " -o /path/to/file Specify output file name\n"
+ " -c x,y,z,t Specify input columns for (up to) 4 input parameters.\n"
+ " Defaults to 1,2,3,4\n"
+ " -z value Provide a fixed z value for all input data (e.g. -z 0)\n"
+ " -t value Provide a fixed t value for all input data (e.g. -t 0)\n"
+ " -v Verbose: Provide non-essential informational output.\n"
+ " Repeat -v for more verbosity (e.g. -vv)\n"
+ "--------------------------------------------------------------------------------\n"
+ "Long Options:\n"
+ "--------------------------------------------------------------------------------\n"
+ " --output Alias for -o\n"
+ " --columns Alias for -c\n"
+ " --height Alias for -z\n"
+ " --time Alias for -t\n"
+ " --verbose Alias for -v\n"
+ " --help Alias for -h\n"
+ "--------------------------------------------------------------------------------\n"
+ "Operator Specs:\n"
+ "--------------------------------------------------------------------------------\n"
+ "The operator specs describe the action to be performed by cct, e.g:\n"
+ "\n"
+ " +proj=utm +ellps=GRS80 +zone=32\n"
+ "\n"
+ "instructs cct to convert input data to Universal Transverse Mercator, zone 32\n"
+ "coordinates, based on the GRS80 ellipsoid.\n"
+ "\n"
+ "Hence, the command\n"
+ "\n"
+ " echo 12 55 | cct -z0 -t0 +proj=utm +zone=32 +ellps=GRS80\n"
+ "\n"
+ "Should give results comparable to the classic proj command\n"
+ "\n"
+ " echo 12 55 | proj +proj=utm +zone=32 +ellps=GRS80\n"
+ "--------------------------------------------------------------------------------\n"
+ "Examples:\n"
+ "--------------------------------------------------------------------------------\n"
+ "1. convert geographical input to UTM zone 32 on the GRS80 ellipsoid:\n"
+ " cct +proj=utm +ellps=GRS80 +zone=32\n"
+ "2. roundtrip accuracy check for the case above:\n"
+ " cct +proj=pipeline +proj=utm +ellps=GRS80 +zone=32 +step +step +inv\n"
+ "3. as (1) but specify input columns for longitude, latitude, height and time:\n"
+ " cct -c 5,2,1,4 +proj=utm +ellps=GRS80 +zone=32\n"
+ "4. as (1) but specify fixed height and time, hence needing only 2 cols in input:\n"
+ " cct -t 0 -z 0 +proj=utm +ellps=GRS80 +zone=32\n"
+ "--------------------------------------------------------------------------------\n"
+};
+
+int main(int argc, char **argv) {
+ PJ *P;
+ PJ_COORD point;
+ OPTARGS *o;
+ FILE *fout = stdout;
+ char *buf;
+ int input_unit, output_unit, nfields = 4, direction = 1, verbose;
+ double fixed_z = HUGE_VAL, fixed_time = HUGE_VAL;
+ int columns_xyzt[] = {1, 2, 3, 4};
+ const char *longflags[] = {"v=verbose", "h=help", 0};
+ const char *longkeys[] = {"o=output", "c=columns", "z=height", "t=time", 0};
+
+ o = opt_parse (argc, argv, "hv", "cozt", longflags, longkeys);
+ if (0==o)
+ return 0;
+
+ if (opt_given (o, "h")) {
+ printf (usage, o->progname);
+ return 0;
+ }
+
+
+ direction = opt_given (o, "I")? -1: 1;
+ verbose = opt_given (o, "v");
+
+ if (opt_given (o, "o"))
+ fout = fopen (opt_arg (o, "output"), "rt");
+ if (0==fout) {
+ fprintf (stderr, "%s: Cannot open '%s' for output\n", o->progname, opt_arg (o, "output"));
+ free (o);
+ return 1;
+ }
+ if (verbose > 3)
+ fprintf (fout, "%s: Running in very verbose mode\n", o->progname);
+
+
+
+ if (opt_given (o, "z")) {
+ fixed_z = proj_atof (opt_arg (o, "z"));
+ nfields--;
+ }
+
+ if (opt_given (o, "t")) {
+ fixed_time = proj_atof (opt_arg (o, "t"));
+ nfields--;
+ }
+
+ if (opt_given (o, "c")) {
+ int ncols = sscanf (opt_arg (o, "c"), "%d,%d,%d,%d", columns_xyzt, columns_xyzt+1, columns_xyzt+3, columns_xyzt+3);
+ if (ncols != nfields) {
+ fprintf (stderr, "%s: Too few input columns given: '%s'\n", o->progname, opt_arg (o, "c"));
+ free (o);
+ if (stdout != fout)
+ fclose (fout);
+ return 1;
+ }
+ }
+
+ /* Setup transformation */
+ P = proj_create_argv (0, o->pargc, o->pargv);
+ if ((0==P) || (0==o->pargc)) {
+ fprintf (stderr, "%s: Bad transformation arguments. '%s -h' for help\n", o->progname, o->progname);
+ free (o);
+ if (stdout != fout)
+ fclose (fout);
+ return 1;
+ }
+
+ input_unit = P->left;
+ output_unit = P->right;
+ if (PJ_IO_UNITS_CLASSIC==P->left)
+ input_unit = PJ_IO_UNITS_RADIANS;
+ if (PJ_IO_UNITS_CLASSIC==P->right)
+ output_unit = PJ_IO_UNITS_METERS;
+ if (direction==-1) {
+ enum pj_io_units swap = input_unit;
+ input_unit = output_unit;
+ output_unit = swap;
+ }
+
+ /* Allocate input buffer */
+ buf = calloc (1, 10000);
+ if (0==buf) {
+ fprintf (stderr, "%s: Out of memory\n", o->progname);
+ pj_free (P);
+ free (o);
+ if (stdout != fout)
+ fclose (fout);
+ return 1;
+ }
+
+
+ /* Loop over all lines of all input files */
+ while (opt_input_loop (o, optargs_file_format_text)) {
+ void *ret = fgets (buf, 10000, o->input);
+ int res;
+ opt_eof_handler (o);
+ if (0==ret) {
+ fprintf (stderr, "Read error in record %d\n", (int) o->record_index);
+ continue;
+ }
+ point = parse_input_line (buf, columns_xyzt, fixed_z, fixed_time);
+ if (PJ_IO_UNITS_RADIANS==input_unit) {
+ point.lpzt.lam = proj_torad (point.lpzt.lam);
+ point.lpzt.phi = proj_torad (point.lpzt.phi);
+ }
+ point = proj_trans_coord (P, direction, point);
+ if (PJ_IO_UNITS_RADIANS==output_unit) {
+ point.lpzt.lam = proj_todeg (point.lpzt.lam);
+ point.lpzt.phi = proj_todeg (point.lpzt.phi);
+ }
+ res = print_output_line (fout, buf, point);
+ if (0==res) {
+ fprintf (fout, "# UNREADABLE: %s", buf);
+ if (verbose)
+ fprintf (stderr, "%s: Could not parse file '%s' line %d\n", o->progname, opt_filename (o), opt_record (o));
+ }
+ }
+ if (stdout != fout)
+ fclose (fout);
+ free (o);
+ return 0;
+}
+
+
+
+
+
+/* return a pointer to the n'th column of buf */
+char *column (char *buf, int n) {
+ int i;
+ if (n <= 0)
+ return buf;
+ for (i = 0; i < n; i++) {
+ while (isspace(*buf))
+ buf++;
+ if (i == n - 1)
+ break;
+ while ((0 != *buf) && !isspace(*buf))
+ buf++;
+ }
+ return buf;
+}
+
+
+PJ_COORD parse_input_line (char *buf, int *columns, double fixed_height, double fixed_time) {
+ PJ_COORD err = proj_coord (HUGE_VAL, HUGE_VAL, HUGE_VAL, HUGE_VAL);
+ PJ_COORD result = err;
+ int prev_errno = errno;
+ char *endptr = 0;
+ errno = 0;
+
+ result.xyzt.z = fixed_height;
+ result.xyzt.t = fixed_time;
+ result.xyzt.x = proj_strtod (column (buf, columns[0]), &endptr);
+ result.xyzt.y = proj_strtod (column (buf, columns[1]), &endptr);
+ if (result.xyzt.z==HUGE_VAL)
+ result.xyzt.z = proj_strtod (column (buf, columns[2]), &endptr);
+ if (result.xyzt.t==HUGE_VAL)
+ result.xyzt.t = proj_strtod (column (buf, columns[3]), &endptr);
+
+ if (0!=errno)
+ return err;
+
+ errno = prev_errno;
+ return result;
+}
+
+
+int print_output_line (FILE *fout, char *buf, PJ_COORD point) {
+ char *c;
+ if (HUGE_VAL!=point.xyzt.x)
+ return fprintf (fout, "%20.15f %20.15f %20.15f %20.15f\n", point.xyzt.x, point.xyzt.y, point.xyzt.z, point.xyzt.t);
+ c = column (buf, 1);
+ /* reflect comments and blanks */
+ if (c && ((*c=='\0') || (*c=='#')))
+ return fprintf (fout, "%s\n", buf);
+ return 0;
+}
diff --git a/src/geodesic.c b/src/geodesic.c
index aeb82c71..84951d7f 100644
--- a/src/geodesic.c
+++ b/src/geodesic.c
@@ -26,6 +26,10 @@
#include "geodesic.h"
#include <math.h>
+#if !defined(HAVE_C99_MATH)
+#define HAVE_C99_MATH 0
+#endif
+
#define GEOGRAPHICLIB_GEODESIC_ORDER 6
#define nA1 GEOGRAPHICLIB_GEODESIC_ORDER
#define nC1 GEOGRAPHICLIB_GEODESIC_ORDER
@@ -105,6 +109,12 @@ enum captype {
};
static real sq(real x) { return x * x; }
+#if HAVE_C99_MATH
+#define atanhx atanh
+#define copysignx copysign
+#define hypotx hypot
+#define cbrtx cbrt
+#else
static real log1px(real x) {
volatile real
y = 1 + x,
@@ -133,6 +143,7 @@ static real cbrtx(real x) {
real y = pow(fabs(x), 1/(real)(3)); /* Return the real cube root */
return x < 0 ? -y : y;
}
+#endif
static real sumx(real u, real v, real* t) {
volatile real s = u + v;
@@ -170,8 +181,13 @@ static void norm2(real* sinx, real* cosx) {
}
static real AngNormalize(real x) {
+#if HAVE_C99_MATH
+ x = remainder(x, (real)(360));
+ return x != -180 ? x : 180;
+#else
x = fmod(x, (real)(360));
return x <= -180 ? x + 360 : (x <= 180 ? x : x - 360);
+#endif
}
static real LatFix(real x)
@@ -202,9 +218,15 @@ 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;
+#if HAVE_C99_MATH && !defined(__GNUC__)
+ /* Disable for gcc because of bug in glibc version < 2.22, see
+ * https://sourceware.org/bugzilla/show_bug.cgi?id=17569 */
+ r = remquo(x, (real)(90), &q);
+#else
r = fmod(x, (real)(360));
q = (int)(floor(r / 90 + (real)(0.5)));
r -= 90 * q;
+#endif
/* now abs(r) <= 45 */
r *= degree;
/* Possibly could call the gnu extension sincos */
@@ -538,7 +560,9 @@ real geod_genposition(const struct geod_geodesicline* l,
salp2 = l->salp0; calp2 = l->calp0 * csig2; /* No need to normalize */
if (outmask & GEOD_DISTANCE)
- s12 = flags & GEOD_ARCMODE ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12;
+ s12 = flags & GEOD_ARCMODE ?
+ l->b * ((1 + l->A1m1) * sig12 + AB1) :
+ s12_a12;
if (outmask & GEOD_LONGITUDE) {
real E = copysignx(1, l->salp0); /* east or west going? */
@@ -576,7 +600,8 @@ real geod_genposition(const struct geod_geodesicline* l,
m12 = l->b * ((dn2 * (l->csig1 * ssig2) - l->dn1 * (l->ssig1 * csig2))
- l->csig1 * csig2 * J12);
if (outmask & GEOD_GEODESICSCALE) {
- real t = l->k2 * (ssig2 - l->ssig1) * (ssig2 + l->ssig1) / (l->dn1 + dn2);
+ real t = l->k2 * (ssig2 - l->ssig1) * (ssig2 + l->ssig1) /
+ (l->dn1 + dn2);
M12 = csig12 + (t * ssig2 - csig2 * J12) * l->ssig1 / l->dn1;
M21 = csig12 - (t * l->ssig1 - l->csig1 * J12) * ssig2 / dn2;
}
@@ -639,7 +664,9 @@ static void geod_setarc(struct geod_geodesicline* l, real a13) {
void geod_gensetdistance(struct geod_geodesicline* l,
unsigned flags, real s13_a13) {
- flags & GEOD_ARCMODE ? geod_setarc(l, s13_a13) : geod_setdistance(l, s13_a13);
+ flags & GEOD_ARCMODE ?
+ geod_setarc(l, s13_a13) :
+ geod_setdistance(l, s13_a13);
}
void geod_position(const struct geod_geodesicline* l, real s12,
@@ -1758,10 +1785,17 @@ int transit(real lon1, real lon2) {
}
int transitdirect(real lon1, real lon2) {
+#if HAVE_C99_MATH
+ lon1 = remainder(lon1, (real)(720));
+ lon2 = remainder(lon2, (real)(720));
+ return ( (lon2 >= 0 && lon2 < 360 ? 0 : 1) -
+ (lon1 >= 0 && lon1 < 360 ? 0 : 1) );
+#else
lon1 = fmod(lon1, (real)(720));
lon2 = fmod(lon2, (real)(720));
return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+#endif
}
void accini(real s[]) {
diff --git a/src/geodesic.h b/src/geodesic.h
index f3cb3009..ab18a01f 100644
--- a/src/geodesic.h
+++ b/src/geodesic.h
@@ -112,7 +112,7 @@
* https://geographiclib.sourceforge.io/
*
* This library was distributed with
- * <a href="../index.html">GeographicLib</a> 1.48.
+ * <a href="../index.html">GeographicLib</a> 1.49.
**********************************************************************/
#if !defined(GEODESIC_H)
@@ -127,12 +127,12 @@
* The minor version of the geodesic library. (This tracks the version of
* GeographicLib.)
**********************************************************************/
-#define GEODESIC_VERSION_MINOR 48
+#define GEODESIC_VERSION_MINOR 49
/**
* The patch level of the geodesic library. (This tracks the version of
* GeographicLib.)
**********************************************************************/
-#define GEODESIC_VERSION_PATCH 1
+#define GEODESIC_VERSION_PATCH 0
/**
* Pack the version components into a single integer. Users should not rely on
@@ -881,16 +881,16 @@ extern "C" {
* mask values for the \e caps argument to geod_lineinit().
**********************************************************************/
enum geod_mask {
- GEOD_NONE = 0U, /**< Calculate nothing */
- GEOD_LATITUDE = 1U<<7 | 0U, /**< Calculate latitude */
- GEOD_LONGITUDE = 1U<<8 | 1U<<3, /**< Calculate longitude */
- GEOD_AZIMUTH = 1U<<9 | 0U, /**< Calculate azimuth */
- GEOD_DISTANCE = 1U<<10 | 1U<<0, /**< Calculate distance */
- GEOD_DISTANCE_IN = 1U<<11 | 1U<<0 | 1U<<1, /**< Allow distance as input */
- GEOD_REDUCEDLENGTH= 1U<<12 | 1U<<0 | 1U<<2, /**< Calculate reduced length */
- GEOD_GEODESICSCALE= 1U<<13 | 1U<<0 | 1U<<2, /**< Calculate geodesic scale */
- GEOD_AREA = 1U<<14 | 1U<<4, /**< Calculate reduced length */
- GEOD_ALL = 0x7F80U| 0x1FU /**< Calculate everything */
+ GEOD_NONE = 0U, /**< Calculate nothing */
+ GEOD_LATITUDE = 1U<<7 | 0U, /**< Calculate latitude */
+ GEOD_LONGITUDE = 1U<<8 | 1U<<3, /**< Calculate longitude */
+ GEOD_AZIMUTH = 1U<<9 | 0U, /**< Calculate azimuth */
+ GEOD_DISTANCE = 1U<<10 | 1U<<0, /**< Calculate distance */
+ GEOD_DISTANCE_IN = 1U<<11 | 1U<<0 | 1U<<1,/**< Allow distance as input */
+ GEOD_REDUCEDLENGTH= 1U<<12 | 1U<<0 | 1U<<2,/**< Calculate reduced length */
+ GEOD_GEODESICSCALE= 1U<<13 | 1U<<0 | 1U<<2,/**< Calculate geodesic scale */
+ GEOD_AREA = 1U<<14 | 1U<<4, /**< Calculate reduced length */
+ GEOD_ALL = 0x7F80U| 0x1FU /**< Calculate everything */
};
/**
diff --git a/src/geodtest.c b/src/geodtest.c
index 5ca741b1..6899436c 100644
--- a/src/geodtest.c
+++ b/src/geodtest.c
@@ -16,7 +16,7 @@
#include <math.h>
#if defined(_MSC_VER)
-// Squelch warnings about assignment within conditional expression
+/* Squelch warnings about assignment within conditional expression */
# pragma warning (disable: 4706)
#endif
@@ -618,8 +618,9 @@ static int GeodSolve73() {
return result;
}
-static void planimeter(const struct geod_geodesic* g, double points[][2], int N,
- double* perimeter, double* area) {
+static void planimeter(const struct geod_geodesic* g,
+ double points[][2], int N,
+ double* perimeter, double* area) {
struct geod_polygon p;
int i;
geod_polygon_init(&p, 0);
@@ -628,8 +629,9 @@ static void planimeter(const struct geod_geodesic* g, double points[][2], int N,
geod_polygon_compute(g, &p, 0, 1, area, perimeter);
}
-static void polylength(const struct geod_geodesic* g, double points[][2], int N,
- double* perimeter) {
+static void polylength(const struct geod_geodesic* g,
+ double points[][2], int N,
+ double* perimeter) {
struct geod_polygon p;
int i;
geod_polygon_init(&p, 1);
@@ -658,6 +660,34 @@ static int GeodSolve74() {
return result;
}
+static int GeodSolve76() {
+ /* The distance from Wellington and Salamanca (a classic failure of
+ Vincenty) */
+ double azi1, azi2, s12;
+ struct geod_geodesic g;
+ int result = 0;
+ geod_init(&g, wgs84_a, wgs84_f);
+ geod_inverse(&g, -(41+19/60.0), 174+49/60.0, 40+58/60.0, -(5+30/60.0),
+ &s12, &azi1, &azi2);
+ result += assertEquals(azi1, 160.39137649664, 0.5e-11);
+ result += assertEquals(azi2, 19.50042925176, 0.5e-11);
+ result += assertEquals(s12, 19960543.857179, 0.5e-6);
+ return result;
+}
+
+static int GeodSolve78() {
+ /* An example where the NGS calculator fails to converge */
+ double azi1, azi2, s12;
+ struct geod_geodesic g;
+ int result = 0;
+ geod_init(&g, wgs84_a, wgs84_f);
+ geod_inverse(&g, 27.2, 0.0, -27.1, 179.5, &s12, &azi1, &azi2);
+ result += assertEquals(azi1, 45.82468716758, 0.5e-11);
+ result += assertEquals(azi2, 134.22776532670, 0.5e-11);
+ result += assertEquals(s12, 19974354.765767, 0.5e-6);
+ return result;
+}
+
static int Planimeter0() {
/* Check fix for pole-encircling bug found 2011-03-16 */
double pa[4][2] = {{89, 0}, {89, 90}, {89, 180}, {89, 270}};
@@ -786,6 +816,8 @@ int main() {
if ((i = GeodSolve71())) {++n; printf("GeodSolve71 fail: %d\n", i);}
if ((i = GeodSolve73())) {++n; printf("GeodSolve73 fail: %d\n", i);}
if ((i = GeodSolve74())) {++n; printf("GeodSolve74 fail: %d\n", i);}
+ if ((i = GeodSolve76())) {++n; printf("GeodSolve76 fail: %d\n", i);}
+ if ((i = GeodSolve78())) {++n; printf("GeodSolve78 fail: %d\n", i);}
if ((i = Planimeter0())) {++n; printf("Planimeter0 fail: %d\n", i);}
if ((i = Planimeter5())) {++n; printf("Planimeter5 fail: %d\n", i);}
if ((i = Planimeter6())) {++n; printf("Planimeter6 fail: %d\n", i);}
diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake
index c22e1b52..1be10362 100644
--- a/src/lib_proj.cmake
+++ b/src/lib_proj.cmake
@@ -89,6 +89,7 @@ SET(SRC_LIBPROJ_PJ
PJ_lagrng.c
PJ_larr.c
PJ_lask.c
+ PJ_latlong.c
PJ_lcca.c
PJ_lcc.c
PJ_loxim.c
@@ -193,7 +194,6 @@ SET(SRC_LIBPROJ_CORE
pj_initcache.c
pj_inv.c
pj_inv3d.c
- pj_latlong.c
pj_list.c
pj_list.h
pj_log.c
diff --git a/src/makefile.vc b/src/makefile.vc
index cc57d806..ac5acf15 100644
--- a/src/makefile.vc
+++ b/src/makefile.vc
@@ -25,7 +25,7 @@ misc = \
PJ_chamb.obj PJ_hammer.obj PJ_lagrng.obj PJ_larr.obj \
PJ_lask.obj PJ_nocol.obj PJ_ob_tran.obj PJ_oea.obj \
PJ_sch.obj PJ_tpeqd.obj PJ_vandg.obj PJ_vandg2.obj \
- PJ_vandg4.obj PJ_wag7.obj pj_latlong.obj PJ_krovak.obj \
+ PJ_vandg4.obj PJ_wag7.obj PJ_latlong.obj PJ_krovak.obj \
pj_geocent.obj PJ_healpix.obj PJ_qsc.obj
pseudo = \
@@ -70,11 +70,13 @@ LIBOBJ = $(support) $(pseudo) $(azimuthal) $(conic) $(cylinder) $(misc) \
PROJEXE_OBJ = proj.obj gen_cheb.obj p_series.obj emess.obj
CS2CSEXE_OBJ = cs2cs.obj gen_cheb.obj p_series.obj emess.obj
GEODEXE_OBJ = geod.obj geod_set.obj geod_interface.obj emess.obj
+CCTEXE_OBJ = cct.obj proj_strtod.obj
MULTISTRESSTEST_OBJ = multistresstest.obj
PROJ_DLL = proj$(VERSION).dll
PROJ_EXE = proj.exe
CS2CS_EXE = cs2cs.exe
GEOD_EXE = geod.exe
+CCT_EXE = cct.exe
NAD2BIN_EXE = nad2bin.exe
MULTISTRESSTEST_EXE = multistresstest.exe
@@ -83,7 +85,7 @@ CFLAGS = /nologo -I. -DPROJ_LIB=\"$(PROJ_LIB_DIR)\" \
default: all
-all: proj.lib $(PROJ_EXE) $(CS2CS_EXE) $(GEOD_EXE) $(NAD2BIN_EXE)
+all: proj.lib $(PROJ_EXE) $(CS2CS_EXE) $(GEOD_EXE) $(CCT_EXE) $(NAD2BIN_EXE)
proj.lib: $(LIBOBJ)
if exist proj.lib del proj.lib
@@ -108,6 +110,10 @@ $(GEOD_EXE): $(GEODEXE_OBJ) $(EXE_PROJ)
cl $(GEODEXE_OBJ) $(EXE_PROJ)
if exist $(GEOD_EXE).manifest mt -manifest $(GEOD_EXE).manifest -outputresource:$(GEOD_EXE);1
+$(CCT_EXE): $(CCTEXE_OBJ) $(EXE_PROJ)
+ cl $(CCTEXE_OBJ) $(EXE_PROJ)
+ if exist $(CCT_EXE).manifest mt -manifest $(CCT_EXE).manifest -outputresource:$(CCT_EXE);1
+
$(NAD2BIN_EXE): nad2bin.obj emess.obj $(EXE_PROJ)
cl nad2bin.obj emess.obj $(EXE_PROJ)
diff --git a/src/multistresstest.c b/src/multistresstest.c
index 8fb764e2..ddbbb033 100644
--- a/src/multistresstest.c
+++ b/src/multistresstest.c
@@ -363,6 +363,7 @@ static int do_main(void)
{
printf( "Unable to translate:\n%s\n", test->src_def );
test->skip = 1;
+ pj_free (dst_pj);
continue;
}
@@ -370,6 +371,7 @@ static int do_main(void)
{
printf( "Unable to translate:\n%s\n", test->dst_def );
test->skip = 1;
+ pj_free (src_pj);
continue;
}
diff --git a/src/optargpm.h b/src/optargpm.h
new file mode 100644
index 00000000..6be2c9ef
--- /dev/null
+++ b/src/optargpm.h
@@ -0,0 +1,593 @@
+/***********************************************************************
+
+ OPTARGPM - a header-only library for decoding
+ PROJ.4 style command line options
+
+ Thomas Knudsen, 2017-09-10
+
+************************************************************************
+
+For PROJ.4 command line programs, we have a somewhat complex option
+decoding situation, since we have to navigate in a cocktail of classic
+single letter style options, prefixed by "-", GNU style long options
+prefixwd by "--", transformation specification elements prefixed by "+",
+and input file names prefixed by "" nothing.
+
+Hence, classic getopt.h style decoding does not cut the mustard, so
+this is an attempt to catch up and chop the ketchup.
+
+Since optargpm (for "optarg plus minus") does not belong, in any
+obvious way, in any systems development library, it is provided as
+a "header only" library.
+
+While this is conventional in C++, it is frowned at in plain C.
+But frown away - "header only" has its places, and this is one of
+them.
+
+By convention, we expect a command line to consist of the following
+elements:
+
+ <operator/program name>
+ [short ("-")/long ("--") options}
+ [operator ("+") specs]
+ [operands/input files]
+
+or less verbose:
+
+ <operator> [options] [operator specs] [operands]
+
+or less abstract:
+
+ proj -I --output=foo +proj=utm +zone=32 +ellps=GRS80 bar baz...
+
+Where
+
+Operator is proj
+Options are -I --output=foo
+Operator specs are +proj=utm +zone=32 +ellps=GRS80
+Operands are bar baz
+
+
+While claiming neither to save the world, nor to hint at the "shape of
+jazz to come", at least optargpm has shown useful in constructing cs2cs
+style transformation filters.
+
+Supporting a wide range of option syntax, the getoptpm API is somewhat
+quirky, but also compact, consisting of one data type, 3(+2) functions,
+and one enumeration:
+
+OPTARGS
+ Housekeeping data type. An instance of OPTARGS is conventionally
+ called o or opt
+opt_parse (opt, argc, argv ...):
+ The work horse: Define supported options; Split (argc, argv)
+ into groups (options, op specs, operands); Parse option
+ arguments.
+opt_given (o, option):
+ The number of times <option> was given on the command line.
+ (i.e. 0 if not given or option unsupported)
+opt_arg (o, option):
+ A char pointer to the argument for <option>
+
+The 2 additional functions (of which, one is really a macro) implements
+a "read all operands sequentially" functionality, eliminating the need to
+handle open/close of a sequence of input files:
+
+enum OPTARGS_FILE_MODE:
+ indicates whether to read operands in text (0) or binary (1) mode
+opt_input_loop (o, mode):
+ When used as condition in a while loop, traverses all operands,
+ giving the impression of reading just a single input file.
+opt_eof_handler (o):
+ Auxiliary macro, to be called inside the input loop after each
+ read operation
+
+Usage is probably easiest understood by a brief textbook style example:
+
+Consider a simple program taking the conventinal "-v, -h, -o" options
+indicating "verbose output", "help please", and "output file specification",
+respectively.
+
+The "-v" and "-h" options are *flags*, taking no arguments, while the
+"-o" option is a *key*, taking a *value* argument, representing the
+output file name.
+
+The short options have long aliases: "--verbose", "--help" and "--output".
+Additionally, the long key "--hello", without any short counterpart, is
+supported.
+
+-------------------------------------------------------------------------------
+
+
+int main(int argc, char **argv) {
+ PJ *P;
+ OPTARGS *o;
+ FILE *out = stdout;
+ char *longflags[] = {"v=verbose", "h=help", 0};
+ char *longkeys[] = {"o=output", "hello", 0};
+
+ o = opt_parse (argc, argv, "hv", "o", longflags, longkeys);
+ if (0==o)
+ return 0;
+
+
+ if (opt_given (o, "h")) {
+ printf ("Usage: %s [-v|--verbose] [-h|--help] [-o|--output <filename>] [--hello=<name>] infile...", o->progname);
+ exit (0);
+ }
+
+ if (opt_given (o, "v"))
+ puts ("Feeling chatty today?");
+
+ if (opt_given (o, "hello")) {
+ printf ("Hello, %s!\n", opt_arg(o, "hello"));
+ exit (0);
+ }
+
+ if (opt_given (o, "o"))
+ out = fopen (opt_arg (o, "output"), "rt"); // Note: "output" translates to "o" internally
+
+ // Setup transformation
+ P = proj_create_argv (0, o->pargc, o->pargv);
+
+ // Loop over all lines of all input files
+ while (opt_input_loop (o, optargs_file_format_text)) {
+ char buf[1000];
+ int ret = fgets (buf, 1000, o->input);
+ opt_eof_handler (o);
+ if (0==ret) {
+ fprintf (stderr, "Read error in record %d\n", (int) o->record_index);
+ continue;
+ }
+ do_what_needs_to_be_done (buf);
+ }
+
+ return 0;
+}
+
+
+-------------------------------------------------------------------------------
+
+Note how short aliases for longflags and longkeys are defined by prefixing
+an "o=", "h=" or "v=", respectively. This also means that it is possible to
+have more than one alias for each short option, e.g.
+
+ longkeys = {"o=output", "o=banana", 0}
+
+would define both "--output" and "--banana" to be aliases for "-o".
+
+************************************************************************
+
+Thomas Knudsen, thokn@sdfe.dk, 2016-05-25/2017-09-10
+
+************************************************************************
+
+* Copyright (c) 2016, 2017 Thomas Knudsen
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+
+***********************************************************************/
+
+#define PJ_LIB__
+#include <proj.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+
+/**************************************************************************************************/
+struct OPTARGS;
+typedef struct OPTARGS OPTARGS;
+enum OPTARGS_FILE_FORMAT {optargs_file_format_text = 0, optargs_file_format_binary = 1};
+
+char *opt_filename (OPTARGS *opt);
+static int opt_eof (OPTARGS *opt);
+int opt_record (OPTARGS *opt);
+int opt_input_loop (OPTARGS *opt, int binary);
+static int opt_is_flag (OPTARGS *opt, int ordinal);
+static int opt_raise_flag (OPTARGS *opt, int ordinal);
+static int opt_ordinal (OPTARGS *opt, char *option);
+int opt_given (OPTARGS *opt, char *option);
+char *opt_arg (OPTARGS *opt, char *option);
+OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, const char **longflags, const char **longkeys);
+
+#define opt_eof_handler(opt) if (opt_eof (opt)) {continue;} else {;}
+/**************************************************************************************************/
+
+struct OPTARGS {
+ int argc, margc, pargc, fargc;
+ char **argv, **margv, **pargv, **fargv;
+ FILE *input;
+ int input_index;
+ int record_index;
+ char *progname; /* argv[0], stripped from /path/to, if present */
+ char flaglevel[21]; /* if flag -f is specified n times, its optarg pointer is set to flaglevel + n */
+ char *optarg[256]; /* optarg[(int) 'f'] holds a pointer to the argument of option "-f" */
+ char *flags; /* a list of flag style options supported, e.g. "hv" (help and verbose) */
+ char *keys; /* a list of key/value style options supported, e.g. "o" (output) */
+ const char **longflags; /* long flags, {"help", "verbose"}, or {"h=help", "v=verbose"}, to indicate homologous short options */
+ const char **longkeys; /* e.g. {"output"} or {o=output"} to support --output=/path/to/output-file. In the latter case, */
+ /* all operations on "--output" gets redirected to "-o", so user code need handle arguments to "-o" only */
+};
+
+
+/* name of file currently read from */
+char *opt_filename (OPTARGS *opt) {
+ if (0==opt)
+ return 0;
+ if (0==opt->fargc)
+ return opt->flaglevel;
+ return opt->fargv[opt->input_index];
+}
+
+static int opt_eof (OPTARGS *opt) {
+ if (0==opt)
+ return 1;
+ return feof (opt->input);
+}
+
+/* record number of most recently read record */
+int opt_record (OPTARGS *opt) {
+ if (0==opt)
+ return 0;
+ return opt->record_index + 1;
+}
+
+
+/* handle closing/opening of a "stream-of-streams" */
+int opt_input_loop (OPTARGS *opt, int binary) {
+ if (0==opt)
+ return 0;
+
+ /* most common case: increment record index and read on */
+ if ( (opt->input!=0) && !feof (opt->input) ) {
+ opt->record_index++;
+ return 1;
+ }
+
+ opt->record_index = 0;
+
+ /* no input files specified - read from stdin */
+ if ((0==opt->fargc) && (0==opt->input)) {
+ opt->input = stdin;
+ return 1;
+ }
+
+ /* if we're here, we have either reached eof on current input file. */
+ /* or not yet opened a file. If eof on stdin, we're done */
+ if (opt->input==stdin)
+ return 0;
+
+ /* end if no more input */
+ if (0!=opt->input)
+ fclose (opt->input);
+ if (opt->input_index >= opt->fargc)
+ return 0;
+
+ /* otherwise, open next input file */
+ opt->input = fopen (opt->fargv[opt->input_index++], binary? "rb": "rt");
+
+ /* ignore non-existing files - go on! */
+ if (0==opt->input)
+ return opt_input_loop (opt, binary);
+ return 0;
+}
+
+
+/* return true if option with given ordinal is a flag, false if undefined or key=value */
+static int opt_is_flag (OPTARGS *opt, int ordinal) {
+ if (opt->optarg[ordinal] < opt->flaglevel)
+ return 0;
+ if (opt->optarg[ordinal] > opt->flaglevel + 20)
+ return 0;
+ return 1;
+}
+
+static int opt_raise_flag (OPTARGS *opt, int ordinal) {
+ if (opt->optarg[ordinal] < opt->flaglevel)
+ return 1;
+ if (opt->optarg[ordinal] > opt->flaglevel + 20)
+ return 1;
+
+ /* Max out at 20 */
+ if (opt->optarg[ordinal]==opt->flaglevel + 20)
+ return 0;
+ opt->optarg[ordinal]++;
+ return 0;
+}
+
+/* Find the ordinal value of any (short or long) option */
+static int opt_ordinal (OPTARGS *opt, char *option) {
+ int i;
+ if (0==opt)
+ return 0;
+ if (0==option)
+ return 0;
+ if (0==option[0])
+ return 0;
+ /* An ordinary -o style short option */
+ if (strlen (option)==1) {
+ /* Undefined option? */
+ if (0==opt->optarg[(int) option[0]])
+ return 0;
+ return (int) option[0];
+ }
+
+ /* --longname style long options are slightly harder */
+ for (i = 0; i < 64; i++) {
+ const char **f = opt->longflags;
+ if (0==f)
+ break;
+ if (0==f[i])
+ break;
+ if (0==strcmp(f[i], "END"))
+ break;
+ if (0==strcmp(f[i], option))
+ return 128 + i;
+
+ /* long alias? - return ordinal for corresponding short */
+ if ((strlen(f[i]) > 2) && (f[i][1]=='=') && (0==strcmp(f[i]+2, option))) {
+ /* Undefined option? */
+ if (0==opt->optarg[(int) f[i][0]])
+ return 0;
+ return (int) f[i][0];
+ }
+ }
+
+ for (i = 0; i < 64; i++) {
+ const char **v = opt->longkeys;
+ if (0==v)
+ return 0;
+ if (0==v[i])
+ return 0;
+ if (0==strcmp (v[i], "END"))
+ return 0;
+ if (0==strcmp(v[i], option))
+ return 192 + i;
+
+ /* long alias? - return ordinal for corresponding short */
+ if ((strlen(v[i]) > 2) && (v[i][1]=='=') && (0==strcmp(v[i]+2, option))) {
+ /* Undefined option? */
+ if (0==opt->optarg[(int) v[i][0]])
+ return 0;
+ return (int) v[i][0];
+ }
+
+ }
+
+ return 0;
+}
+
+
+/* Returns 0 if option was not given on command line, non-0 otherwise */
+int opt_given (OPTARGS *opt, char *option) {
+ int ordinal = opt_ordinal (opt, option);
+ if (0==ordinal)
+ return 0;
+ /* For flags we return the number of times the flag was specified (mostly for repeated -v(erbose) flags) */
+ if (opt_is_flag (opt, ordinal))
+ return (int) (opt->optarg[ordinal] - opt->flaglevel);
+ return opt->argv[0] != opt->optarg[ordinal];
+}
+
+
+/* Returns the argument to a given option */
+char *opt_arg (OPTARGS *opt, char *option) {
+ int ordinal = opt_ordinal (opt, option);
+ if (0==ordinal)
+ return 0;
+ return opt->optarg[ordinal];
+}
+
+
+/* split command line options into options/flags ("-" style), projdefs ("+" style) and input file args */
+OPTARGS *opt_parse (int argc, char **argv, const char *flags, const char *keys, const char **longflags, const char **longkeys) {
+ int i, j;
+ OPTARGS *o;
+ char *last_path_delim;
+
+ o = (OPTARGS *) calloc (1, sizeof(OPTARGS));
+ if (0==o)
+ return 0;
+
+ o->argc = argc;
+ o->argv = argv;
+ o->progname = argv[0];
+ last_path_delim = strrchr (argv[0], '\\');
+ if (last_path_delim > o->progname)
+ o->progname = last_path_delim;
+ last_path_delim = strrchr (argv[0], '/');
+ if (last_path_delim > o->progname)
+ o->progname = last_path_delim;
+
+
+ /* Reset all flags */
+ for (i = 0; i < (int) strlen (flags); i++)
+ o->optarg[(int) flags[i]] = o->flaglevel;
+
+ /* Flag args for all argument taking options as "unset" */
+ for (i = 0; i < (int) strlen (keys); i++)
+ o->optarg[(int) keys[i]] = argv[0];
+
+ /* Hence, undefined/illegal options have an argument of 0 */
+
+ /* long opts are handled similarly, but are mapped to the high bit character range (above 128) */
+ o->longflags = longflags;
+ o->longkeys = longkeys;
+
+
+ /* check aliases, An end user should never experience this, but the developer should make sure that aliases are valid */
+ for (i = 0; longflags && longflags[i]; i++) {
+ /* Go on if it does not look like an alias */
+ if (strlen (longflags[i]) < 3)
+ continue;
+ if ('='!=longflags[i][1])
+ continue;
+ if (0==strchr (flags, longflags[i][0])) {
+ fprintf (stderr, "%s: Invalid alias - '%s'. Valid short flags are '%s'\n", o->progname, longflags[i], flags);
+ free (o);
+ return 0;
+ }
+ }
+ for (i = 0; longkeys && longkeys[i]; i++) {
+ /* Go on if it does not look like an alias */
+ if (strlen (longkeys[i]) < 3)
+ continue;
+ if ('='!=longkeys[i][1])
+ continue;
+ if (0==strchr (keys, longkeys[i][0])) {
+ fprintf (stderr, "%s: Invalid alias - '%s'. Valid short flags are '%s'\n", o->progname, longkeys[i], keys);
+ free (o);
+ return 0;
+ }
+ }
+
+ /* aside from counting the number of times a flag has been specified, we also abuse the */
+ /* flaglevel array to provide a pseudo-filename for the case of reading from stdin */
+ strcpy (o->flaglevel, "<stdin>");
+
+ for (i = 128; (longflags != 0) && (longflags[i - 128] != 0); i++) {
+ if (i==192) {
+ free (o);
+ fprintf (stderr, "Too many flag style long options\n");
+ return 0;
+ }
+ o->optarg[i] = o->flaglevel;
+ }
+
+ for (i = 192; (longkeys != 0) && (longkeys[i - 192] != 0); i++) {
+ if (i==256) {
+ free (o);
+ fprintf (stderr, "Too many value style long options\n");
+ return 0;
+ }
+ o->optarg[i] = argv[0];
+ }
+
+ /* Now, set up the agrc/argv pairs, and interpret args */
+ o->argc = argc;
+ o->argv = argv;
+
+ /* Process all '-' and '--'-style options */
+ for (i = 1; i < argc; i++) {
+ int arg_group_size = (int) strlen (argv[i]);
+
+ if ('-' != argv[i][0])
+ break;
+ if (0==o->margv)
+ o->margv = argv + i;
+ o->margc++;
+
+ for (j = 1; j < arg_group_size; j++) {
+ int c = argv[i][j];
+ char cstring[2], *crepr = cstring;
+ cstring[0] = (char) c;
+ cstring[1] = 0;
+
+
+ /* Long style flags and options (--long_opt_name, --long_opt_namr arg, --long_opt_name=arg) */
+ if (c== (int)'-') {
+ char *equals;
+ crepr = argv[i] + 2;
+
+ /* need to maniplulate a bit to support gnu style --pap=pop syntax */
+ equals = strchr (crepr, '=');
+ if (equals)
+ *equals = 0;
+ c = opt_ordinal (o, crepr);
+ if (0==c)
+ return fprintf (stderr, "Invalid option \"%s\"\n", crepr), (OPTARGS *) 0;
+
+ /* inline (gnu) --foo=bar style arg */
+ if (equals) {
+ *equals = '=';
+ if (opt_is_flag (o, c))
+ return fprintf (stderr, "Option \"%s\" takes no arguments\n", crepr), (OPTARGS *) 0;
+ o->optarg[c] = equals + 1;
+ break;
+ }
+
+ /* "outline" --foo bar style arg */
+ if (!opt_is_flag (o, c)) {
+ if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0]))
+ return fprintf (stderr, "Missing argument for option \"%s\"\n", crepr), (OPTARGS *) 0;
+ o->optarg[c] = argv[i + 1];
+ i++; /* eat the arg */
+ break;
+ }
+
+ if (!opt_is_flag (o, c))
+ return fprintf (stderr, "Expected flag style long option here, but got \"%s\"\n", crepr), (OPTARGS *) 0;
+
+ /* Flag style option, i.e. taking no arguments */
+ opt_raise_flag (o, c);
+ break;
+ }
+
+ /* classic short options */
+ if (0==o->optarg[c])
+ return fprintf (stderr, "Invalid option \"%s\"\n", crepr), (OPTARGS *) 0;
+
+ /* Flag style option, i.e. taking no arguments */
+ if (opt_is_flag (o, c)) {
+ opt_raise_flag (o, c);
+ continue;
+ }
+
+ /* options taking argumants */
+
+ /* argument separate (i.e. "-i 10") */
+ if (j + 1==arg_group_size) {
+ if ((argc==i + 1) || ('+'==argv[i+1][0]) || ('-'==argv[i+1][0]))
+ return fprintf (stderr, "Bad or missing arg for option \"%s\"\n", crepr), (OPTARGS *) 0;
+ o->optarg[(int) c] = argv[i + 1];
+ i++;
+ break;
+ }
+
+ /* Option arg inline (i.e. "-i10") */
+ o->optarg[c] = argv[i] + j + 1;
+ break;
+ }
+ }
+
+ /* Process all '+'-style options, starting from where '-'-style processing ended */
+ o->pargv = argv + i;
+ for (/* empty */; i < argc; i++) {
+ if ('-' == argv[i][0]) {
+ free (o);
+ fprintf (stderr, "+ and - style options must not be mixed\n");
+ return 0;
+ }
+
+ if ('+' != argv[i][0])
+ break;
+ o->pargc++;
+ }
+
+ /* Handle input file names */
+ o->fargc = argc - i;
+ if (0!=o->fargc)
+ o->fargv = argv + i;
+
+ return o;
+
+}
diff --git a/src/pj_ctx.c b/src/pj_ctx.c
index 89b2816f..a8edaf43 100644
--- a/src/pj_ctx.c
+++ b/src/pj_ctx.c
@@ -27,6 +27,7 @@
#include <projects.h>
#include <string.h>
+#include <errno.h>
static projCtx_t default_context;
static volatile int default_context_initialized = 0;
@@ -38,6 +39,10 @@ static volatile int default_context_initialized = 0;
projCtx pj_get_ctx( projPJ pj )
{
+ if (0==pj)
+ return pj_get_default_ctx ();
+ if (0==pj->ctx)
+ return pj_get_default_ctx ();
return pj->ctx;
}
@@ -50,6 +55,8 @@ projCtx pj_get_ctx( projPJ pj )
void pj_set_ctx( projPJ pj, projCtx ctx )
{
+ if (pj==0)
+ return;
pj->ctx = ctx;
}
@@ -98,6 +105,8 @@ projCtx pj_ctx_alloc()
{
projCtx ctx = (projCtx_t *) malloc(sizeof(projCtx_t));
+ if (0==ctx)
+ return 0;
memcpy( ctx, pj_get_default_ctx(), sizeof(projCtx_t) );
ctx->last_errno = 0;
@@ -111,7 +120,7 @@ projCtx pj_ctx_alloc()
void pj_ctx_free( projCtx ctx )
{
- free( ctx );
+ pj_dealloc( ctx );
}
/************************************************************************/
@@ -121,21 +130,25 @@ void pj_ctx_free( projCtx ctx )
int pj_ctx_get_errno( projCtx ctx )
{
+ if (0==ctx)
+ return pj_get_default_ctx ()->last_errno;
return ctx->last_errno;
}
/************************************************************************/
/* pj_ctx_set_errno() */
/* */
-/* Also sets the global 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 )
- pj_errno = new_errno;
+ if( new_errno == 0 )
+ return;
+ errno = new_errno;
+ pj_errno = new_errno;
}
/************************************************************************/
@@ -145,6 +158,8 @@ void pj_ctx_set_errno( projCtx ctx, int new_errno )
void pj_ctx_set_debug( projCtx ctx, int new_debug )
{
+ if (0==ctx)
+ pj_get_default_ctx ()->debug_level = new_debug;
ctx->debug_level = new_debug;
}
@@ -155,6 +170,8 @@ void pj_ctx_set_debug( projCtx ctx, int new_debug )
void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) )
{
+ if (0==ctx)
+ return;
ctx->logger = new_logger;
}
@@ -165,6 +182,8 @@ void pj_ctx_set_logger( projCtx ctx, void (*new_logger)(void*,int,const char*) )
void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
{
+ if (0==ctx)
+ return;
ctx->app_data = new_app_data;
}
@@ -175,6 +194,8 @@ void pj_ctx_set_app_data( projCtx ctx, void *new_app_data )
void *pj_ctx_get_app_data( projCtx ctx )
{
+ if (0==ctx)
+ return 0;
return ctx->app_data;
}
@@ -185,6 +206,8 @@ void *pj_ctx_get_app_data( projCtx ctx )
void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
{
+ if (0==ctx)
+ return;
ctx->fileapi = fileapi;
}
@@ -195,5 +218,7 @@ void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
{
+ if (0==ctx)
+ return 0;
return ctx->fileapi;
}
diff --git a/src/pj_fwd.c b/src/pj_fwd.c
index 02f18d1c..e010f6ec 100644
--- a/src/pj_fwd.c
+++ b/src/pj_fwd.c
@@ -17,8 +17,8 @@ pj_fwd(LP lp, PJ *P) {
return err;
last_errno = proj_errno_reset (P);
- /* Check input coordinates if angular */
- if ((P->left==PJ_IO_UNITS_CLASSIC)||(P->left==PJ_IO_UNITS_RADIANS)) {
+ /* Check validity of angular input coordinates */
+ if (P->left==PJ_IO_UNITS_RADIANS) {
/* check for forward and latitude or longitude overange */
t = fabs(lp.phi)-M_HALFPI;
diff --git a/src/pj_fwd3d.c b/src/pj_fwd3d.c
index be683745..d141178f 100644
--- a/src/pj_fwd3d.c
+++ b/src/pj_fwd3d.c
@@ -20,8 +20,8 @@ XYZ pj_fwd3d(LPZ lpz, PJ *P) {
last_errno = proj_errno_reset(P);
- /* Check input coordinates if angular */
- if ((P->left==PJ_IO_UNITS_CLASSIC)||(P->left==PJ_IO_UNITS_RADIANS)) {
+ /* Check validity of angular input coordinates */
+ if (P->left==PJ_IO_UNITS_RADIANS) {
/* check for forward and latitude or longitude overange */
t = fabs(lpz.phi)-M_HALFPI;
diff --git a/src/pj_geocent.c b/src/pj_geocent.c
index a00fc991..667c29bd 100644
--- a/src/pj_geocent.c
+++ b/src/pj_geocent.c
@@ -48,19 +48,6 @@ static LP inverse(XY xy, PJ *P) {
return lp;
}
-
-static void *freeup_new (PJ *P) {
- if (0==P)
- return 0;
-
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
PJ *PROJECTION(geocent) {
P->is_geocent = 1;
P->x0 = 0.0;
diff --git a/src/pj_gridlist.c b/src/pj_gridlist.c
index 4193526f..1123274e 100644
--- a/src/pj_gridlist.c
+++ b/src/pj_gridlist.c
@@ -102,11 +102,11 @@ static int pj_gridlist_merge_gridfile( projCtx ctx,
PJ_GRIDINFO **new_list;
int new_max = *p_gridmax + 20;
- new_list = (PJ_GRIDINFO **) pj_malloc(sizeof(void*) * new_max);
+ new_list = (PJ_GRIDINFO **) pj_calloc(new_max, sizeof(void *));
if( *p_gridlist != NULL )
{
memcpy( new_list, *p_gridlist,
- sizeof(void*) * (*p_gridmax) );
+ sizeof(void *) * (*p_gridmax) );
pj_dalloc( *p_gridlist );
}
@@ -194,7 +194,7 @@ PJ_GRIDINFO **pj_gridlist_from_nadgrids( projCtx ctx, const char *nadgrids,
if( end_char >= sizeof(name) )
{
pj_dalloc( gridlist );
- pj_ctx_set_errno( ctx, -38 );
+ pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
pj_release_lock();
return NULL;
}
@@ -211,7 +211,7 @@ PJ_GRIDINFO **pj_gridlist_from_nadgrids( projCtx ctx, const char *nadgrids,
&& required )
{
pj_dalloc( gridlist );
- pj_ctx_set_errno( ctx, -38 );
+ pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
pj_release_lock();
return NULL;
}
diff --git a/src/pj_init.c b/src/pj_init.c
index 7448fdb6..951f1cfb 100644
--- a/src/pj_init.c
+++ b/src/pj_init.c
@@ -414,6 +414,8 @@ bum_call:
return result;
}
+
+
/************************************************************************/
/* pj_init() */
/* */
@@ -438,15 +440,18 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
int found_def = 0;
PJ *PIN = 0;
+ if (0==ctx)
+ ctx = pj_get_default_ctx ();
+
ctx->last_errno = 0;
start = NULL;
- /* put arguments into internal linked list */
if (argc <= 0) {
- pj_ctx_set_errno( ctx, -1 );
- goto bum_call;
+ pj_ctx_set_errno (ctx, PJD_ERR_NO_ARGS);
+ return 0;
}
-
+
+ /* put arguments into internal linked list */
start = curr = pj_mkparam(argv[0]);
/* build parameter list and expand +init's. Does not take care of a single +init. */
@@ -458,12 +463,11 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
found_def = 0;
curr = get_init(ctx, &curr, curr->next, pj_param(ctx, curr, "sinit").s, &found_def);
if (!curr)
- goto bum_call;
+ return pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS);
- if (!found_def) {
- pj_ctx_set_errno( ctx, -2);
- goto bum_call;
- }
+ if (!found_def)
+ return pj_dealloc_params (ctx, start, PJD_ERR_NO_OPTION_IN_INIT_FILE);
+
} else {
curr = curr->next;
}
@@ -475,31 +479,32 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
found_def = 0;
curr = get_init(ctx, &start, curr, pj_param(ctx, start, "sinit").s, &found_def);
if (!curr)
- goto bum_call;
- if (!found_def) {
- pj_ctx_set_errno( ctx, -2);
- goto bum_call;
- }
+ return pj_dealloc_params (ctx, start, PJD_ERR_NO_ARGS);
+ if (!found_def)
+ return pj_dealloc_params (ctx, start, PJD_ERR_NO_OPTION_IN_INIT_FILE);
}
-
- if (ctx->last_errno) goto bum_call;
-
+
+ if (ctx->last_errno)
+ return pj_dealloc_params (ctx, start, ctx->last_errno);
+
/* find projection selection */
- if (!(name = pj_param(ctx, start, "sproj").s)) {
- pj_ctx_set_errno( ctx, -4 );
- goto bum_call;
- }
+ if (!(name = pj_param(ctx, start, "sproj").s))
+ return pj_default_destructor (PIN, PJD_ERR_PROJ_NOT_NAMED);
for (i = 0; (s = pj_list[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_ctx_set_errno( ctx, -5 ); goto bum_call; }
-
+ if (!s)
+ return pj_dealloc_params (ctx, start, PJD_ERR_UNKNOWN_PROJECTION_ID);
+
/* set defaults, unless inhibited */
- if (!pj_param(ctx, start, "bno_defs").i)
+ if (!(pj_param(ctx, start, "bno_defs").i))
curr = get_defaults(ctx,&start, curr, name);
proj = (PJ *(*)(PJ *)) pj_list[i].proj;
/* allocate projection structure */
- if (!(PIN = (*proj)(0))) goto bum_call;
+ PIN = proj(0);
+ if (0==PIN)
+ return pj_dealloc_params (ctx, start, ENOMEM);
+
PIN->ctx = ctx;
PIN->params = start;
PIN->is_latlong = 0;
@@ -515,19 +520,19 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
PIN->vgridlist_geoid_count = 0;
/* set datum parameters */
- if (pj_datum_set(ctx, start, PIN)) goto bum_call;
+ if (pj_datum_set(ctx, start, PIN))
+ return pj_default_destructor (PIN, PJD_ERR_MISSING_ARGS);
/* set ellipsoid/sphere parameters */
if (pj_ell_set(ctx, start, &PIN->a, &PIN->es)) {
pj_log (ctx, PJ_LOG_DEBUG_MINOR, "pj_init_ctx: Must specify ellipsoid or sphere");
- goto bum_call;
+ return pj_default_destructor (PIN, PJD_ERR_MISSING_ARGS);
}
PIN->a_orig = PIN->a;
PIN->es_orig = PIN->es;
/* Compute some ancillary ellipsoidal parameters */
-
PIN->e = sqrt(PIN->es); /* eccentricity */
PIN->alpha = asin (PIN->e); /* angular eccentricity */
@@ -536,7 +541,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
PIN->e2s = PIN->e2 * PIN->e2;
/* third eccentricity */
- PIN->e3 = sin (PIN->alpha) / sqrt(2 - sin (PIN->alpha)*sin (PIN->alpha));
+ PIN->e3 = (0!=PIN->alpha)? sin (PIN->alpha) / sqrt(2 - sin (PIN->alpha)*sin (PIN->alpha)): 0;
PIN->e3s = PIN->e3 * PIN->e3;
/* flattening */
@@ -544,7 +549,7 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
PIN->rf = PIN->f != 0.0 ? 1.0/PIN->f: HUGE_VAL;
/* second flattening */
- PIN->f2 = 1/cos (PIN->alpha) - 1;
+ PIN->f2 = (cos(PIN->alpha)!=0)? 1/cos (PIN->alpha) - 1: 0;
PIN->rf2 = PIN->f2 != 0.0 ? 1/PIN->f2: HUGE_VAL;
/* third flattening */
@@ -557,7 +562,8 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
PIN->ra = 1. / PIN->a;
PIN->one_es = 1. - PIN->es;
- if (PIN->one_es == 0.) { pj_ctx_set_errno( ctx, -6 ); goto bum_call; }
+ if (PIN->one_es == 0.)
+ return pj_default_destructor (PIN, PJD_ERR_ECCENTRICITY_IS_ONE);
PIN->rone_es = 1./PIN->one_es;
@@ -586,38 +592,28 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
/* longitude center for wrapping */
PIN->is_long_wrap_set = pj_param(ctx, start, "tlon_wrap").i;
- if (PIN->is_long_wrap_set)
- {
+ if (PIN->is_long_wrap_set) {
PIN->long_wrap_center = pj_param(ctx, start, "rlon_wrap").f;
/* Don't accept excessive values otherwise we might perform badly */
/* when correcting longitudes around it */
/* The test is written this way to error on long_wrap_center "=" NaN */
if( !(fabs(PIN->long_wrap_center) < 10 * M_TWOPI) )
- {
- pj_ctx_set_errno( ctx, -14 );
- goto bum_call;
- }
+ return pj_default_destructor (PIN, PJD_ERR_LAT_OR_LON_EXCEED_LIMIT);
}
-
+
/* axis orientation */
if( (pj_param(ctx, start,"saxis").s) != NULL )
{
static const char *axis_legal = "ewnsud";
const char *axis_arg = pj_param(ctx, start,"saxis").s;
if( strlen(axis_arg) != 3 )
- {
- pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
- goto bum_call;
- }
+ return pj_default_destructor (PIN, PJD_ERR_AXIS);
if( strchr( axis_legal, axis_arg[0] ) == NULL
|| strchr( axis_legal, axis_arg[1] ) == NULL
|| strchr( axis_legal, axis_arg[2] ) == NULL)
- {
- pj_ctx_set_errno( ctx, PJD_ERR_AXIS );
- goto bum_call;
- }
-
+ return pj_default_destructor (PIN, PJD_ERR_AXIS);
+
/* it would be nice to validate we don't have on axis repeated */
strcpy( PIN->axis, axis_arg );
}
@@ -631,6 +627,8 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
/* false easting and northing */
PIN->x0 = pj_param(ctx, start, "dx_0").f;
PIN->y0 = pj_param(ctx, start, "dy_0").f;
+ PIN->z0 = pj_param(ctx, start, "dz_0").f;
+ PIN->t0 = pj_param(ctx, start, "dt_0").f;
/* general scaling factor */
if (pj_param(ctx, start, "tk_0").i)
@@ -639,26 +637,23 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
PIN->k0 = pj_param(ctx, start, "dk").f;
else
PIN->k0 = 1.;
- if (PIN->k0 <= 0.) {
- pj_ctx_set_errno( ctx, -31 );
- goto bum_call;
- }
+ if (PIN->k0 <= 0.)
+ return pj_default_destructor (PIN, PJD_ERR_K_LESS_THAN_ZERO);
/* set units */
s = 0;
if ((name = pj_param(ctx, start, "sunits").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; }
+ if (!s)
+ return pj_default_destructor (PIN, PJD_ERR_UNKNOW_UNIT_ID);
s = pj_units[i].to_meter;
}
if (s || (s = pj_param(ctx, start, "sto_meter").s)) {
PIN->to_meter = pj_strtod(s, &s);
if (*s == '/') /* ratio number */
PIN->to_meter /= pj_strtod(++s, 0);
- if (PIN->to_meter <= 0.0) {
- pj_ctx_set_errno( ctx, -51);
- goto bum_call;
- }
+ if (PIN->to_meter <= 0.0)
+ return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
PIN->fr_meter = 1. / PIN->to_meter;
} else
PIN->to_meter = PIN->fr_meter = 1.;
@@ -667,17 +662,16 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
s = 0;
if ((name = pj_param(ctx, start, "svunits").s) != NULL) {
for (i = 0; (s = pj_units[i].id) && strcmp(name, s) ; ++i) ;
- if (!s) { pj_ctx_set_errno( ctx, -7 ); goto bum_call; }
+ if (!s)
+ return pj_default_destructor (PIN, PJD_ERR_UNKNOW_UNIT_ID);
s = pj_units[i].to_meter;
}
if (s || (s = pj_param(ctx, start, "svto_meter").s)) {
PIN->vto_meter = pj_strtod(s, &s);
if (*s == '/') /* ratio number */
PIN->vto_meter /= pj_strtod(++s, 0);
- if (PIN->vto_meter <= 0.0) {
- pj_ctx_set_errno( ctx, -51);
- goto bum_call;
- }
+ if (PIN->vto_meter <= 0.0)
+ return pj_default_destructor (PIN, PJD_ERR_UNIT_FACTOR_LESS_THAN_0);
PIN->vfr_meter = 1. / PIN->vto_meter;
} else {
PIN->vto_meter = PIN->to_meter;
@@ -704,7 +698,8 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
&& *next_str == '\0' )
value = name;
- if (!value) { pj_ctx_set_errno( ctx, -46 ); goto bum_call; }
+ if (!value)
+ return pj_default_destructor (PIN, PJD_ERR_UNKNOWN_PRIME_MERIDIAN);
PIN->from_greenwich = dmstor_ctx(ctx,value,NULL);
}
else
@@ -712,55 +707,15 @@ pj_init_ctx(projCtx ctx, int argc, char **argv) {
/* Private object for the geodesic functions */
PIN->geod = pj_calloc (1, sizeof (struct geod_geodesic));
- if (0!=PIN->geod)
- geod_init(PIN->geod, PIN->a, (1 - sqrt (1 - PIN->es)));
+ if (0==PIN->geod)
+ return pj_default_destructor (PIN, ENOMEM);
+ geod_init(PIN->geod, PIN->a, (1 - sqrt (1 - PIN->es)));
/* projection specific initialization */
- {
- /* Backup those variables so that we can clean them in case
- * (*proj)(PIN) fails */
- void* gridlist = PIN->gridlist;
- void* vgridlist_geoid = PIN->vgridlist_geoid;
- void* catalog_name = PIN->catalog_name;
- void* geod = PIN->geod;
- if (!(PIN = (*proj)(PIN)) || ctx->last_errno) {
- if (PIN)
- pj_free(PIN);
- else {
- for ( ; start; start = curr) {
- curr = start->next;
- pj_dalloc(start);
- }
- if( gridlist )
- pj_dalloc( gridlist );
- if( vgridlist_geoid )
- pj_dalloc( vgridlist_geoid );
- if( catalog_name )
- pj_dalloc( catalog_name );
- if( geod )
- pj_dalloc( geod );
- }
- PIN = 0;
- }
- }
-
- return PIN;
-
-bum_call: /* cleanup error return */
- {
- if (PIN)
- {
- pj_free(PIN);
- }
- else {
- for ( ; start; start = curr) {
- curr = start->next;
- pj_dalloc(start);
- }
- }
+ PIN = proj(PIN);
+ if ((0==PIN) || ctx->last_errno)
return 0;
- }
-
+ return PIN;
}
/************************************************************************/
@@ -769,65 +724,17 @@ bum_call: /* cleanup error return */
/* This is the application callable entry point for destroying */
/* a projection definition. It does work generic to all */
/* projection types, and then calls the projection specific */
-/* free function (P->pfree()) to do local work. This maps to */
-/* the FREEUP code in the individual projection source files. */
+/* free function (P->pfree()) to do local work. In most cases */
+/* P->pfree()==pj_default_destructor. */
/************************************************************************/
-void
-pj_free(PJ *P) {
- if (P) {
- paralist *t, *n;
-
- /* free parameter list elements */
- for (t = P->params; t; t = n) {
- n = t->next;
- pj_dalloc(t);
- }
-
- /* free array of grid pointers if we have one */
- if( P->gridlist != NULL )
- pj_dalloc( P->gridlist );
-
- if( P->vgridlist_geoid != NULL )
- pj_dalloc( P->vgridlist_geoid );
-
- if( P->catalog_name != NULL )
- pj_dalloc( P->catalog_name );
-
- /* We used to call pj_dalloc( 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(); */
- /* TODO: we should probably have a public pj_cleanup() method to do all */
- /* that */
-
- if( P->geod != NULL )
- pj_dalloc( P->geod );
-
- /* free projection parameters */
- P->pfree(P);
- }
-}
-
-
-
-
-
-
-
-
-/************************************************************************/
-/* pj_prepare() */
-/* */
-/* Helper function for the PJ_xxxx functions providing the */
-/* projection specific setup for each projection type. */
-/* */
-/* Currently not used, but placed here as part of the material */
-/* Demonstrating the idea for a future PJ_xxx architecture */
-/* (cf. pj_minimal.c) */
-/* */
-/************************************************************************/
-void pj_prepare (PJ *P, const char *description, void (*freeup)(struct PJconsts *), size_t sizeof_struct_opaque) {
- P->descr = description;
- P->pfree = freeup;
- P->opaque = pj_calloc (1, sizeof_struct_opaque);
+void pj_free(PJ *P) {
+ if (0==P)
+ return;
+ /* free projection parameters - all the hard work is done by */
+ /* pj_default_destructor (in pj_malloc.c), 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, 0);
}
diff --git a/src/pj_inv.c b/src/pj_inv.c
index 55fc917f..68a5595b 100644
--- a/src/pj_inv.c
+++ b/src/pj_inv.c
@@ -42,7 +42,7 @@ LP pj_inv(XY xy, PJ *P) {
if (P->ctx->last_errno)
return err;
- if ((P->left==PJ_IO_UNITS_CLASSIC)||(P->left==PJ_IO_UNITS_RADIANS)) {
+ if (P->left==PJ_IO_UNITS_RADIANS) {
/* reduce from del lp.lam */
lp.lam += P->lam0;
diff --git a/src/pj_inv3d.c b/src/pj_inv3d.c
index a01cfa7e..53e39a76 100644
--- a/src/pj_inv3d.c
+++ b/src/pj_inv3d.c
@@ -42,7 +42,7 @@ LPZ pj_inv3d (XYZ xyz, PJ *P) {
if (P->ctx->last_errno)
return err;
- if ((P->left==PJ_IO_UNITS_CLASSIC)||(P->left==PJ_IO_UNITS_RADIANS)) {
+ if (P->left==PJ_IO_UNITS_RADIANS) {
/* reduce from del lp.lam */
lpz.lam += P->lam0;
diff --git a/src/pj_malloc.c b/src/pj_malloc.c
index 330b14a6..4e465c46 100644
--- a/src/pj_malloc.c
+++ b/src/pj_malloc.c
@@ -40,7 +40,7 @@
** projection system memory allocation/deallocation call with custom
** application procedures. */
-#include <projects.h>
+#include "projects.h"
#include <errno.h>
/**********************************************************************/
@@ -52,30 +52,43 @@ 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.
-***********************************************************************/
- int old_errno = errno;
- void *res = malloc(size);
- if ( res && !old_errno )
- errno = 0;
- return res;
-}
-/**********************************************************************/
-void pj_dalloc(void *ptr) {
-/**********************************************************************/
- free(ptr);
+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 (0==res)
@@ -86,9 +99,15 @@ The array is initialized to zeros.
/**********************************************************************/
+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:
@@ -113,64 +132,59 @@ pointer" to signal an error in a multi level allocation:
+/*****************************************************************************/
+void *pj_dealloc_params (projCtx ctx, paralist *start, int errlev) {
+/*****************************************************************************
+ Companion to pj_default_destructor (below). Deallocates a linked list
+ of "+proj=xxx" initialization parameters.
+
+ Also called from pj_init_ctx when encountering errors before the PJ
+ proper is allocated.
+******************************************************************************/
+ paralist *t, *n;
+ for (t = start; t; t = n) {
+ n = t->next;
+ pj_dealloc(t);
+ }
+ pj_ctx_set_errno (ctx, errlev);
+ return (void *) 0;
+}
+
/*****************************************************************************/
-static void *pj_freeup_msg_plain (PJ *P, int errlev) { /* Destructor */
+void *pj_default_destructor (PJ *P, int errlev) { /* Destructor */
/*****************************************************************************
Does memory deallocation for "plain" PJ objects, i.e. that vast majority
of PJs where the opaque object does not contain any additionally
- allocated memory.
+ allocated memory below the P->opaque level.
******************************************************************************/
- if (0==P)
- return 0;
+ /* Even if P==0, we set the errlev on pj_error and the default context */
+ /* Note that both, in the multithreaded case, may then contain undefined */
+ /* values. This is expected behaviour. For MT have one ctx per thread */
if (0!=errlev)
- pj_ctx_set_errno (P->ctx, errlev);
+ pj_ctx_set_errno (pj_get_ctx(P), errlev);
- if (0==P->opaque)
- return pj_dealloc (P);
+ if (0==P)
+ return 0;
+
+ /* free grid lists */
+ pj_dealloc( P->gridlist );
+ pj_dealloc( P->vgridlist_geoid );
+ pj_dealloc( P->catalog_name );
+
+ /* We used to call pj_dalloc( 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(); */
+ /* 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 parameter list elements */
+ pj_dealloc_params (pj_get_ctx(P), P->params, errlev);
pj_dealloc (P->opaque);
return pj_dealloc(P);
}
-
-
-/*****************************************************************************/
-void pj_freeup_plain (PJ *P) {
-/*****************************************************************************
- Adapts pj_freeup_msg_plain to the format defined for the callback in
- the PJ object.
-
- i.e. reduces most instances of projection deallocation code to:
-
- static void freeup (PJ *P) {
- pj_freeup_plain (P);
- return;
- }
-
- rather than:
-
- static void *freeup_msg_add (PJ *P, int errlev) {
- if (0==P)
- return 0;
- pj_ctx_set_errno (P->ctx, errlev);
-
- if (0==P->opaque)
- return pj_dealloc (P);
-
- (* projection specific deallocation goes here *)
-
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
- }
-
- (* Adapts pipeline_freeup to the format defined for the PJ object *)
- static void freeup_msg_add (PJ *P) {
- freeup_new_add (P, 0);
- return;
- }
-
- ******************************************************************************/
- pj_freeup_msg_plain (P, 0);
- return;
- }
diff --git a/src/pj_mlfn.c b/src/pj_mlfn.c
index 2b823026..e00f2bf1 100644
--- a/src/pj_mlfn.c
+++ b/src/pj_mlfn.c
@@ -19,19 +19,23 @@
#define EPS 1e-11
#define MAX_ITER 10
#define EN_SIZE 5
- double *
-pj_enfn(double es) {
- double t, *en;
- if ((en = (double *)pj_malloc(EN_SIZE * sizeof(double))) != NULL) {
- en[0] = C00 - es * (C02 + es * (C04 + es * (C06 + es * C08)));
- en[1] = es * (C22 - es * (C04 + es * (C06 + es * C08)));
- en[2] = (t = es * es) * (C44 - es * (C46 + es * C48));
- en[3] = (t *= es) * (C66 - es * C68);
- en[4] = t * es * C88;
- } /* else return NULL if unable to allocate memory */
- return en;
+double *pj_enfn(double es) {
+ double t, *en;
+
+ en = (double *) pj_malloc(EN_SIZE * sizeof (double));
+ if (0==en)
+ return 0;
+
+ en[0] = C00 - es * (C02 + es * (C04 + es * (C06 + es * C08)));
+ en[1] = es * (C22 - es * (C04 + es * (C06 + es * C08)));
+ en[2] = (t = es * es) * (C44 - es * (C46 + es * C48));
+ en[3] = (t *= es) * (C66 - es * C68);
+ en[4] = t * es * C88;
+
+ return en;
}
+
double
pj_mlfn(double phi, double sphi, double cphi, double *en) {
cphi *= sphi;
diff --git a/src/pj_obs_api.c b/src/pj_obs_api.c
index b2929a07..9f699fcf 100644
--- a/src/pj_obs_api.c
+++ b/src/pj_obs_api.c
@@ -12,7 +12,7 @@
* Author: Thomas Knudsen, thokn@sdfe.dk, 2016-06-09/2016-11-06
*
******************************************************************************
- * Copyright (c) 2016, Thomas Knudsen/SDFE
+ * Copyright (c) 2016, 2017 Thomas Knudsen/SDFE
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -36,7 +36,7 @@
#include <proj.h>
#include "proj_internal.h"
#include "projects.h"
-#include <geodesic.h>
+#include "geodesic.h"
#include <stddef.h>
#include <errno.h>
@@ -69,8 +69,8 @@ PJ_OBS proj_obs (double x, double y, double z, double t, double o, double p, dou
-/* Geodesic distance between two points with angular 2D coordinates */
-double proj_lp_dist (PJ *P, LP a, LP b) {
+/* Geodesic distance (in meter) between two points with angular 2D coordinates */
+double proj_lp_dist (const PJ *P, LP a, LP b) {
double s12, azi1, azi2;
/* Note: the geodesic code takes arguments in degrees */
geod_inverse (P->geod, PJ_TODEG(a.phi), PJ_TODEG(a.lam), PJ_TODEG(b.phi), PJ_TODEG(b.lam), &s12, &azi1, &azi2);
@@ -90,9 +90,10 @@ double proj_xyz_dist (XYZ a, XYZ b) {
/* Measure numerical deviation after n roundtrips fwd-inv (or inv-fwd) */
-double proj_roundtrip (PJ *P, enum proj_direction direction, int n, PJ_OBS obs) {
+double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD coo) {
int i;
- PJ_OBS o, u;
+ PJ_COORD o, u;
+ enum pj_io_units unit;
if (0==P)
return HUGE_VAL;
@@ -102,30 +103,48 @@ double proj_roundtrip (PJ *P, enum proj_direction direction, int n, PJ_OBS obs)
return HUGE_VAL;
}
- o.coo = obs.coo;
-
- for (i = 0; i < n; i++) {
- switch (direction) {
- case PJ_FWD:
- u = pj_fwdobs (o, P);
- o = pj_invobs (u, P);
- break;
- case PJ_INV:
- u = pj_invobs (o, P);
- o = pj_fwdobs (u, P);
- break;
- default:
- proj_errno_set (P, EINVAL);
- return HUGE_VAL;
- }
+ o = coo;
+
+ switch (direction) {
+ case PJ_FWD:
+ for (i = 0; i < n; i++) {
+ u = pj_fwdcoord (o, P);
+ o = pj_invcoord (u, P);
+ }
+ break;
+ case PJ_INV:
+ for (i = 0; i < n; i++) {
+ u = pj_invcoord (o, P);
+ o = pj_fwdcoord (u, P);
+ }
+ break;
+ default:
+ proj_errno_set (P, EINVAL);
+ return HUGE_VAL;
}
- return proj_xyz_dist (o.coo.xyz, obs.coo.xyz);
+ /* left when forward, because we do a roundtrip, and end where we begin */
+ unit = direction==PJ_FWD? P->left: P->right;
+ if (unit==PJ_IO_UNITS_RADIANS)
+ return hypot (proj_lp_dist (P, coo.lp, o.lp), coo.lpz.z - o.lpz.z);
+
+ return proj_xyz_dist (coo.xyz, coo.xyz);
}
+
+
+
+
+
+
+
+
+
+
+
/* Apply the transformation P to the coordinate coo */
-PJ_OBS proj_trans_obs (PJ *P, enum proj_direction direction, PJ_OBS obs) {
+PJ_OBS proj_trans_obs (PJ *P, PJ_DIRECTION direction, PJ_OBS obs) {
if (0==P)
return obs;
@@ -147,7 +166,7 @@ PJ_OBS proj_trans_obs (PJ *P, enum proj_direction direction, PJ_OBS obs) {
/* Apply the transformation P to the coordinate coo */
-PJ_COORD proj_trans_coord (PJ *P, enum proj_direction direction, PJ_COORD coo) {
+PJ_COORD proj_trans_coord (PJ *P, PJ_DIRECTION direction, PJ_COORD coo) {
if (0==P)
return coo;
@@ -171,7 +190,7 @@ PJ_COORD proj_trans_coord (PJ *P, enum proj_direction direction, PJ_COORD coo) {
/*************************************************************************************/
size_t proj_transform (
PJ *P,
- enum proj_direction direction,
+ PJ_DIRECTION direction,
double *x, size_t sx, size_t nx,
double *y, size_t sy, size_t ny,
double *z, size_t sz, size_t nz,
@@ -319,7 +338,7 @@ size_t proj_transform (
}
/*****************************************************************************/
-int proj_transform_obs (PJ *P, enum proj_direction direction, size_t n, PJ_OBS *obs) {
+int proj_transform_obs (PJ *P, PJ_DIRECTION direction, size_t n, PJ_OBS *obs) {
/******************************************************************************
Batch transform an array of PJ_OBS.
@@ -337,7 +356,7 @@ int proj_transform_obs (PJ *P, enum proj_direction direction, size_t n, PJ_OBS *
}
/*****************************************************************************/
-int proj_transform_coord (PJ *P, enum proj_direction direction, size_t n, PJ_COORD *coord) {
+int proj_transform_coord (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord) {
/******************************************************************************
Batch transform an array of PJ_COORD.
@@ -407,34 +426,20 @@ PJ *proj_destroy (PJ *P) {
return 0;
}
-/* For now, if PJ itself is clean, we return the thread local error level. */
-/* This may change as OBS_API error reporting matures */
int proj_errno (PJ *P) {
- if (0==P)
- return pj_ctx_get_errno (pj_get_default_ctx ());
- if (0 != P->last_errno)
- return P->last_errno;
return pj_ctx_get_errno (pj_get_ctx (P));
}
/*****************************************************************************/
void proj_errno_set (PJ *P, int err) {
/******************************************************************************
- Sets errno in the PJ, and bubbles it up to the context and pj_errno levels
- through the low level pj_ctx interface.
+ Sets errno at the context and bubble it up to the thread local errno
******************************************************************************/
- if (0==P) {
- errno = EINVAL;
- return;
- }
-
/* Use proj_errno_reset to explicitly clear the error status */
if (0==err)
return;
- /* set local error level */
- P->last_errno = err;
- /* and let it bubble up */
+ /* For P==0 err goes to the default context */
proj_context_errno_set (pj_get_ctx (P), err);
errno = err;
return;
@@ -454,14 +459,16 @@ void proj_errno_restore (PJ *P, int err) {
See usage example under proj_errno_reset ()
******************************************************************************/
+ if (0==err)
+ return;
proj_errno_set (P, err);
}
/*****************************************************************************/
int proj_errno_reset (PJ *P) {
/******************************************************************************
- Clears errno in the PJ, and bubbles it up to the context and
- pj_errno levels through the low level pj_ctx interface.
+ Clears errno in the context and thread local levels
+ through the low level pj_ctx interface.
Returns the previous value of the errno, for convenient reset/restore
operations:
@@ -471,24 +478,17 @@ int proj_errno_reset (PJ *P) {
do_something_with_P (P);
- (* failure - keep latest error status *)
+ // failure - keep latest error status
if (proj_errno(P))
return;
- (* success - restore previous error status *)
+ // success - restore previous error status
proj_errno_restore (P, last_errno);
return;
}
******************************************************************************/
int last_errno;
- if (0==P) {
- errno = EINVAL;
- return EINVAL;
- }
last_errno = proj_errno (P);
- /* set local error level */
- P->last_errno = 0;
- /* and let it bubble up */
pj_ctx_set_errno (pj_get_ctx (P), 0);
errno = 0;
return last_errno;
@@ -501,15 +501,16 @@ PJ_CONTEXT *proj_context_create (void) {
}
-void proj_context_destroy (PJ_CONTEXT *ctx) {
+PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx) {
if (0==ctx)
- return;
+ return 0;
/* Trying to free the default context is a no-op (since it is statically allocated) */
if (pj_get_default_ctx ()==ctx)
- return;
+ return 0;
pj_ctx_free (ctx);
+ return 0;
}
@@ -582,7 +583,7 @@ PJ_INFO proj_info(void) {
/*****************************************************************************/
-PJ_PROJ_INFO proj_pj_info(const PJ *P) {
+PJ_PROJ_INFO proj_pj_info(PJ *P) {
/******************************************************************************
Basic info about a particular instance of a projection object.
@@ -594,6 +595,11 @@ PJ_PROJ_INFO proj_pj_info(const PJ *P) {
memset(&info, 0, sizeof(PJ_PROJ_INFO));
+ /* Expected accuracy of the transformation. Hardcoded for now, will be improved */
+ /* later. Most likely to be used when a transformation is set up with */
+ /* proj_create_crs_to_crs in a future version that leverages the EPSG database. */
+ info.accuracy = -1.0;
+
if (!P) {
return info;
}
@@ -606,7 +612,7 @@ PJ_PROJ_INFO proj_pj_info(const PJ *P) {
pj_strlcpy(info.description, P->descr, sizeof(info.description));
/* projection definition */
- def = pj_get_def((PJ *)P, 0); /* pj_get_def takes a non-const PJ pointer */
+ def = pj_get_def(P, 0); /* pj_get_def takes a non-const PJ pointer */
pj_strlcpy(info.definition, &def[1], sizeof(info.definition)); /* def includes a leading space */
pj_dealloc(def);
@@ -729,7 +735,7 @@ PJ_INIT_INFO proj_init_info(const char *initname){
/*****************************************************************************/
-PJ_DERIVS proj_derivatives(const PJ *P, const LP lp) {
+PJ_DERIVS proj_derivatives(PJ *P, const LP lp) {
/******************************************************************************
Derivatives of coordinates.
@@ -739,8 +745,7 @@ PJ_DERIVS proj_derivatives(const PJ *P, const LP lp) {
******************************************************************************/
PJ_DERIVS derivs;
- /* casting to struct DERIVS for compatibility reasons */
- if (pj_deriv(lp, 1e-5, (PJ *)P, (struct DERIVS *)&derivs)) {
+ if (pj_deriv(lp, 1e-5, P, &derivs)) {
/* errno set in pj_derivs */
memset(&derivs, 0, sizeof(PJ_DERIVS));
}
@@ -750,7 +755,7 @@ PJ_DERIVS proj_derivatives(const PJ *P, const LP lp) {
/*****************************************************************************/
-PJ_FACTORS proj_factors(const PJ *P, const LP lp) {
+PJ_FACTORS proj_factors(PJ *P, const LP lp) {
/******************************************************************************
Cartographic characteristics at point lp.
@@ -766,8 +771,7 @@ PJ_FACTORS proj_factors(const PJ *P, const LP lp) {
/* pj_factors rely code being zero */
factors.code = 0;
- /* casting to struct FACTORS for compatibility reasons */
- if (pj_factors(lp, (PJ *)P, 0.0, (struct FACTORS *)&factors)) {
+ if (pj_factors(lp, P, 0.0, &factors)) {
/* errno set in pj_factors */
memset(&factors, 0, sizeof(PJ_FACTORS));
}
@@ -776,6 +780,22 @@ PJ_FACTORS proj_factors(const PJ *P, const LP lp) {
}
+const PJ_ELLPS *proj_list_ellps(void) {
+ return pj_get_ellps_ref();
+}
+
+const PJ_UNITS *proj_list_units(void) {
+ return pj_get_units_ref();
+}
+
+const PJ_OPERATIONS *proj_list_operations(void) {
+ return pj_get_list_ref();
+}
+
+const PJ_PRIME_MERIDIANS *proj_list_prime_meridians(void) {
+ return pj_get_prime_meridians_ref();
+}
+
double proj_torad (double angle_in_degrees) { return PJ_TORAD (angle_in_degrees);}
double proj_todeg (double angle_in_radians) { return PJ_TODEG (angle_in_radians);}
@@ -787,5 +807,3 @@ double proj_dmstor(const char *is, char **rs) {
char* proj_rtodms(char *s, double r, int pos, int neg) {
return rtodms(s, r, pos, neg);
}
-
-
diff --git a/src/pj_run_selftests.c b/src/pj_run_selftests.c
index 87aee76d..90193af8 100644
--- a/src/pj_run_selftests.c
+++ b/src/pj_run_selftests.c
@@ -40,7 +40,8 @@ int pj_run_selftests (int verbosity) {
static void run_one_test (const char *mnemonic, int (testfunc)(void), int verbosity, int *n_ok, int *n_ko, int *n_stubs) {
- int ret = testfunc ();
+ int ret;
+ ret = testfunc ();
switch (ret) {
case 0: (*n_ok)++; break;
case 10000: (*n_stubs)++; break;
diff --git a/src/pj_strerrno.c b/src/pj_strerrno.c
index 74a7eea0..89a5a025 100644
--- a/src/pj_strerrno.c
+++ b/src/pj_strerrno.c
@@ -61,30 +61,36 @@ pj_err_list[] = {
"non-convergent computation", /* -53 */
"missing required arguments", /* -54 */
"lat_0 = 0", /* -55 */
+ "ellipsoidal usage unsupported", /* -56 */
+
+ /* When adding error messages, remember to update ID defines in
+ projects.h, and transient_error array in pj_transform */
};
char *pj_strerrno(int err) {
static char note[50];
+ size_t adjusted_err;
if (0==err)
return 0;
+ /* System error codes are positive */
if (err > 0) {
#ifdef HAVE_STRERROR
return strerror(err);
#else
- sprintf(note,"no system list, errno: %d\n", err);
+ /* Defend string boundary against exorbitantly large err values */
+ /* which may occur on platforms with 64-bit ints */
+ sprintf(note,"no system list, errno: %d\n", (err < 9999)? err: 9999);
return note;
#endif
}
- else /*if (err < 0)*/ {
- size_t adjusted_err = - err - 1;
- if (adjusted_err < (sizeof(pj_err_list) / sizeof(char *)))
- return(pj_err_list[adjusted_err]);
- else {
- sprintf( note, "invalid projection system error (%d)", err );
- return note;
- }
- }
+ /* PROJ.4 error codes are negative */
+ adjusted_err = - err - 1;
+ if (adjusted_err < (sizeof(pj_err_list) / sizeof(char *)))
+ return(pj_err_list[adjusted_err]);
+
+ sprintf( note, "invalid projection system error (%d)", (err > -9999)? err: -9999);
+ return note;
}
diff --git a/src/pj_transform.c b/src/pj_transform.c
index a842ba72..9f532188 100644
--- a/src/pj_transform.c
+++ b/src/pj_transform.c
@@ -54,22 +54,32 @@ static int pj_adjust_axis( projCtx ctx, const char *axis, int denormalize_flag,
/*
** This table is intended to indicate for any given error code in
-** the range 0 to -44, whether that error will occur for all locations (ie.
+** the range 0 to -56, 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[50] = {
+static const int transient_error[60] = {
/* 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 };
+ /* 40 to 49 */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ /* 50 to 59 */ 1, 0, 1, 0, 1, 1, 1, 0, 0, 0 };
/************************************************************************/
/* pj_transform() */
diff --git a/src/proj.c b/src/proj.c
index 67d60f21..049593c9 100644
--- a/src/proj.c
+++ b/src/proj.c
@@ -21,243 +21,288 @@
extern void gen_cheb(int, projUV(*)(projUV), char *, PJ *, int, char **);
+static PJ *Proj;
+static projUV (*proj)(projUV, PJ *);
- static PJ
-*Proj;
- static projUV
-(*proj)(projUV, PJ *);
- static int
-reversein = 0, /* != 0 reverse input arguments */
-reverseout = 0, /* != 0 reverse output arguments */
-bin_in = 0, /* != 0 then binary input */
-bin_out = 0, /* != 0 then binary output */
-echoin = 0, /* echo input data to output line */
-tag = '#', /* beginning of line tag character */
-inverse = 0, /* != 0 then inverse projection */
-prescale = 0, /* != 0 apply cartesian scale factor */
-dofactors = 0, /* determine scale factors */
-facs_bad = 0, /* return condition from pj_factors */
-very_verby = 0, /* very verbose mode */
-postscale = 0;
- static char
-*cheby_str, /* string controlling Chebychev evaluation */
-*oform = (char *)0, /* output format for x-y or decimal degrees */
-*oterr = "*\t*", /* output line for unprojectable input */
-*usage =
-"%s\nusage: %s [ -bCeEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n";
- static struct FACTORS
-facs;
- static double
-(*informat)(const char *, char **), /* input data deformatter function */
-fscale = 0.; /* cartesian scale factor */
- static projUV
-int_proj(projUV data) {
- if (prescale) { data.u *= fscale; data.v *= fscale; }
- data = (*proj)(data, Proj);
- if (postscale && data.u != HUGE_VAL)
- { data.u *= fscale; data.v *= fscale; }
- return(data);
+static int
+ reversein = 0, /* != 0 reverse input arguments */
+ reverseout = 0, /* != 0 reverse output arguments */
+ bin_in = 0, /* != 0 then binary input */
+ bin_out = 0, /* != 0 then binary output */
+ echoin = 0, /* echo input data to output line */
+ tag = '#', /* beginning of line tag character */
+ inverse = 0, /* != 0 then inverse projection */
+ prescale = 0, /* != 0 apply cartesian scale factor */
+ dofactors = 0, /* determine scale factors */
+ facs_bad = 0, /* return condition from pj_factors */
+ very_verby = 0, /* very verbose mode */
+ postscale = 0;
+
+static char
+ *cheby_str, /* string controlling Chebychev evaluation */
+ *oform = (char *)0, /* output format for x-y or decimal degrees */
+ *oterr = "*\t*", /* output line for unprojectable input */
+ *usage = "%s\nusage: %s [ -bCeEfiIlormsStTvVwW [args] ] [ +opts[=arg] ] [ files ]\n";
+
+static struct FACTORS facs;
+
+static double (*informat)(const char *, char **), /* input data deformatter function */
+ fscale = 0.; /* cartesian scale factor */
+
+static projUV int_proj(projUV data) {
+ if (prescale) {
+ data.u *= fscale;
+ data.v *= fscale;
+ }
+
+ data = (*proj)(data, Proj);
+
+ if (postscale && data.u != HUGE_VAL) {
+ data.u *= fscale;
+ data.v *= fscale;
+ }
+
+ return data;
}
- static void /* file processing function */
-process(FILE *fid) {
- char line[MAX_LINE+3], *s = 0, pline[40];
- projUV data;
-
- for (;;) {
- ++emess_dat.File_line;
- if (bin_in) { /* binary input */
- if (fread(&data, sizeof(projUV), 1, fid) != 1)
- break;
- } else { /* ascii input */
- if (!(s = fgets(line, MAX_LINE, fid)))
- break;
- if (!strchr(s, '\n')) { /* overlong line */
- int c;
- (void)strcat(s, "\n");
- /* gobble up to newline */
- while ((c = fgetc(fid)) != EOF && c != '\n') ;
- }
- if (*s == tag) {
- if (!bin_out)
- (void)fputs(line, stdout);
- continue;
- }
- if (reversein) {
- data.v = (*informat)(s, &s);
- data.u = (*informat)(s, &s);
- } else {
- data.u = (*informat)(s, &s);
- data.v = (*informat)(s, &s);
- }
- if (data.v == HUGE_VAL)
- data.u = HUGE_VAL;
- if (!*s && (s > line)) --s; /* assumed we gobbled \n */
- if (!bin_out && echoin) {
- char t;
- t = *s;
- *s = '\0';
- (void)fputs(line, stdout);
- *s = t;
- putchar('\t');
- }
- }
- if (data.u != HUGE_VAL) {
- if (prescale) { data.u *= fscale; data.v *= fscale; }
- if (dofactors && !inverse)
- facs_bad = pj_factors(data, Proj, 0., &facs);
- data = (*proj)(data, Proj);
- if (dofactors && inverse)
- facs_bad = pj_factors(data, Proj, 0., &facs);
- if (postscale && data.u != HUGE_VAL)
- { data.u *= fscale; data.v *= fscale; }
- }
- if (bin_out) { /* binary output */
- (void)fwrite(&data, sizeof(projUV), 1, stdout);
- continue;
- } else if (data.u == HUGE_VAL) /* error output */
- (void)fputs(oterr, stdout);
- else if (inverse && !oform) { /*ascii DMS output */
- if (reverseout) {
- (void)fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
- putchar('\t');
- (void)fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
- } else {
- (void)fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
- putchar('\t');
- (void)fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
- }
- } else { /* x-y or decimal degree ascii output */
- if (inverse) {
- data.v *= RAD_TO_DEG;
- data.u *= RAD_TO_DEG;
- }
- if (reverseout) {
- (void)printf(oform,data.v); putchar('\t');
- (void)printf(oform,data.u);
- } else {
- (void)printf(oform,data.u); putchar('\t');
- (void)printf(oform,data.v);
- }
- }
- if (dofactors) /* print scale factor data */
- {
- if (!facs_bad)
- (void)printf("\t<%g %g %g %g %g %g>",
- facs.h, facs.k, facs.s,
- facs.omega * RAD_TO_DEG, facs.a, facs.b);
- else
- (void)fputs("\t<* * * * * *>", stdout);
+
+/* file processing function */
+static void process(FILE *fid) {
+ char line[MAX_LINE+3], *s = 0, pline[40];
+ projUV data;
+
+ for (;;) {
+ ++emess_dat.File_line;
+
+ if (bin_in) { /* binary input */
+ if (fread(&data, sizeof(projUV), 1, fid) != 1)
+ break;
+ } else { /* ascii input */
+ if (!(s = fgets(line, MAX_LINE, fid)))
+ break;
+
+ if (!strchr(s, '\n')) { /* overlong line */
+ int c;
+ (void)strcat(s, "\n");
+ /* gobble up to newline */
+ while ((c = fgetc(fid)) != EOF && c != '\n') ;
+ }
+
+ if (*s == tag) {
+ if (!bin_out)
+ (void)fputs(line, stdout);
+ continue;
+ }
+
+ if (reversein) {
+ data.v = (*informat)(s, &s);
+ data.u = (*informat)(s, &s);
+ } else {
+ data.u = (*informat)(s, &s);
+ data.v = (*informat)(s, &s);
+ }
+
+ if (data.v == HUGE_VAL)
+ data.u = HUGE_VAL;
+
+ if (!*s && (s > line)) --s; /* assumed we gobbled \n */
+ if (!bin_out && echoin) {
+ char t;
+ t = *s;
+ *s = '\0';
+ (void)fputs(line, stdout);
+ *s = t;
+ putchar('\t');
+ }
+ }
+
+ if (data.u != HUGE_VAL) {
+ if (prescale) { data.u *= fscale; data.v *= fscale; }
+ if (dofactors && !inverse)
+ facs_bad = pj_factors(data, Proj, 0., &facs);
+ data = (*proj)(data, Proj);
+
+ if (dofactors && inverse)
+ facs_bad = pj_factors(data, Proj, 0., &facs);
+
+ if (postscale && data.u != HUGE_VAL)
+ { data.u *= fscale; data.v *= fscale; }
+ }
+
+ if (bin_out) { /* binary output */
+ (void)fwrite(&data, sizeof(projUV), 1, stdout);
+ continue;
+ } else if (data.u == HUGE_VAL) /* error output */
+ (void)fputs(oterr, stdout);
+ else if (inverse && !oform) { /*ascii DMS output */
+ if (reverseout) {
+ (void)fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
+ putchar('\t');
+ (void)fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
+ } else {
+ (void)fputs(rtodms(pline, data.u, 'E', 'W'), stdout);
+ putchar('\t');
+ (void)fputs(rtodms(pline, data.v, 'N', 'S'), stdout);
+ }
+ } else { /* x-y or decimal degree ascii output, scale if warranted by output units */
+ if (inverse) {
+ if (Proj->left == PJ_IO_UNITS_RADIANS) {
+ data.v *= RAD_TO_DEG;
+ data.u *= RAD_TO_DEG;
}
- (void)fputs(bin_in ? "\n" : s, stdout);
- }
+ } else {
+ if (Proj->right == PJ_IO_UNITS_RADIANS) {
+ data.v *= RAD_TO_DEG;
+ data.u *= RAD_TO_DEG;
+ }
+ }
+
+ if (reverseout) {
+ (void)printf(oform,data.v); putchar('\t');
+ (void)printf(oform,data.u);
+ } else {
+ (void)printf(oform,data.u); putchar('\t');
+ (void)printf(oform,data.v);
+ }
+ }
+
+ /* print scale factor data */
+ if (dofactors) {
+ if (!facs_bad)
+ (void)printf("\t<%g %g %g %g %g %g>",
+ facs.h, facs.k, facs.s,
+ facs.omega * RAD_TO_DEG, facs.a, facs.b);
+ else
+ (void)fputs("\t<* * * * * *>", stdout);
+ }
+ (void)fputs(bin_in ? "\n" : s, stdout);
+ }
}
- static void /* file processing function --- verbosely */
-vprocess(FILE *fid) {
- char line[MAX_LINE+3], *s, pline[40];
- projUV dat_ll, dat_xy, temp;
- int linvers;
-
- if (!oform)
- oform = "%.3f";
- if (bin_in || bin_out)
- emess(1,"binary I/O not available in -V option");
- for (;;) {
- ++emess_dat.File_line;
- if (!(s = fgets(line, MAX_LINE, fid)))
- break;
- if (!strchr(s, '\n')) { /* overlong line */
- int c;
- (void)strcat(s, "\n");
- /* gobble up to newline */
- while ((c = fgetc(fid)) != EOF && c != '\n') ;
- }
- if (*s == tag) { /* pass on data */
- (void)fputs(s, stdout);
- continue;
- }
- /* check to override default input mode */
- if (*s == 'I' || *s == 'i') {
- linvers = 1;
- ++s;
- } else if (*s == 'I' || *s == 'i') {
- linvers = 0;
- ++s;
- } else
- linvers = inverse;
- if (linvers) {
- if (!PJ_INVERS(Proj)) {
- emess(-1,"inverse for this projection not avail.\n");
- continue;
- }
- dat_xy.u = strtod(s, &s);
- dat_xy.v = strtod(s, &s);
- if (dat_xy.u == HUGE_VAL || dat_xy.v == HUGE_VAL) {
- emess(-1,"lon-lat input conversion failure\n");
- continue;
- }
- if (prescale) { dat_xy.u *= fscale; dat_xy.v *= fscale; }
- if (reversein) {
- temp.u = dat_xy.u;
- temp.v = dat_xy.v;
- dat_xy.u = temp.v;
- dat_xy.v = temp.u;
- }
- dat_ll = pj_inv(dat_xy, Proj);
- } else {
- dat_ll.u = dmstor(s, &s);
- dat_ll.v = dmstor(s, &s);
- if (dat_ll.u == HUGE_VAL || dat_ll.v == HUGE_VAL) {
- emess(-1,"lon-lat input conversion failure\n");
- continue;
- }
- if (reversein) {
- temp.u = dat_ll.u;
- temp.v = dat_ll.v;
- dat_ll.u = temp.v;
- dat_ll.v = temp.u;
- }
- dat_xy = pj_fwd(dat_ll, Proj);
- if (postscale) { dat_xy.u *= fscale; dat_xy.v *= 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()));
- continue;
- }
- if (!*s && (s > line)) --s; /* assumed we gobbled \n */
- if (pj_factors(dat_ll, Proj, 0., &facs)) {
- emess(-1,"failed to compute factors\n\n");
- continue;
- }
- if (*s != '\n')
- (void)fputs(s, stdout);
- (void)fputs("Longitude: ", stdout);
- (void)fputs(rtodms(pline, dat_ll.u, 'E', 'W'), stdout);
- (void)printf(" [ %.11g ]\n", dat_ll.u * RAD_TO_DEG);
- (void)fputs("Latitude: ", stdout);
- (void)fputs(rtodms(pline, dat_ll.v, 'N', 'S'), stdout);
- (void)printf(" [ %.11g ]\n", dat_ll.v * RAD_TO_DEG);
- (void)fputs("Easting (x): ", stdout);
- (void)printf(oform, dat_xy.u); putchar('\n');
- (void)fputs("Northing (y): ", stdout);
- (void)printf(oform, dat_xy.v); putchar('\n');
- (void)printf("Meridian scale (h)%c: %.8f ( %.4g %% error )\n",
- facs.code & IS_ANAL_HK ? '*' : ' ', facs.h, (facs.h-1.)*100.);
- (void)printf("Parallel scale (k)%c: %.8f ( %.4g %% error )\n",
- facs.code & IS_ANAL_HK ? '*' : ' ', facs.k, (facs.k-1.)*100.);
- (void)printf("Areal scale (s): %.8f ( %.4g %% error )\n",
- facs.s, (facs.s-1.)*100.);
- (void)printf("Angular distortion (w): %.3f\n", facs.omega *
- RAD_TO_DEG);
- (void)printf("Meridian/Parallel angle: %.5f\n",
- facs.thetap * RAD_TO_DEG);
- (void)printf("Convergence%c: ",facs.code & IS_ANAL_CONV ? '*' : ' ');
- (void)fputs(rtodms(pline, facs.conv, 0, 0), stdout);
- (void)printf(" [ %.8f ]\n", facs.conv * RAD_TO_DEG);
- (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n",
- facs.a, facs.b);
- }
+
+/* file processing function --- verbosely */
+static void vprocess(FILE *fid) {
+ char line[MAX_LINE+3], *s, pline[40];
+ projUV dat_ll, dat_xy, temp;
+ int linvers;
+
+
+ if (!oform)
+ oform = "%.3f";
+
+ if (bin_in || bin_out)
+ emess(1,"binary I/O not available in -V option");
+
+ for (;;) {
+ ++emess_dat.File_line;
+
+ if (!(s = fgets(line, MAX_LINE, fid)))
+ break;
+
+ if (!strchr(s, '\n')) { /* overlong line */
+ int c;
+ (void)strcat(s, "\n");
+ /* gobble up to newline */
+ while ((c = fgetc(fid)) != EOF && c != '\n') ;
+ }
+
+ if (*s == tag) { /* pass on data */
+ (void)fputs(s, stdout);
+ continue;
+ }
+
+ /* check to override default input mode */
+ if (*s == 'I' || *s == 'i') {
+ linvers = 1;
+ ++s;
+ } else if (*s == 'I' || *s == 'i') {
+ linvers = 0;
+ ++s;
+ } else
+ linvers = inverse;
+
+ if (linvers) {
+ if (!PJ_INVERS(Proj)) {
+ emess(-1,"inverse for this projection not avail.\n");
+ continue;
+ }
+ dat_xy.u = strtod(s, &s);
+ dat_xy.v = strtod(s, &s);
+ if (dat_xy.u == HUGE_VAL || dat_xy.v == HUGE_VAL) {
+ emess(-1,"lon-lat input conversion failure\n");
+ continue;
+ }
+ if (prescale) { dat_xy.u *= fscale; dat_xy.v *= fscale; }
+ if (reversein) {
+ temp.u = dat_xy.u;
+ temp.v = dat_xy.v;
+ dat_xy.u = temp.v;
+ dat_xy.v = temp.u;
+ }
+ dat_ll = pj_inv(dat_xy, Proj);
+ } else {
+ dat_ll.u = dmstor(s, &s);
+ dat_ll.v = dmstor(s, &s);
+ if (dat_ll.u == HUGE_VAL || dat_ll.v == HUGE_VAL) {
+ emess(-1,"lon-lat input conversion failure\n");
+ continue;
+ }
+ if (reversein) {
+ temp.u = dat_ll.u;
+ temp.v = dat_ll.v;
+ dat_ll.u = temp.v;
+ dat_ll.v = temp.u;
+ }
+ dat_xy = pj_fwd(dat_ll, Proj);
+ if (postscale) { dat_xy.u *= fscale; dat_xy.v *= fscale; }
+ }
+
+ /* apply rad->deg scaling in case the output from a pipeline has degrees as units */
+ if (!inverse && Proj->right == PJ_IO_UNITS_RADIANS) {
+ dat_xy.u *= RAD_TO_DEG;
+ dat_xy.v *= RAD_TO_DEG;
+ }
+
+ /* 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()));
+ continue;
+ }
+
+ if (!*s && (s > line)) --s; /* assumed we gobbled \n */
+ if (pj_factors(dat_ll, Proj, 0., &facs)) {
+ emess(-1,"failed to compute factors\n\n");
+ continue;
+ }
+
+ if (*s != '\n')
+ (void)fputs(s, stdout);
+
+ (void)fputs("Longitude: ", stdout);
+ (void)fputs(rtodms(pline, dat_ll.u, 'E', 'W'), stdout);
+ (void)printf(" [ %.11g ]\n", dat_ll.u * RAD_TO_DEG);
+ (void)fputs("Latitude: ", stdout);
+ (void)fputs(rtodms(pline, dat_ll.v, 'N', 'S'), stdout);
+ (void)printf(" [ %.11g ]\n", dat_ll.v * RAD_TO_DEG);
+ (void)fputs("Easting (x): ", stdout);
+ (void)printf(oform, dat_xy.u); putchar('\n');
+ (void)fputs("Northing (y): ", stdout);
+ (void)printf(oform, dat_xy.v); putchar('\n');
+ (void)printf("Meridian scale (h)%c: %.8f ( %.4g %% error )\n",
+ facs.code & IS_ANAL_HK ? '*' : ' ', facs.h, (facs.h-1.)*100.);
+ (void)printf("Parallel scale (k)%c: %.8f ( %.4g %% error )\n",
+ facs.code & IS_ANAL_HK ? '*' : ' ', facs.k, (facs.k-1.)*100.);
+ (void)printf("Areal scale (s): %.8f ( %.4g %% error )\n",
+ facs.s, (facs.s-1.)*100.);
+ (void)printf("Angular distortion (w): %.3f\n", facs.omega *
+ RAD_TO_DEG);
+ (void)printf("Meridian/Parallel angle: %.5f\n",
+ facs.thetap * RAD_TO_DEG);
+ (void)printf("Convergence%c: ",facs.code & IS_ANAL_CONV ? '*' : ' ');
+ (void)fputs(rtodms(pline, facs.conv, 0, 0), stdout);
+ (void)printf(" [ %.8f ]\n", facs.conv * RAD_TO_DEG);
+ (void)printf("Max-min (Tissot axis a-b) scale error: %.5f %.5f\n\n",
+ facs.a, facs.b);
+ }
}
int main(int argc, char **argv) {
@@ -273,6 +318,7 @@ int main(int argc, char **argv) {
(void)fprintf(stderr, usage, pj_get_release(), emess_dat.Prog_name);
exit (0);
}
+
/* process run line arguments */
while (--argc > 0) { /* collect run line arguments */
if(**++argv == '-') for(arg = *argv;;) {
@@ -459,6 +505,7 @@ int main(int argc, char **argv) {
gen_cheb(inverse, int_proj, cheby_str, Proj, iargc, iargv);
exit(0);
}
+
/* set input formatting control */
if (mon) {
pj_pr_list(Proj);
@@ -477,6 +524,7 @@ int main(int argc, char **argv) {
}
}
}
+
if (inverse)
informat = strtod;
else {
@@ -485,8 +533,7 @@ int main(int argc, char **argv) {
oform = "%.2f";
}
- if (bin_out)
- {
+ if (bin_out) {
SET_BINARY_MODE(stdout);
}
@@ -516,7 +563,9 @@ int main(int argc, char **argv) {
(void)fclose(fid);
emess_dat.File_name = 0;
}
+
if( Proj )
pj_free(Proj);
+
exit(0); /* normal completion */
}
diff --git a/src/proj.def b/src/proj.def
index 12816f1c..598f2824 100644
--- a/src/proj.def
+++ b/src/proj.def
@@ -143,3 +143,7 @@ EXPORTS
proj_derivatives @130
proj_factors @131
+ proj_list_operations @132
+ proj_list_ellps @133
+ proj_list_units @134
+ proj_list_prime_meridians @135
diff --git a/src/proj.h b/src/proj.h
index 1d6191fd..049daf19 100644
--- a/src/proj.h
+++ b/src/proj.h
@@ -182,11 +182,11 @@ typedef union PJ_TRIPLET PJ_TRIPLET;
union PJ_COORD;
typedef union PJ_COORD PJ_COORD;
-struct PJ_DERIVS;
-typedef struct PJ_DERIVS PJ_DERIVS;
+struct DERIVS;
+typedef struct DERIVS PJ_DERIVS;
-struct PJ_FACTORS;
-typedef struct PJ_FACTORS PJ_FACTORS;
+struct FACTORS;
+typedef struct FACTORS PJ_FACTORS;
/* Data type for projection/transformation information */
struct PJconsts;
@@ -205,6 +205,23 @@ typedef struct PJ_GRID_INFO PJ_GRID_INFO;
struct PJ_INIT_INFO;
typedef struct PJ_INIT_INFO PJ_INIT_INFO;
+/* Data types for list of operations, ellipsoids, datums and units used in PROJ.4 */
+struct PJ_LIST;
+typedef struct PJ_LIST PJ_OPERATIONS;
+
+struct PJ_ELLPS;
+typedef struct PJ_ELLPS PJ_ELLPS;
+
+struct PJ_DATUMS;
+typedef struct PJ_DATUMS PJ_DATUMS;
+
+struct PJ_UNITS;
+typedef struct PJ_UNITS PJ_UNITS;
+
+struct PJ_PRIME_MERIDIANS;
+typedef struct PJ_PRIME_MERIDIANS PJ_PRIME_MERIDIANS;
+
+
/* Omega, Phi, Kappa: Rotations */
typedef struct {double o, p, k;} PJ_OPK;
@@ -288,22 +305,10 @@ struct PJ_OBS {
unsigned int flags; /* additional data, intended for flags */
};
-
-struct PJ_DERIVS {
- double x_l, x_p; /* derivatives of x for lambda-phi */
- double y_l, y_p; /* derivatives of y for lambda-phi */
-};
-
-struct PJ_FACTORS {
- struct PJ_DERIVS der;
- double h, k; /* meridional, parallel scales */
- double omega, thetap; /* angular distortion, theta prime */
- double conv; /* convergence */
- double s; /* areal scale factor */
- double a, b; /* max-min scale error */
- int code; /* info as to analytics, see following */
-};
-
+#define PJ_IS_ANAL_XL_YL 01 /* derivatives of lon analytic */
+#define PJ_IS_ANAL_XP_YP 02 /* derivatives of lat analytic */
+#define PJ_IS_ANAL_HK 04 /* h and k analytic */
+#define PJ_IS_ANAL_CONV 010 /* convergence analytic */
struct PJ_INFO {
char release[64]; /* Release info. Version + date */
@@ -317,10 +322,11 @@ struct PJ_INFO {
};
struct PJ_PROJ_INFO {
- char id[16]; /* Name of the projection in question */
- char description[128]; /* Description of the projection */
- char definition[512]; /* Projection definition */
- int has_inverse; /* 1 if an inverse mapping exists, 0 otherwise */
+ char id[16]; /* Name of the projection in question */
+ char description[128]; /* Description of the projection */
+ char definition[512]; /* Projection definition */
+ int has_inverse; /* 1 if an inverse mapping exists, 0 otherwise */
+ double accuracy; /* Expected accuracy of the transformation. -1 if unknown. */
};
struct PJ_GRID_INFO {
@@ -351,8 +357,10 @@ typedef struct projCtx_t PJ_CONTEXT;
/* Functionality for handling thread contexts */
+#define PJ_DEFAULT_CTX 0
PJ_CONTEXT *proj_context_create (void);
-void proj_context_destroy (PJ_CONTEXT *ctx);
+PJ_CONTEXT *proj_context_destroy (PJ_CONTEXT *ctx);
+
/* Manage the transformation definition object PJ */
@@ -363,38 +371,38 @@ PJ *proj_destroy (PJ *P);
/* Apply transformation to observation - in forward or inverse direction */
-enum proj_direction {
+enum PJ_DIRECTION {
PJ_FWD = 1, /* Forward */
PJ_IDENT = 0, /* Do nothing */
PJ_INV = -1 /* Inverse */
};
+typedef enum PJ_DIRECTION PJ_DIRECTION;
-
-PJ_OBS proj_trans_obs (PJ *P, enum proj_direction direction, PJ_OBS obs);
-PJ_COORD proj_trans_coord (PJ *P, enum proj_direction direction, PJ_COORD coord);
+PJ_OBS proj_trans_obs (PJ *P, PJ_DIRECTION direction, PJ_OBS obs);
+PJ_COORD proj_trans_coord (PJ *P, PJ_DIRECTION direction, PJ_COORD coord);
size_t proj_transform (
PJ *P,
- enum proj_direction direction,
+ PJ_DIRECTION direction,
double *x, size_t sx, size_t nx,
double *y, size_t sy, size_t ny,
double *z, size_t sz, size_t nz,
double *t, size_t st, size_t nt
);
-int proj_transform_obs (PJ *P, enum proj_direction direction, size_t n, PJ_OBS *obs);
-int proj_transform_coord (PJ *P, enum proj_direction direction, size_t n, PJ_COORD *coord);
+int proj_transform_obs (PJ *P, PJ_DIRECTION direction, size_t n, PJ_OBS *obs);
+int proj_transform_coord (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord);
/* Initializers */
PJ_COORD proj_coord (double x, double y, double z, double t);
PJ_OBS proj_obs (double x, double y, double z, double t, double o, double p, double k, int id, unsigned int flags);
/* Measure internal consistency - in forward or inverse direction */
-double proj_roundtrip (PJ *P, enum proj_direction direction, int n, PJ_OBS obs);
-
+double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD coo);
+
/* Geodesic distance between two points with angular 2D coordinates */
-double proj_lp_dist (PJ *P, LP a, LP b);
+double proj_lp_dist (const PJ *P, LP a, LP b);
/* Euclidean distance between two points with linear 2D coordinates */
double proj_xy_dist (XY a, XY b);
@@ -410,15 +418,21 @@ int proj_errno_reset (PJ *P);
void proj_errno_restore (PJ *P, int err);
-PJ_DERIVS proj_derivatives(const PJ *P, const LP lp);
-PJ_FACTORS proj_factors(const PJ *P, const LP lp);
-
+PJ_DERIVS proj_derivatives(PJ *P, const LP lp);
+PJ_FACTORS proj_factors(PJ *P, const LP lp);
+
/* Info functions - get information about various PROJ.4 entities */
PJ_INFO proj_info(void);
-PJ_PROJ_INFO proj_pj_info(const PJ *P);
+PJ_PROJ_INFO proj_pj_info(PJ *P);
PJ_GRID_INFO proj_grid_info(const char *gridname);
PJ_INIT_INFO proj_init_info(const char *initname);
+/* List functions: */
+/* Get lists of operations, ellipsoids, units and prime meridians. */
+const PJ_OPERATIONS *proj_list_operations(void);
+const PJ_ELLPS *proj_list_ellps(void);
+const PJ_UNITS *proj_list_units(void);
+const PJ_PRIME_MERIDIANS *proj_list_prime_meridians(void);
/* These are trivial, and while occasionaly useful in real code, primarily here to */
/* simplify demo code, and in acknowledgement of the proj-internal discrepancy between */
diff --git a/src/proj_etmerc.c b/src/proj_etmerc.c
index ff466ea8..a756a7ac 100644
--- a/src/proj_etmerc.c
+++ b/src/proj_etmerc.c
@@ -42,6 +42,7 @@
#define PROJ_LIB__
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -232,28 +233,12 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-
-static void *freeup_new (PJ *P) { /* Destructor */
- if (0==P)
- return 0;
- if (0==P->opaque)
- return pj_dealloc (P);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
-}
-
static PJ *setup(PJ *P) { /* general initialization */
double f, n, np, Z;
struct pj_opaque *Q = P->opaque;
if (P->es <= 0) {
- proj_errno_set(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
}
/* flattening */
@@ -340,7 +325,7 @@ static PJ *setup(PJ *P) { /* general initialization */
PJ *PROJECTION(etmerc) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
return setup (P);
}
@@ -411,12 +396,12 @@ PJ *PROJECTION(utm) {
int zone;
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor (P, ENOMEM);
P->opaque = Q;
if (P->es == 0.0) {
proj_errno_set(P, PJD_ERR_ELLIPSOID_USE_REQUIRED);
- return freeup_new(P);
+ return pj_default_destructor(P, ENOMEM);
}
P->y0 = pj_param (P->ctx, P->params, "bsouth").i ? 10000000. : 0.;
P->x0 = 500000.;
@@ -426,8 +411,7 @@ PJ *PROJECTION(utm) {
if (zone > 0 && zone <= 60)
--zone;
else {
- proj_errno_set(P, PJD_ERR_INVALID_UTM_ZONE);
- return freeup_new(P);
+ return pj_default_destructor(P, PJD_ERR_INVALID_UTM_ZONE);
}
}
else /* nearest central meridian input */
diff --git a/src/proj_rouss.c b/src/proj_rouss.c
index b33e7926..952e5c55 100644
--- a/src/proj_rouss.c
+++ b/src/proj_rouss.c
@@ -24,6 +24,7 @@
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#define PJ_LIB__
+#include <errno.h>
#include <proj.h>
#include "projects.h"
@@ -79,21 +80,17 @@ static LP e_inverse (XY xy, PJ *P) { /* Ellipsoidal, inverse */
}
-static void *freeup_new (PJ *P) { /* Destructor */
+static void *destructor (PJ *P, int errlev) {
if (0==P)
return 0;
+
if (0==P->opaque)
- return pj_dealloc (P);
+ return pj_default_destructor (P, errlev);
if (P->opaque->en)
pj_dealloc (P->opaque->en);
- pj_dealloc (P->opaque);
- return pj_dealloc(P);
-}
-static void freeup (PJ *P) {
- freeup_new (P);
- return;
+ return pj_default_destructor (P, ENOMEM);
}
@@ -102,11 +99,12 @@ PJ *PROJECTION(rouss) {
struct pj_opaque *Q = pj_calloc (1, sizeof (struct pj_opaque));
if (0==Q)
- return freeup_new (P);
+ return pj_default_destructor(P, ENOMEM);
P->opaque = Q;
if (!((Q->en = proj_mdist_ini(P->es))))
- return freeup_new(P);
+ return pj_default_destructor (P, ENOMEM);
+
es2 = sin(P->phi0);
Q->s0 = proj_mdist(P->phi0, es2, cos(P->phi0), Q->en);
t = 1. - (es2 = P->es * es2 * es2);
@@ -149,6 +147,7 @@ PJ *PROJECTION(rouss) {
P->fwd = e_forward;
P->inv = e_inverse;
+ P->destructor = destructor;
return P;
}
diff --git a/src/proj_strtod.c b/src/proj_strtod.c
new file mode 100644
index 00000000..e9942e5c
--- /dev/null
+++ b/src/proj_strtod.c
@@ -0,0 +1,251 @@
+/***********************************************************************
+
+ proj_strtod: Convert string to double, accepting underscore separators
+
+ Thomas Knudsen, 2017-01-17/09-19
+
+************************************************************************
+
+Conventionally, PROJ.4 does not honor locale settings, consistently
+behaving as if LC_ALL=C.
+
+For this to work, we have, for many years, been using other solutions
+than the C standard library strtod/atof functions for converting strings
+to doubles.
+
+In the early versions of proj, iirc, a gnu version of strtod was used,
+mostly to work around cases where the same system library was used for
+C and Fortran linking, hence making strtod accept "D" and "d" as
+exponentiation indicators, following Fortran Double Precision constant
+syntax. This broke the proj angular syntax accepting a "d" to mean
+"degree": 12d34'56", meaning 12 degrees 34 minutes and 56 seconds.
+
+With an explicit MIT licence, PROJ.4 could not include GPL code any
+longer, and apparently at some time, the GPL code was replaced by the
+current C port of a GDAL function (in pj_strtod.c), which reads the
+LC_NUMERIC setting and, behind the back of the user, momentarily changes
+the conventional '.' delimiter to whatever the locale requires, then
+calls the system supplied strtod.
+
+While this requires a minimum amount of coding, it only solves one
+problem, and not in a very generic way.
+
+Another problem, I would like to see solved, is the handling of underscores
+as generic delimiters. This is getting popular in a number of programming
+languages (Ada, C++, C#, D, Java, Julia, Perl 5, Python, Rust, etc.
+cf. e.g. https://www.python.org/dev/peps/pep-0515/), and in our case of
+handling numbers being in the order of magnitude of the Earth's dimensions,
+and a resolution of submillimetre, i.e. having 10 or more significant digits,
+splitting the "wall of digits" into smaller chunks is of immense value.
+
+Hence this reimplementation of strtod, which hardcodes '.' as indicator of
+numeric fractions, and accepts '_' anywhere in a numerical string sequence:
+So a typical northing value can be written
+
+ 6_098_907.8250 m
+rather than
+ 6098907.8250 m
+
+which, in my humble opinion, is well worth the effort.
+
+While writing this code, I took ample inspiration from Michael Ringgaard's
+strtod version over at http://www.jbox.dk/sanos/source/lib/strtod.c.html,
+and Yasuhiro Matsumoto's public domain version over at
+https://gist.github.com/mattn/1890186. The code below is, however, not
+copied from any of the two mentioned - it is a reimplementation, and
+probably suffers from its own set of bugs. So for now, it is intended
+not as a replacement of pj_strtod, but only as an experimental piece of
+code for use in an experimental new transformation program, cct.
+
+************************************************************************
+
+Thomas Knudsen, thokn@sdfe.dk, 2017-01-17/2017-09-18
+
+************************************************************************
+
+* Copyright (c) 2017 Thomas Knudsen & SDFE
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* 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 <ctype.h>
+#include <float.h> /* for HUGE_VAL */
+#include <math.h> /* for pow() */
+
+double proj_strtod(const char *str, char **endptr);
+double proj_atof(const char *str);
+
+
+double proj_strtod(const char *str, char **endptr) {
+ double number = 0;
+ int exponent = 0;
+ int sign = 0;
+ char *p = (char *) str;
+ int n = 0;
+ int num_digits_total = 0;
+ int num_digits_after_comma = 0;
+
+ if (0==str) {
+ errno = EFAULT;
+ if (endptr)
+ *endptr = p;
+ return HUGE_VAL;
+ }
+
+ /* First skip leading whitespace */
+ while (isspace(*p))
+ p++;
+
+ /* Empty string? */
+ if (0==*p) {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = p;
+ return HUGE_VAL;
+ }
+
+ /* Then handle optional prefixed sign */
+ switch (*p) {
+ case '-':
+ sign = -1, p++; break;
+ case '+':
+ sign = 1, p++; break;
+ default:
+ if (isdigit(*p) || '_'==*p || '.'==*p)
+ break;
+ if (endptr)
+ *endptr = p;
+ errno = EINVAL;
+ return HUGE_VAL;
+ }
+
+ /* Now expect a (potentially zero-length) string of digits */
+ while (isdigit(*p) || ('_'==*p)) {
+ if ('_'==*p) {
+ p++;
+ continue;
+ }
+ number = number * 10. + (*p - '0');
+ p++;
+ num_digits_total++;
+ }
+
+ /* Do we have a fractional part? */
+ if ('.'==*p) {
+ p++;
+
+ while (isdigit(*p) || '_'==*p) {
+ if ('_'==*p) {
+ p++;
+ continue;
+ }
+ number = number * 10. + (*p - '0');
+ p++;
+ num_digits_total++;
+ num_digits_after_comma++;
+ }
+
+ exponent = -num_digits_after_comma;
+ }
+
+ /* non-digit */
+ if (0==num_digits_total) {
+ errno = EINVAL;
+ if (endptr)
+ *endptr = p;
+ return HUGE_VAL;
+ }
+
+ if (sign==-1)
+ number = -number;
+
+ /* Do we have an exponent part? */
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ /* Does it have a sign? */
+ sign = 0;
+ if ('-'==*p)
+ sign = -1;
+ if ('+'==*p)
+ sign = +1;
+ if (0==sign) {
+ if (!isdigit(*p) && *p!='_') {
+ if (endptr)
+ *endptr = p;
+ return HUGE_VAL;
+ }
+ }
+ else
+ p++;
+
+
+ /* Go on and read the exponent */
+ n = 0;
+ while (isdigit(*p) || '_'==*p) {
+ if ('_'==*p) {
+ p++;
+ continue;
+ }
+ n = n * 10 + (*p - '0');
+ p++;
+ }
+
+ if (-1==sign)
+ n = -n;
+ exponent += n;
+ }
+
+ if ((exponent < DBL_MIN_EXP) || (exponent > DBL_MAX_EXP)) {
+ errno = ERANGE;
+ if (endptr)
+ *endptr = p;
+ return HUGE_VAL;
+ }
+
+ number *= pow (10, exponent);
+
+ if (fabs(number) > DBL_MAX)
+ errno = ERANGE;
+
+ if (endptr)
+ *endptr = p;
+
+ return number;
+}
+
+double proj_atof(const char *str) {
+ return proj_strtod(str, (void *) 0);
+}
+
+#ifdef TEST
+#include <string.h>
+
+int main (int argc, char **argv) {
+ double res;
+ char *endptr;
+ if (argc < 2)
+ return 0;
+ res = proj_strtod (argv[1], &endptr);
+ printf ("res = %20.15g. Rest = [%s], errno = %d\n", res, endptr, (int) errno);
+ return 0;
+}
+#endif
diff --git a/src/projects.h b/src/projects.h
index 872bf816..9391835d 100644
--- a/src/projects.h
+++ b/src/projects.h
@@ -253,62 +253,8 @@ struct PJconsts {
void (*spc)(LP, PJ *, struct FACTORS *);
- void (*pfree)(PJ *);
-
- /*************************************************************************************
-
- E R R O R R E P O R T I N G
-
- **************************************************************************************
-
- Currently, we're doing error reporting through the context->last_errno indicator.
-
- It is, however, not entirely sure this will be the right way to do it in all
- cases: During allocation/initialization, it is certainly nice to have a higher
- level error indicator, since we primarily signal "something went wrong", by
- returning 0 from the pj_init family of functions - and with a null return we
- cannot pass messages through internal state in the PJ object.
-
- Historically, the errno variable has been used for that kind of messages, but
- apparently, thread safety was added to PROJ.4 at a time where it was not clear
- that errno is actually thread local.
-
- Additionally, errno semantics has historically been misinterpreted in parts of
- pj_init.c, a misinterpretation, that was mitigated by a hack in pj_malloc.c
- some 15 years ago.
-
- This PJ-local errno is a first step towards a more structured approach to
- error reporting, being implemented in the OBS_API (cf. pj_obs_api.[ch]), and
- related plumbing efforts.
-
- In due course this will let us get rid of the pj_malloc.c hack, and allow us
- to introduce a more layered error reporting structure, where errors are
- reported where they occur, and bubble up to the higher levels (context->errno,
- then thread local errno), so the highest level indicate "something went wrong
- somewhere", then the more localized ones can be used for pinpointing:
-
- errno: "something went wrong somewhere on this thread",
- context->last_errno: "something went wrong in some PROJ.4 related code",
- PJ->last_errno: "It was in THIS PJ something went wrong",
- pj_strerrno: "This was what went wrong".
-
- Which will be quite helpful, once fully implemented, especially for
- debugging complex transformation pipelines, while still maintaining backward
- compatibility in the messaging system.
-
- Note that there is even a global pj_errno, which is here and there accessed
- without acquiring lock. This, and the practise of resetting the thread local
- errno, should be given some consideration during the cleanup of the error
- reporting system.
-
- The name "last_errno", rather than "errno" is used partially for alignment
- with the context->last_errno, partially because in a multithreaded environment,
- errno is a macro, and spurious spaces turning "errno" into a separate token
- will expose it to macro expansion, to the tune of much confusion and agony.
-
- **************************************************************************************/
- int last_errno;
-
+ void *(*destructor)(PJ *, int);
+
/*************************************************************************************
@@ -386,7 +332,7 @@ struct PJconsts {
**************************************************************************************/
double lam0, phi0; /* central longitude, latitude */
- double x0, y0; /* false easting and northing */
+ double x0, y0, z0, t0; /* false easting and northing (and height and time) */
/*************************************************************************************
@@ -524,7 +470,24 @@ struct FACTORS {
/* library errors */
#define PJD_ERR_NO_ARGS -1
+#define PJD_ERR_NO_OPTION_IN_INIT_FILE -2
+#define PJD_ERR_NO_COLOR_IN_INIT_STRING -3
+#define PJD_ERR_PROJ_NOT_NAMED -4
+#define PJD_ERR_UNKNOWN_PROJECTION_ID -5
+#define PJD_ERR_ECCENTRICITY_IS_ONE -6
+#define PJD_ERR_UNKNOW_UNIT_ID -7
+#define PJD_ERR_INVALID_BOOLEAN_PARAM -8
+#define PJD_ERR_UNKNOWN_ELLP_PARAM -9
+#define PJD_ERR_REC_FLATTENING_IS_ZERO -10
+#define PJD_ERR_REF_RAD_LARGER_THAN_90 -11
+#define PJD_ERR_ES_LESS_THAN_ZERO -12
+#define PJD_ERR_MAJOR_AXIS_NOT_GIVEN -13
#define PJD_ERR_LAT_OR_LON_EXCEED_LIMIT -14
+#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_ACOS_ASIN_ARG_TOO_LARGE -19
#define PJD_ERR_TOLERANCE_CONDITION -20
#define PJD_ERR_CONIC_LAT_EQUAL -21
#define PJD_ERR_LAT_LARGER_THAN_90 -22
@@ -536,24 +499,32 @@ struct FACTORS {
#define PJD_ERR_LSAT_NOT_IN_RANGE -28
#define PJD_ERR_PATH_NOT_IN_RANGE -29
#define PJD_ERR_H_LESS_THAN_ZERO -30
+#define PJD_ERR_K_LESS_THAN_ZERO -31
#define PJD_ERR_LAT_1_OR_2_ZERO_OR_90 -32
#define PJD_ERR_LAT_0_OR_ALPHA_EQ_90 -33
#define PJD_ERR_ELLIPSOID_USE_REQUIRED -34
#define PJD_ERR_INVALID_UTM_ZONE -35
+#define PJD_ERR_TCHEBY_VAL_OUT_OF_RANGE -36
#define PJD_ERR_FAILED_TO_FIND_PROJ -37
+#define PJD_ERR_FAILED_TO_LOAD_GRID -38
#define PJD_ERR_INVALID_M_OR_N -39
#define PJD_ERR_N_OUT_OF_RANGE -40
+#define PJD_ERR_LAT_1_2_UNSPECIFIED -41
#define PJD_ERR_ABS_LAT1_EQ_ABS_LAT2 -42
#define PJD_ERR_LAT_0_HALF_PI_FROM_MEAN -43
+#define PJD_ERR_UNPARSEABLE_CS_DEF -44
#define PJD_ERR_GEOCENTRIC -45
#define PJD_ERR_UNKNOWN_PRIME_MERIDIAN -46
#define PJD_ERR_AXIS -47
#define PJD_ERR_GRID_AREA -48
#define PJD_ERR_INVALID_SWEEP_AXIS -49
+#define PJD_ERR_MALFORMED_PIPELINE -50
+#define PJD_ERR_UNIT_FACTOR_LESS_THAN_0 -51
#define PJD_ERR_INVALID_SCALE -52
#define PJD_ERR_NON_CONVERGENT -53
#define PJD_ERR_MISSING_ARGS -54
#define PJD_ERR_LAT_0_IS_ZERO -55
+#define PJD_ERR_ELLIPSOIDAL_UNSUPPORTED -56
struct projFileAPI_t;
@@ -616,8 +587,10 @@ C_NAMESPACE PJ *pj_##name (PJ *P) { \
P = (PJ*) pj_calloc (1, sizeof(PJ)); \
if (0==P) \
return 0; \
- P->pfree = freeup; \
+ P->destructor = pj_default_destructor; \
P->descr = des_##name; \
+ P->left = PJ_IO_UNITS_RADIANS; \
+ P->right = PJ_IO_UNITS_CLASSIC; \
return P; \
} \
PJ *pj_projection_specific_setup_##name (PJ *P)
@@ -707,12 +680,12 @@ int pj_datum_set(projCtx,paralist *, PJ *);
int pj_prime_meridian_set(paralist *, PJ *);
int pj_angular_units_set(paralist *, PJ *);
-void pj_prepare (PJ *P, const char *description, void (*freeup)(struct PJconsts *), size_t sizeof_struct_opaque);
-
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_get_init(projCtx ctx, paralist **start, paralist *next, char *name, int *found_def);
+void *pj_dealloc_params (projCtx ctx, paralist *start, int errlev);
+
double *pj_enfn(double);
double pj_mlfn(double, double, double, double *);
@@ -822,6 +795,8 @@ struct PJ_LIST *pj_get_list_ref( void );
struct PJ_SELFTEST_LIST *pj_get_selftest_list_ref ( void );
struct PJ_PRIME_MERIDIANS *pj_get_prime_meridians_ref( void );
+void *pj_default_destructor (PJ *P, int errlev);
+
double pj_atof( const char* nptr );
double pj_strtod( const char *nptr, char **endptr );
void pj_freeup_plain (PJ *P);
diff --git a/src/test228.c b/src/test228.c
index 1f3d04e8..94f0ec08 100644
--- a/src/test228.c
+++ b/src/test228.c
@@ -54,6 +54,8 @@ static void* thread_main(void* unused)
assert(fabs(y - 49.999396034285531698) < 1e-15);
}
+ pj_free (p_OSGB36_proj);
+ pj_free (p_WGS84_proj);
return NULL;
}
diff --git a/travis/before_install.sh b/travis/before_install.sh
index 8a4bbd24..249cb591 100755
--- a/travis/before_install.sh
+++ b/travis/before_install.sh
@@ -1,6 +1,20 @@
#!/bin/bash
-pip install --user cpp-coveralls
-./travis/docker.sh
+# All platform-specific before_install scripts starts by running this
+# "global" before_install script.
+# Specify which version of python to use. The default python to use on Travis
+# can vary from platform to platform, so we use pyenv to make sure we use
+# a version that works for the complete build processs. (Not in use at the moment,
+# since the pyenv setup on Travis is not consistent across platforms and partly
+# broken as well)
+#pyenv global system 3.5
+#pyenv versions # a bit of debug info
+# What is the current python setup?
+which python
+python --version
+python3 --version
+
+which pip
+pip --version
diff --git a/travis/install.sh b/travis/install.sh
index 70b8e90d..51a8ea2f 100755
--- a/travis/install.sh
+++ b/travis/install.sh
@@ -84,7 +84,6 @@ PROJ_LIB=$GRIDDIR ./src/proj -VC
# install & run the working GIGS test
# create locations that pyproj understands
-python3 --version
ln -s src include
ln -s src/.libs lib
mkdir share
@@ -92,12 +91,12 @@ ln -s nad share/proj
pwd
# install pyproj
export CFLAGS=
-PROJ_DIR=`pwd` pip3 install -v --user pyproj
+PROJ_DIR=`pwd` pip install -v --user pyproj
cd test/gigs
# run test_json.py
-PROJ_LIB=../../nad python3 test_json.py --test conversion 5101.1-jhs.json 5101.4-jhs-etmerc.json 5105.2.json 5106.json 5108.json 5110.json 5111.1.json
-PROJ_LIB=../../nad python3 test_json.py 5101.2-jhs.json 5101.3-jhs.json 5102.1.json 5103.1.json 5103.2.json 5103.3.json 5107.json 5109.json 5112.json 5113.json 5201.json 5208.json
+PROJ_LIB=../../nad python test_json.py --test conversion 5101.1-jhs.json 5101.4-jhs-etmerc.json 5105.2.json 5106.json 5108.json 5110.json 5111.1.json
+PROJ_LIB=../../nad python test_json.py 5101.2-jhs.json 5101.3-jhs.json 5102.1.json 5103.1.json 5103.2.json 5103.3.json 5107.json 5109.json 5112.json 5113.json 5201.json 5208.json
cd ../..
mv src/.libs/*.gc* src
diff --git a/travis/linux_clang/before_install.sh b/travis/linux_clang/before_install.sh
index 75acd97a..f6e21076 100755
--- a/travis/linux_clang/before_install.sh
+++ b/travis/linux_clang/before_install.sh
@@ -2,4 +2,5 @@
set -e
+./travis/before_install.sh
# do nothing
diff --git a/travis/linux_clang/install.sh b/travis/linux_clang/install.sh
index 56e16ce6..a0dd9353 100755
--- a/travis/linux_clang/install.sh
+++ b/travis/linux_clang/install.sh
@@ -4,4 +4,4 @@ set -e
export CCACHE_CPP2=yes
-CC="ccache clang" CFLAGS="-g -Wall -Wextra -Werror -Wunused-parameter -Wmissing-prototypes -Wmissing-declarations -Wformat -Werror=format-security -Wshadow -Wfloat-conversion -O2" ./travis/install.sh
+CC="ccache clang" CFLAGS="-g -Wall -Wextra -Werror -Wunused-parameter -Wmissing-prototypes -Wmissing-declarations -Wformat -Werror=format-security -Wshadow -Wfloat-conversion -fsanitize=address -O2" ./travis/install.sh
diff --git a/travis/linux_gcc/before_install.sh b/travis/linux_gcc/before_install.sh
index 31805e80..0c37643c 100755
--- a/travis/linux_gcc/before_install.sh
+++ b/travis/linux_gcc/before_install.sh
@@ -1,5 +1,7 @@
#!/bin/bash
+./travis/before_install.sh
+
sudo apt-get install -y cppcheck
cppcheck --inline-suppr --template='{file}:{line},{severity},{id},{message}' --enable=all --inconclusive --std=posix -DPJ_SELFTEST=1 src/*.c 2>/tmp/cppcheck.txt
@@ -12,4 +14,6 @@ fi
set -e
-./travis/before_install.sh
+pip install --user cpp-coveralls
+./travis/docker.sh
+
diff --git a/travis/mingw32/before_install.sh b/travis/mingw32/before_install.sh
index 18949b75..5cadb761 100755
--- a/travis/mingw32/before_install.sh
+++ b/travis/mingw32/before_install.sh
@@ -2,6 +2,8 @@
set -e
+./travis/before_install.sh
+
sudo apt-get update -qq
sudo apt-get install -qq wine
sudo apt-get install -qq mingw32
diff --git a/travis/osx/before_install.sh b/travis/osx/before_install.sh
index cd553dda..4ca62084 100755
--- a/travis/osx/before_install.sh
+++ b/travis/osx/before_install.sh
@@ -2,5 +2,7 @@
set -e
+./travis/before_install.sh
+
brew install ccache
brew install python3