Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b377bf1258 | ||
|
|
a95431d866 | ||
|
|
c5fb541686 | ||
|
|
bc31bda210 | ||
|
|
c4191f3057 | ||
|
|
a6390b59ae | ||
|
|
9bb87ea478 | ||
|
|
9d2851ad36 | ||
|
|
0a4aa2317d | ||
|
|
4724025e6c | ||
|
|
f1209ff020 | ||
|
|
66fd99a883 | ||
|
|
7040857c1f | ||
|
|
2afa147d29 | ||
|
|
7468536f07 | ||
|
|
c40ee9dfbb | ||
|
|
941bb82c7e | ||
|
|
9cb40a8322 | ||
|
|
034238e501 | ||
|
|
0961d15ac1 | ||
|
|
9d61bf83af | ||
|
|
9d8647371d | ||
|
|
f6c4241652 | ||
|
|
90b6685a99 | ||
|
|
9263e1d36e | ||
|
|
da93fe3bea | ||
|
|
dd9afa39d7 | ||
|
|
8821b3591e | ||
|
|
316ca96fc9 | ||
|
|
408cb1e427 | ||
|
|
32fc01c08f | ||
|
|
13d651a730 | ||
|
|
e8459c135d | ||
|
|
237296b7e8 | ||
|
|
fc73b2f2ca | ||
|
|
eafeb61ce5 | ||
|
|
19841f21f4 | ||
|
|
08ae5764f5 | ||
|
|
11f63432d3 | ||
|
|
ea106578ee | ||
|
|
db040122c5 | ||
|
|
ea73297ea4 | ||
|
|
17864e68dc | ||
|
|
830f94a811 | ||
|
|
28e1770f27 | ||
|
|
f934c002c0 | ||
|
|
be59650039 | ||
|
|
f085b39752 | ||
|
|
aa8c7826cf | ||
|
|
2093aca072 | ||
|
|
c4589fbe42 | ||
|
|
0a1f1fe469 | ||
|
|
9d0bd793b5 | ||
|
|
d3bdbb8417 | ||
|
|
ed92965937 | ||
|
|
f73527fa20 | ||
|
|
a06f4a258f | ||
|
|
2aeb122fb2 | ||
|
|
d6ae5289b6 | ||
|
|
cde119a251 | ||
|
|
2dfe2cdd1f | ||
|
|
7baf00c5bc | ||
|
|
a70e477087 | ||
|
|
f36d237426 | ||
|
|
b934fd3885 | ||
|
|
49f8ea7ea4 | ||
|
|
c165952bcf | ||
|
|
8063c0b992 | ||
|
|
3fa5d486b9 | ||
|
|
6d45bbc88b | ||
|
|
e872984b46 | ||
|
|
2804ee5ec0 | ||
|
|
1f01ecb90a | ||
|
|
9f908ae47c | ||
|
|
1b702a82f5 | ||
|
|
22792cd55b | ||
|
|
916a92062f | ||
|
|
6875ef7116 | ||
|
|
126384854b | ||
|
|
41ff94791a |
+1
-1
@@ -16,7 +16,7 @@ task:
|
||||
folder: $HOME/.ccache
|
||||
|
||||
pkginstall_script:
|
||||
- pkg install -y autoconf automake libtool pkgconf sqlite3 wget unzip ccache gmake
|
||||
- pkg install -y autoconf automake libtool pkgconf sqlite3 tiff wget unzip ccache gmake
|
||||
download_grid_script:
|
||||
- wget https://download.osgeo.org/proj/proj-datumgrid-1.8.zip
|
||||
- (cd data && unzip -o ../proj-datumgrid-1.8.zip)
|
||||
|
||||
@@ -83,6 +83,7 @@ elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel")
|
||||
set(PROJ_CXX_WARN_FLAGS -Wall)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(PROJ_C_WARN_FLAGS "${PROJ_C_WARN_FLAGS}"
|
||||
CACHE STRING "C flags used to compile PROJ targets")
|
||||
set(PROJ_CXX_WARN_FLAGS "${PROJ_CXX_WARN_FLAGS}"
|
||||
@@ -133,6 +134,39 @@ IF("${SQLITE3_VERSION}" VERSION_LESS "3.11")
|
||||
message(SEND_ERROR "sqlite3 >= 3.11 required!")
|
||||
ENDIF()
|
||||
|
||||
################################################################################
|
||||
# Check for libtiff
|
||||
################################################################################
|
||||
|
||||
option(DISABLE_TIFF "Disable TIFF support" OFF)
|
||||
mark_as_advanced(DISABLE_TIFF)
|
||||
if(DISABLE_TIFF)
|
||||
message(WARNING "TIFF support has been disabled and will result in the inability to read some grids")
|
||||
else()
|
||||
find_package(TIFF REQUIRED)
|
||||
if(TIFF_FOUND)
|
||||
boost_report_value(TIFF_FOUND)
|
||||
else()
|
||||
message(SEND_ERROR "libtiff dependency not found!")
|
||||
endif()
|
||||
add_definitions(-DTIFF_ENABLED)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# Check for curl
|
||||
################################################################################
|
||||
|
||||
option(ENABLE_CURL "Enable Curl support" ON)
|
||||
if(ENABLE_CURL)
|
||||
find_package(CURL REQUIRED)
|
||||
if(CURL_FOUND)
|
||||
boost_report_value(CURL_FOUND)
|
||||
else()
|
||||
message(SEND_ERROR "curl dependency not found!")
|
||||
endif()
|
||||
add_definitions(-DCURL_ENABLED)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
# threading configuration
|
||||
################################################################################
|
||||
|
||||
@@ -772,7 +772,7 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = src/iso19111 include/proj src/proj.h src/proj_experimental.h src/general_doc.dox
|
||||
INPUT = src/iso19111 include/proj src/proj.h src/proj_experimental.h src/general_doc.dox src/filemanager.cpp src/networkfilemanager.cpp
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
||||
+4
-1
@@ -27,9 +27,10 @@ build_script:
|
||||
- set PATH=%CD%;%PATH%
|
||||
- cd ..
|
||||
- vcpkg install sqlite3:"%platform%"-windows
|
||||
- vcpkg install tiff:"%platform%"-windows
|
||||
- vcpkg install curl:"%platform%"-windows
|
||||
- set SQLITE3_BIN=%APPVEYOR_BUILD_FOLDER%\sqlite3\bin
|
||||
- mkdir %SQLITE3_BIN%
|
||||
- copy c:\projects\proj\vcpkg\installed\"%platform%"-windows\bin\sqlite3.dll %SQLITE3_BIN%
|
||||
- ps: |
|
||||
appveyor DownloadFile https://sqlite.org/2018/sqlite-tools-win32-x86-3250100.zip
|
||||
7z x sqlite-tools-win32-x86-3250100.zip
|
||||
@@ -50,6 +51,8 @@ build_script:
|
||||
- set PROJ_DIR=%APPVEYOR_BUILD_FOLDER%\proj_dir
|
||||
- cmake -G "%VS_FULL%" .. -DCMAKE_BUILD_TYPE=Release -DBUILD_LIBPROJ_SHARED="%BUILD_LIBPROJ_SHARED%" -DCMAKE_C_FLAGS="/WX" -DCMAKE_CXX_FLAGS="/WX" -DCMAKE_TOOLCHAIN_FILE=C:/projects/proj/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX="%PROJ_DIR%"
|
||||
- cmake --build . --config Release --target install
|
||||
- copy c:\projects\proj\vcpkg\installed\"%platform%"-windows\bin\*.dll %PROJ_DIR%\bin
|
||||
- dir %PROJ_DIR%\bin
|
||||
|
||||
test_script:
|
||||
- echo test_script
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
# add test with sh script
|
||||
#
|
||||
|
||||
function(proj_test_set_properties TESTNAME)
|
||||
set_tests_properties( ${TESTNAME}
|
||||
PROPERTIES ENVIRONMENT "PROJ_IGNORE_USER_WRITABLE_DIRECTORY=YES;PROJ_LIB=${PROJECT_BINARY_DIR}/data/for_tests")
|
||||
endfunction()
|
||||
|
||||
function(proj_add_test_script_sh SH_NAME BIN_USE)
|
||||
if(UNIX)
|
||||
get_filename_component(testname ${SH_NAME} NAME_WE)
|
||||
@@ -26,8 +31,8 @@ function(proj_add_test_script_sh SH_NAME BIN_USE)
|
||||
COMMAND ${PROJECT_SOURCE_DIR}/test/cli/${SH_NAME}
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${${BIN_USE}}
|
||||
)
|
||||
set_tests_properties( ${testname}
|
||||
PROPERTIES ENVIRONMENT "PROJ_LIB=${PROJECT_BINARY_DIR}/data/for_tests")
|
||||
|
||||
proj_test_set_properties(${testname})
|
||||
endif()
|
||||
|
||||
endif()
|
||||
@@ -43,8 +48,6 @@ function(proj_add_gie_test TESTNAME TESTCASE)
|
||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${GIE_BIN}
|
||||
${TESTFILE}
|
||||
)
|
||||
set_tests_properties( ${TESTNAME}
|
||||
PROPERTIES ENVIRONMENT "PROJ_LIB=${PROJECT_BINARY_DIR}/data/for_tests")
|
||||
|
||||
proj_test_set_properties(${TESTNAME})
|
||||
|
||||
endfunction()
|
||||
|
||||
@@ -20,6 +20,8 @@ AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl Enable as much warnings as possible
|
||||
AX_CFLAGS_WARN_ALL(C_WFLAGS)
|
||||
AX_CXXFLAGS_WARN_ALL(CXX_WFLAGS)
|
||||
@@ -169,6 +171,15 @@ AC_SUBST(NO_ZERO_AS_NULL_POINTER_CONSTANT_FLAG,$NO_ZERO_AS_NULL_POINTER_CONSTANT
|
||||
CFLAGS="${CFLAGS} -fvisibility=hidden"
|
||||
CXXFLAGS="${CXXFLAGS} -fvisibility=hidden"
|
||||
|
||||
case "${host_os}" in
|
||||
cygwin* | mingw32* | pw32* | beos* | darwin*)
|
||||
CFLAGS="${CFLAGS} -DNOMINMAX"
|
||||
CXXFLAGS="${CXXFLAGS} -DNOMINMAX"
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Checks for libraries.
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS=`echo "$CFLAGS" | sed "s/-Werror/ /"`
|
||||
@@ -240,6 +251,78 @@ if test x"$SQLITE3_CHECK" != x"yes" ; then
|
||||
AC_MSG_ERROR([Please install sqlite3 binary.])
|
||||
fi
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Check for libtiff
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([tiff-is-strongly-discouraged],
|
||||
AS_HELP_STRING([--disable-tiff-is-strongly-discouraged],
|
||||
[Disable TIFF support. Strongly discouraged !]),
|
||||
[enable_tiff=no],
|
||||
[enable_tiff=yes])
|
||||
|
||||
if test "x$enable_tiff" = "xyes" -o "x$enable_tiff" = ""; then
|
||||
if test "x$TIFF_CFLAGS$TIFF_LIBS" = "x" ; then
|
||||
if $PKG_CONFIG libtiff; then
|
||||
PKG_CHECK_MODULES([TIFF], [libtiff])
|
||||
else
|
||||
PKG_CHECK_MODULES([TIFF], [libtiff-4])
|
||||
fi
|
||||
fi
|
||||
TIFF_ENABLED_FLAGS=-DTIFF_ENABLED
|
||||
fi
|
||||
AC_SUBST(TIFF_CFLAGS,$TIFF_CFLAGS)
|
||||
AC_SUBST(TIFF_LIBS,$TIFF_LIBS)
|
||||
AC_SUBST(TIFF_ENABLED_FLAGS,$TIFF_ENABLED_FLAGS)
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Check for curl
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
FOUND_CURL=no
|
||||
CURL_CFLAGS=
|
||||
CURL_LIB=
|
||||
|
||||
AC_ARG_WITH(curl,
|
||||
[ --with-curl[=ARG] Enable curl support (ARG=path to curl-config.)],,,)
|
||||
|
||||
dnl Clear some cache variables
|
||||
unset ac_cv_path_LIBCURL
|
||||
|
||||
if test "`basename xx/$with_curl`" = "curl-config" ; then
|
||||
LIBCURL_CONFIG="$with_curl"
|
||||
elif test "$with_curl" = "no" ; then
|
||||
LIBCURL_CONFIG=no
|
||||
else
|
||||
AC_PATH_PROG(LIBCURL_CONFIG, curl-config, not-found)
|
||||
fi
|
||||
|
||||
if test "$LIBCURL_CONFIG" = "not-found" ; then
|
||||
AC_MSG_ERROR([curl not found. If wanting to do a build without curl support (and thus without built-in networking capability), explictly disable it with --without-curl])
|
||||
elif test "$LIBCURL_CONFIG" != "no" ; then
|
||||
|
||||
CURL_VERNUM=`$LIBCURL_CONFIG --vernum`
|
||||
CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
|
||||
|
||||
AC_MSG_RESULT([ found libcurl version $CURL_VER])
|
||||
|
||||
AC_CHECK_LIB(curl,curl_global_init,FOUND_CURL=yes,FOUND_CURL=no,`$LIBCURL_CONFIG --libs`)
|
||||
|
||||
if test "$FOUND_CURL" = "no" ; then
|
||||
AC_MSG_ERROR([curl not found. If wanting to do a build without curl support (and thus without built-in networking capability), explictly disable it with --without-curl])
|
||||
fi
|
||||
CURL_ENABLED_FLAGS=-DCURL_ENABLED
|
||||
fi
|
||||
|
||||
if test "$FOUND_CURL" = "yes" ; then
|
||||
CURL_CFLAGS=`$LIBCURL_CONFIG --cflags`
|
||||
CURL_LIBS=`$LIBCURL_CONFIG --libs`
|
||||
fi
|
||||
|
||||
AC_SUBST(CURL_CFLAGS,$CURL_CFLAGS)
|
||||
AC_SUBST(CURL_LIBS,$CURL_LIBS)
|
||||
AC_SUBST(CURL_ENABLED_FLAGS,$CURL_ENABLED_FLAGS)
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
dnl Check for external Google Test
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
+13
-2
@@ -2,6 +2,10 @@
|
||||
# files containing dictionary of useful projection
|
||||
#
|
||||
|
||||
set(CONFIG_FILES
|
||||
proj.ini
|
||||
)
|
||||
|
||||
set(PROJ_DICTIONARY
|
||||
null
|
||||
world
|
||||
@@ -54,7 +58,7 @@ add_custom_command(
|
||||
add_custom_target(generate_proj_db ALL DEPENDS ${PROJ_DB})
|
||||
|
||||
if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
foreach(FILE ${PROJ_DICTIONARY} ${GRIDSHIFT_FILES})
|
||||
foreach(FILE ${CONFIG_FILES} ${PROJ_DICTIONARY} ${GRIDSHIFT_FILES})
|
||||
configure_file(${FILE} ${FILE} COPYONLY)
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -78,18 +82,25 @@ set(DATA_FOR_TESTS
|
||||
nzgd2kgrid0005.gsb
|
||||
ITRF2000
|
||||
BETA2007.gsb)
|
||||
file(GLOB DATA_TESTS tests/*)
|
||||
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/for_tests)
|
||||
foreach(FILE ${DATA_FOR_TESTS})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/for_tests/tests)
|
||||
foreach(FILE ${DATA_FOR_TESTS} ${CONFIG_FILES})
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILE} ${CMAKE_CURRENT_BINARY_DIR}/for_tests/${FILE} COPYONLY)
|
||||
endif()
|
||||
endforeach()
|
||||
foreach(FILE ${DATA_TESTS})
|
||||
get_filename_component(FILENAME ${FILE} NAME)
|
||||
configure_file(${FILE} ${CMAKE_CURRENT_BINARY_DIR}/for_tests/tests/${FILENAME} COPYONLY)
|
||||
endforeach()
|
||||
|
||||
#
|
||||
#install
|
||||
#
|
||||
set(ALL_DATA_FILE
|
||||
${CONFIG_FILES}
|
||||
${PROJ_DICTIONARY}
|
||||
${GRIDSHIFT_FILES}
|
||||
${PROJ_DB}
|
||||
|
||||
+48
-3
@@ -1,6 +1,6 @@
|
||||
DATAPATH = $(top_srcdir)/data
|
||||
|
||||
pkgdata_DATA = GL27 nad.lst nad27 nad83 world other.extra \
|
||||
pkgdata_DATA = proj.ini GL27 nad.lst nad27 nad83 world other.extra \
|
||||
CH null \
|
||||
ITRF2000 ITRF2008 ITRF2014 proj.db \
|
||||
projjson.schema.json
|
||||
@@ -38,12 +38,55 @@ SQL_ORDERED_LIST = sql/begin.sql \
|
||||
sql/customizations.sql \
|
||||
sql/commit.sql
|
||||
|
||||
EXTRA_DIST = GL27 nad.lst nad27 nad83 \
|
||||
EXTRA_DIST = proj.ini GL27 nad.lst nad27 nad83 \
|
||||
world other.extra \
|
||||
CH \
|
||||
ITRF2000 ITRF2008 ITRF2014 \
|
||||
projjson.schema.json \
|
||||
CMakeLists.txt tests/test_nodata.gtx null \
|
||||
CMakeLists.txt \
|
||||
tests/test_nodata.gtx \
|
||||
tests/test_vgrid_bigendian_bigtiff.tif \
|
||||
tests/test_vgrid_bigendian.tif \
|
||||
tests/test_vgrid_bigtiff.tif \
|
||||
tests/test_vgrid_bottomup_with_matrix.tif \
|
||||
tests/test_vgrid_bottomup_with_scale.tif \
|
||||
tests/test_vgrid_deflate_floatingpointpredictor.tif \
|
||||
tests/test_vgrid_deflate.tif \
|
||||
tests/test_vgrid_float64.tif \
|
||||
tests/test_vgrid_in_second_channel.tif \
|
||||
tests/test_vgrid_int16.tif \
|
||||
tests/test_vgrid_int32.tif \
|
||||
tests/test_vgrid_uint32.tif \
|
||||
tests/test_vgrid_invalid_channel_type.tif \
|
||||
tests/test_vgrid_nodata.tif \
|
||||
tests/test_vgrid_pixelisarea.tif \
|
||||
tests/test_vgrid_pixelispoint.tif \
|
||||
tests/test_vgrid_uint16.tif \
|
||||
tests/test_vgrid_uint16_with_scale_offset.tif \
|
||||
tests/test_vgrid_unsupported_byte.tif \
|
||||
tests/test_vgrid_with_overview.tif \
|
||||
tests/test_vgrid_with_subgrid.tif \
|
||||
tests/test_hgrid.tif \
|
||||
tests/test_hgrid_separate.tif \
|
||||
tests/test_hgrid_tiled.tif \
|
||||
tests/test_hgrid_tiled_separate.tif \
|
||||
tests/test_hgrid_strip.tif \
|
||||
tests/test_hgrid_positive_west.tif \
|
||||
tests/test_hgrid_lon_shift_first.tif \
|
||||
tests/test_hgrid_radian.tif \
|
||||
tests/test_hgrid_degree.tif \
|
||||
tests/test_hgrid_with_overview.tif \
|
||||
tests/test_hgrid_extra_ifd_with_other_info.tif \
|
||||
tests/test_hgrid_with_subgrid.tif \
|
||||
tests/test_hgrid_with_subgrid_no_grid_name.tif \
|
||||
tests/subset_of_gr3df97a.tif \
|
||||
tests/egm96_15_uncompressed_truncated.tif \
|
||||
tests/test_vgrid_single_strip_truncated.tif \
|
||||
tests/nkgrf03vel_realigned_extract.tif \
|
||||
tests/nkgrf03vel_realigned_xy_extract.ct2 \
|
||||
tests/nkgrf03vel_realigned_z_extract.gtx \
|
||||
tests/test_hgrid_with_two_level_of_subgrids_no_grid_name.tif \
|
||||
null \
|
||||
generate_all_sql_in.cmake sql_filelist.cmake \
|
||||
$(SQL_ORDERED_LIST)
|
||||
|
||||
@@ -127,6 +170,8 @@ check-local:
|
||||
echo "WARNING: grid $$x missing: some tests will be skipped"; \
|
||||
fi \
|
||||
done; \
|
||||
ln -sf ../$(DATAPATH)/tests for_tests; \
|
||||
ln -sf ../$(DATAPATH)/proj.ini for_tests; \
|
||||
ln -sf ../proj.db for_tests
|
||||
|
||||
clean-local:
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[general]
|
||||
; Lines starting by ; are commented lines.
|
||||
;
|
||||
|
||||
; Network capabilities disabled by default.
|
||||
; Can be overriden with the PROJ_NETWORK=ON environment variable.
|
||||
; network = on
|
||||
|
||||
; Can be overriden with the PROJ_NETWORK_ENDPOINT environment variable.
|
||||
cdn_endpoint = https://cdn.proj.org
|
||||
|
||||
cache_enabled = on
|
||||
|
||||
cache_size_MB = 300
|
||||
|
||||
cache_ttl_sec = 86400
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -91,6 +91,17 @@ cartesian coordinates) and
|
||||
*Coordinate Transformations*, which are coordinate operations where
|
||||
input and output datums differ (e.g. change of reference frame).
|
||||
|
||||
Use of remote grids
|
||||
*******************
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
If the :envvar:`PROJ_NETWORK` environment variable is set to ``ON``,
|
||||
:program:`cct` will attempt to use remote grids stored on CDN (Content
|
||||
Delivery Network) storage, when they are not available locally.
|
||||
|
||||
More details are available in the :ref:`network` section.
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
|
||||
@@ -171,6 +171,16 @@ normally be in DMS format (use ``-f %.12f`` for decimal degrees with 12 decimal
|
||||
places), while projected (cartesian) coordinates will be in linear
|
||||
(meter, feet) units.
|
||||
|
||||
Use of remote grids
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
If the :envvar:`PROJ_NETWORK` environment variable is set to ``ON``,
|
||||
:program:`cs2cs` will attempt to use remote grids stored on CDN (Content
|
||||
Delivery Network) storage, when they are not available locally.
|
||||
|
||||
More details are available in the :ref:`network` section.
|
||||
|
||||
Examples
|
||||
********
|
||||
|
||||
@@ -20,7 +20,7 @@ Synopsis
|
||||
| [[--area name_or_code] | [--bbox west_long,south_lat,east_long,north_lat]]
|
||||
| [--spatial-test contains|intersects]
|
||||
| [--crs-extent-use none|both|intersection|smallest]
|
||||
| [--grid-check none|discard_missing|sort] [--show-superseded]
|
||||
| [--grid-check none|discard_missing|sort|known_available] [--show-superseded]
|
||||
| [--pivot-crs always|if_no_direct_transformation|never|{auth:code[,auth:code]*}]
|
||||
| [--boundcrs-to-wgs84]
|
||||
| [--main-db-path path] [--aux-db-path path]*
|
||||
@@ -151,12 +151,13 @@ The following control parameters can appear in any order:
|
||||
|
||||
.. note:: only used for coordinate operation computation
|
||||
|
||||
.. option:: --grid-check none|discard_missing|sort
|
||||
.. option:: --grid-check none|discard_missing|sort|known_available
|
||||
|
||||
Specify how the presence or absence of a horizontal or vertical shift grid
|
||||
required for a coordinate operation affects the results returned when
|
||||
researching coordinate operations between 2 CRS.
|
||||
The default strategy is ``sort``: in that case, all candidate
|
||||
The default strategy is ``sort`` (if :envvar:`PROJ_NETWORK` is not defined).
|
||||
In that case, all candidate
|
||||
operations are returned, but the actual availability of the grids is used
|
||||
to determine the sorting order. That is, if a coordinate operation involves
|
||||
using a grid that is not available in the PROJ resource directories
|
||||
@@ -166,6 +167,9 @@ The following control parameters can appear in any order:
|
||||
this returns the results as if all the grids where available.
|
||||
The ``discard_missing`` strategy discards results that involve grids not
|
||||
present in the PROJ resource directories.
|
||||
The ``known_available`` strategy discards results that involve grids not
|
||||
present in the PROJ resource directories and that are not known of the CDN.
|
||||
This is the default strategy is :envvar:`PROJ_NETWORK` is set to ``ON``.
|
||||
|
||||
.. note:: only used for coordinate operation computation
|
||||
|
||||
|
||||
@@ -695,613 +695,11 @@ choice.
|
||||
|
||||
.. _description_geotiff_format:
|
||||
|
||||
Description of the PROJ GeoTIFF format
|
||||
++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
The general principles that guide the following requirements and recommendations
|
||||
are such that files will be properly recognized by PROJ, and also by GDAL which
|
||||
is an easy way to inspect such grid files:
|
||||
|
||||
- `TIFF 6.0 <https://www.awaresystems.be/imaging/tiff/specification/TIFF6.pdf>`_
|
||||
based (could possibly be BigTIFF without code changes, if we ever
|
||||
need some day to handle grids larger than 4GB)
|
||||
|
||||
- `GeoTIFF 1.1 <http://docs.opengeospatial.org/is/19-008r4/19-008r4.html>`_ for the georeferencing.
|
||||
GeoTIFF 1.1 is a recent standard, compared to the original GeoTIFF 1.0 version,
|
||||
but its backward compatibility is excellent, so that should not cause much trouble
|
||||
to readers that are not official GeoTIFF 1.1 compliant.
|
||||
|
||||
- Files hosted on the CDN will use a Geographic 2D CRS for the GeoTIFF GeoKeys.
|
||||
That CRS is intended to be the interpolation CRS as defined in
|
||||
`OGC Abstract Specification Topic 2 <http://docs.opengeospatial.org/as/18-005r4/18-005r4.html>`_,
|
||||
that is the CRS to which grid values are refered to.
|
||||
|
||||
Given that they will nominally be related to the EPSG dataset, the `GeodeticCRSGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_geodeticcrsgeokey>`_
|
||||
will be used to store the EPSG code of the CRS. If the CRS cannot be reliably
|
||||
encoded through that key or other geokeys, the ``interpolation_crs_wkt`` metadata
|
||||
item detailed afterwards should be used.
|
||||
|
||||
This CRS will be generally the source CRS (for geographic to
|
||||
geographic horizontal shift grids, or geographic to vertical shift grids), but
|
||||
for vertical to vertical CRS adjustment, this will be the geographic CRS to
|
||||
which the grid is referenced. In some very rare cases of geographic to vertical
|
||||
shift grids, the interpolation CRS might be a geographic CRS that is not the
|
||||
same as the source CRS (into which ellipsoidal height are expressed). The only
|
||||
instance we have in mind is for the EPSG:7001 "ETRS89 to NAP height (1)" transformation
|
||||
using the naptrans2008 VDatum-grid which is referenced to Amersfoort EPSG:4289
|
||||
instead of ETRS89...
|
||||
|
||||
On the reading side, PROJ will ignore that information:
|
||||
the CRS is already stored in the source_crs or interpolation_crs column of the
|
||||
grid_transformation table.
|
||||
|
||||
For geographic to vertical shift files (geoid models), the GeoTIFF 1.1
|
||||
convention will be used to store the value of the `VerticalGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_verticalgeokey>`_
|
||||
So a geoid model that apply to WGS 84 EPSG:4979 will have GeodeticCRSGeoKey = 4326
|
||||
and VerticalGeoKey = 4979.
|
||||
|
||||
- Files hosted on the CDN will use the GeoTIFF defined `ModelTiepointTag and ModelPixelScaleTag
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_raster_to_model_coordinate_transformation_requirements>`_ TIFF tags
|
||||
to store the coordinates of the upper-left pixel and the resolution of the pixels.
|
||||
On the reading side, they will be required and ModelTransformationTag will be ignored.
|
||||
|
||||
.. note::
|
||||
|
||||
Regarding anti-meridian handling, a variety of possibilities exist.
|
||||
We do not attempt to standardize this and filesh hosted on the CDN will use
|
||||
a georeferencing close to the original data producer.
|
||||
For example, NOAA vertical grids that apply to Conterminous USA might even have a top-left
|
||||
longitude beyond 180 (for consistency with Alaska grids, whose origin is < 180)
|
||||
Anti-meridian handling in PROJ has probably issues. This RFC does not attempt
|
||||
to address them in particular, as they are believed to be orthogonal to the
|
||||
topics it covers, and being mostly implementation issues.
|
||||
|
||||
- Files hosted on the CDN will use the `GTRasterTypeGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_gtrastertypegeokey>`_
|
||||
= PixelIsPoint convention.
|
||||
This is the convention used by most existing grid formats currently. Note that GDAL
|
||||
typically use a PixelIsArea convention (but can handle both conventions), so the
|
||||
georeferencing it displays when opening a .gsb or .gtx file appears to have a
|
||||
half-pixel shift regarding to the coordinates stored in the original grid file. On
|
||||
the reading side, PROJ will accept both conventions (for equivalent georeferencing,
|
||||
the value of the origin in a PixelIsArea convention is shifted by a half-pixel
|
||||
towards the upper-left direction). Unspecified behaviour if this GeoKey is absent.
|
||||
|
||||
- Files hosted on the CDN will be tiled, presumably with 256x256 tiles (small
|
||||
grids that are smaller than 256x256 will use a single strip). On the reading
|
||||
side, PROJ will accept TIFF files with any strip or tile organization.
|
||||
Tiling is expressed by specifying the TileWidth, TileHeight, TileOffsets
|
||||
and TileByteCounts tags. Strip organization is expressed by specifying the
|
||||
RowsPerStrip, StripByteCounts and StripOffsets tags.
|
||||
|
||||
- Files hosted on the CDN will use `Compression
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/compression.html>`_ = DEFLATE
|
||||
or LZW (to be determined, possibly with
|
||||
`Predictor <https://www.awaresystems.be/imaging/tiff/tifftags/predictor.html>`_ = 2
|
||||
or 3)
|
||||
On the reading side, PROJ will accept TIFF files with any compression method
|
||||
(appropriate for the data types and PhotometricInterpretation considered)
|
||||
supported by the libtiff build used by PROJ. Of course uncompressed files will be supported.
|
||||
|
||||
- Files hosted on the CDN will use little-endian byte ordering. On the reading
|
||||
side, libtiff will transparently handle both little-endian and big-endian
|
||||
ordering.
|
||||
|
||||
- Files hosted on the CDN will use PlanarConfiguration=Separate.
|
||||
The tools described in a later section will order blocks so that blocks needed
|
||||
for a given location are close to each other.
|
||||
On the reading side, PROJ will handle also PlanarConfiguration=Contig.
|
||||
|
||||
- Files hosted on the CDN will generally use Float32 (BitsPerSample=32 and SampleFormat=IEEEFP)
|
||||
Files may be created using Signed Int 16 (
|
||||
`BitsPerSample <https://www.awaresystems.be/imaging/tiff/tifftags/bitspersample.html>`_ =16 and
|
||||
`SampleFormat <https://www.awaresystems.be/imaging/tiff/tifftags/sampleformat.html>`_ = INT),
|
||||
Unsigned Int 16 (BitsPerSample=16 and SampleFormat=UINT), Signed Int 32 or Unsigned Int 32 generally with an
|
||||
associate scale/offset.
|
||||
On the reading side, only those three data types will be supported as well.
|
||||
|
||||
- Files hosted on the CDN will have a `PhotometricInterpretation
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/photometricinterpretation.html>`_ = MinIsBlack.
|
||||
It will be assumed, and ignored on the reading side.
|
||||
|
||||
- Files hosted on the CDN will nominally have:
|
||||
|
||||
* `SamplesPerPixel <https://www.awaresystems.be/imaging/tiff/tifftags/samplesperpixel.html>`_ = 2
|
||||
for horizontal shift grid, with the first sample being the longitude offset
|
||||
and the second sample being the latitude offset.
|
||||
|
||||
* SamplesPerPixel = 1 for vertical shift grids.
|
||||
|
||||
In the future, different values of SamplesPerPixel may be used to accomodate
|
||||
for other needs. For example for deformation models, SamplesPerPixel = 3 to combine
|
||||
horizontal and vertical adjustments.
|
||||
And even for the current identified needs of horizontal or vertical shifts,
|
||||
more samples may be present (to indicate for example uncertainties), but
|
||||
will be ignored by PROJ.
|
||||
|
||||
The `ExtraSamples <https://www.awaresystems.be/imaging/tiff/tifftags/extrasamples.html>`_
|
||||
tag should be set to a value of SamplesPerPixel - 1 (given the rules that
|
||||
apply for PhotometricInterpretation = MinIsBlack)
|
||||
|
||||
- The `ImageDescription <https://www.awaresystems.be/imaging/tiff/tifftags/imagedescription.html>`_
|
||||
tag may be used to convey extra information about the name, provenance, version
|
||||
and last updated date of the grid.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- The `Copyright <https://www.awaresystems.be/imaging/tiff/tifftags/copyright.html>`_
|
||||
tag may be used to convey extra information about the copyright and license of the grid.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- The `DateTime <https://www.awaresystems.be/imaging/tiff/tifftags/datetime.html>`_
|
||||
tag may be used to convey the date at which the file has been created or
|
||||
converted. In case of a file conversion, for example from NTv2, this will be
|
||||
the date at which the conversion has been performed. The ``ImageDescription``
|
||||
tag however will contain the latest of the CREATED or UPDATED fields from the NTv2 file.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- Files hosted on the CDN will use the `GDAL_NODATA
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/gdal_nodata.html>`_ tag to encode
|
||||
the value of the nodata / missing value, when it applies to the grid.
|
||||
|
||||
If offset and/or scaling is used, the nodata value corresponds to the raw value,
|
||||
before applying offset and scaling.
|
||||
The value found in this tag, if present, will be honoured (to the extent to
|
||||
which current PROJ code makes use of nodata).
|
||||
For floating point data, writers are strongly discouraged to use non-finite values
|
||||
(+/- infinity, NaN) of nodata to maximimize interoperability.
|
||||
The GDAL_NODATA value applies to all samples of a given TIFF IFD.
|
||||
|
||||
- Files hosted on the CDN will use the `GDAL_METADATA
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/gdal_metadata.html>`_ tag to encode extra
|
||||
metadata not supported by baseline or extended TIFF.
|
||||
|
||||
* The root XML node should be ``GDALMetadata``
|
||||
|
||||
* Zero, one or several child XML nodes ``Item`` may be present.
|
||||
|
||||
* A Item should have a ``name`` attribute, and a child text node with its value.
|
||||
``role`` and ``sample`` attributes may be present for attributes that have
|
||||
a special semantics (recognized by GDAL). The value of `sample` should be
|
||||
a integer value between 0 and number_of_samples - 1.
|
||||
|
||||
* Scale and offset to convert integer raw values to floating point values
|
||||
may be expressed with XML `Item` elements whose name attribute is respectively
|
||||
``SCALE`` and ``OFFSET``, and their ``role`` attribute is respectively ``scale``
|
||||
and ``offset``. The decoded value will be: {offset} + {scale} * raw_value_from_geotiff_file
|
||||
|
||||
For a offset value of 1 and scaling of 2, the following payload should be
|
||||
stored:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<GDALMetadata>
|
||||
<Item name="OFFSET" sample="0" role="offset">1</Item>
|
||||
<Item name="SCALE" sample="0" role="scale">2</Item>
|
||||
</GDALMetadata>
|
||||
|
||||
* The type of the grid must be specified with a `Item` whose ``name`` is set
|
||||
to ``TYPE``.
|
||||
|
||||
Values recognized by PROJ currently are:
|
||||
|
||||
- ``HORIZONTAL_OFFSET``: implies the presence of at least two samples.
|
||||
The first sample must contain the latitude offset and the second
|
||||
sample must contain the longitude offset.
|
||||
Corresponds to PROJ ``hgridshift`` method.
|
||||
|
||||
- ``VERTICAL_OFFSET_GEOGRAPHIC_TO_VERTICAL``: implies the presence of at least one sample.
|
||||
The first sample must contain the vertical adjustment. Must be used when
|
||||
the source/interpolation CRS is a Geographic CRS and the target CRS a Vertical CRS.
|
||||
Corresponds to PROJ ``vgridshift`` method.
|
||||
|
||||
- ``VERTICAL_OFFSET_VERTICAL_TO_VERTICAL``: implies the presence of at least one sample.
|
||||
The first sample must contain the vertical adjustment. Must be used when
|
||||
the source and target CRS are Vertical CRS.
|
||||
Corresponds to PROJ ``vgridshift`` method.
|
||||
|
||||
- ``GEOCENTRIC_TRANSLATION``: implies the presence of at least 3 samples.
|
||||
The first 3 samples must be respectively the geocentric adjustments along
|
||||
the X, Y and Z axis. Must be used when the source and target CRS are
|
||||
geocentric CRS. The interpolation CRS must be a geographic CRS.
|
||||
Corresponds to PROJ ``xyzgridshift`` method.
|
||||
|
||||
- ``VELOCITY``: implies the presence of at least 3 samples.
|
||||
The first 3 samples must be respectively the velocities along
|
||||
the E(ast), N(orth), U(p) axis in the local topocentric coordinate system.
|
||||
Corresponds to PROJ ``deformation`` method.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="TYPE">HORIZONTAL_OFFSET</Item>
|
||||
|
||||
* The description of each sample must be specified with a Item whose ``name``
|
||||
attribute is set to ``DESCRIPTION`` and ``role`` attribute to ``description``.
|
||||
|
||||
Values recognized by PROJ for this Item are currently:
|
||||
|
||||
+ ``latitude_offset``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the value to add a latitude expressed in the CRS encoded in the GeoKeys
|
||||
to obtain a latitude value expressed in the target CRS.
|
||||
|
||||
+ ``longitude_offset``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the value to add a longitude expressed in the CRS encoded in the GeoKeys
|
||||
to obtain a longitude value expressed in the target CRS.
|
||||
|
||||
+ ``geoid_undulation``: valid for TYPE=VERTICAL_OFFSET_GEOGRAPHIC_TO_VERTICAL.
|
||||
For a source CRS being a geographic CRS and a target CRS being a vertical CRS,
|
||||
sample values should be the value to add to a geoid-related height (that
|
||||
is expressed in the target CRS) to
|
||||
get an ellipsoidal height (that is expressed in the source CRS), also
|
||||
called the geoid undulation.
|
||||
Note the possible confusion related to what is the source CRS and target CRS and
|
||||
the semantics of the value stored (to convert from the source to the target,
|
||||
one must subtract the value contained in the grid). This is the convention
|
||||
used by the `EPSG:9665 <https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9665>`_
|
||||
operation method.
|
||||
|
||||
+ ``vertical_offset``: valid for TYPE=VERTICAL_OFFSET_VERTICAL_TO_VERTICAL.
|
||||
For a source and target CRS being vertical CRS,
|
||||
sample values should be the value to add to an elevation expressed in the
|
||||
source CRS to obtain a longitude value expressed in the target CRS.
|
||||
|
||||
+ ``x_translation`` / ``y_translation`` / ``z_translation``: valid for
|
||||
TYPE=GEOCENTRIC_TRANSLATION.
|
||||
Sample values should be the value to add to the input geocentric coordinates
|
||||
expressed in the source CRS to geocentric coordinates expressed in the target CRS.
|
||||
|
||||
+ ``east_velocity`` / ``north_velocity`` / ``up_velocity``: valid for
|
||||
TYPE=VELOCITY.
|
||||
Sample values should be the velocity in a linear/time unit in a ENU local
|
||||
topocentric coordinate system.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="DESCRIPTION" sample="0" role="description">latitude_offset</Item>
|
||||
<Item name="DESCRIPTION" sample="1" role="description">longitude_offset</Item>
|
||||
|
||||
Other values may be used (not used by PROJ):
|
||||
|
||||
+ ``latitude_offset_accuracy``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the accuracy of corresponding latitude_offset samples. Generally in metre (if converted from NTv2)
|
||||
|
||||
+ ``longitude_offset_accuracy``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the accuracy of corresponding longitude_offset samples. Generally in metre (if converted from NTv2)
|
||||
|
||||
* The sign convention for the values of the ``longitude_offset`` channel
|
||||
should be indicated with an Item named ``positive_value`` whose value
|
||||
can be ``west`` or ``east``. NTv2 products originally use a ``west``
|
||||
convention, but when converting from them to GeoTIFF, the sign of those
|
||||
samples will be inverted so they use a more natural ``east`` convention.
|
||||
If this item is absent, the default value is ``east``.
|
||||
|
||||
* The unit of the values stored in the grid must be specified for each
|
||||
sample through an Item of name ``UNITTYPE`` and role ``unittype``
|
||||
Valid values should be the name of entries from the EPSG ``unitofmeasure``
|
||||
table. To maximize interoperability, writers are strongly encouraged to
|
||||
limit themselves to the following values:
|
||||
|
||||
For linear units:
|
||||
|
||||
- ``metre`` (default value assumed if absent for vertical shift grid files, and value used for files stored on PROJ CDN)
|
||||
- ``US survey foot``
|
||||
|
||||
For angular units:
|
||||
|
||||
- ``degree``
|
||||
- ``arc-second`` (default value assumed if absent for longitude and latitude offset samples of horizontal shift grid files, and value used for files stored on PROJ CDN)
|
||||
|
||||
For velocity units:
|
||||
|
||||
- ``millimetres per year``
|
||||
|
||||
The longitude and latitude offset samples should use the same unit.
|
||||
The geocentric translation samples should use the same unit.
|
||||
The velocity samples should use the same unit.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="UNITTYPE" sample="0" role="unittype">arc-second</Item>
|
||||
<Item name="UNITTYPE" sample="1" role="unittype">arc-second</Item>
|
||||
|
||||
* The ``target_crs_epsg_code`` metadata item should be present.
|
||||
For a horizontal shift grid, this is the EPSG
|
||||
code of the target geographic CRS. For a vertical shift grid, this is the
|
||||
EPSG code of a the target vertical CRS.
|
||||
If the target CRS has no associated EPSG code, ``target_crs_wkt`` must be
|
||||
used.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``target_crs_wkt`` metadata item must be present if the
|
||||
``target_crs_epsg_code`` cannot be used.
|
||||
Its value should be a valid WKT string according to
|
||||
`WKT:2015 <http://docs.opengeospatial.org/is/12-063r5/12-063r5.html>`_
|
||||
or `WKT:2019 <hhttp://docs.opengeospatial.org/is/18-010r7/18-010r7.html>`_
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``source_crs_epsg_code`` metadata item must be present if the source
|
||||
and interpolation CRS are not the same (typical use case is vertical CRS to vertical CRS
|
||||
transformation), because the GeoKeys encode the interpolation CRS and not the source CRS.
|
||||
If the source CRS has no associated EPSG code, ``source_crs_wkt`` must be
|
||||
used.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``source_crs_wkt`` metadata item must be present if the
|
||||
``source_crs_epsg_code`` cannot be used.
|
||||
Its value should be a valid WKT string according to WKT:2015 or WKT:2019.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``interpolation_crs_wkt`` metadata item may be present if the GeoKeys
|
||||
cannot be used to express reliably the interpolation CRS.
|
||||
Its value should be a valid WKT string according to WKT:2015 or WKT:2019.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``recommended_interpolation_method`` metadata item may be present to
|
||||
describe the method to use to interpolation values at locations not
|
||||
coincident with nodes stored in the grid file. Potential values: ``bilinear``,
|
||||
``bicubic``.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``area_of_use`` metadata item can be used to indicate plain text information
|
||||
about the area of use of the grid (like "USA - Wisconsin"). In case of multiple
|
||||
subgrids, it should be set only on the first one, but applies to the whole
|
||||
set of grids, not just the first one.
|
||||
|
||||
* The ``grid_name`` metadata item should be present if there are
|
||||
subgrids for this grid (that is grids whose extent is contained in the extent
|
||||
of this grid), or if this is a subgrid.
|
||||
It is intended to be a relatively short identifier
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
* The ``parent_grid_name`` metadata item should be present if this is a
|
||||
subgrid and its value should be equal to the paren's ``grid_name``
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
* The ``number_of_nested_grids`` metadata item should be present if there are
|
||||
subgrids for this grid (that is grids whose extent is contained in the extent
|
||||
of this grid).
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
Example
|
||||
+++++++
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntf_r93.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/ntf_r93.gsb
|
||||
with https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_to_gtiff.py
|
||||
|
||||
::
|
||||
|
||||
$ tiffinfo ntf_r93.tif
|
||||
|
||||
TIFF Directory at offset 0x4e (78)
|
||||
Image Width: 156 Image Length: 111
|
||||
Bits/Sample: 32
|
||||
Sample Format: IEEE floating point
|
||||
Compression Scheme: AdobeDeflate
|
||||
Photometric Interpretation: min-is-black
|
||||
Extra Samples: 3<unspecified, unspecified, unspecified>
|
||||
Samples/Pixel: 4
|
||||
Rows/Strip: 111
|
||||
Planar Configuration: separate image planes
|
||||
ImageDescription: NTF (EPSG:4275) to RGF93 (EPSG:4171). Converted from ntf_r93.gsb (version IGN07_01, last updated on 2007-10-31)
|
||||
DateTime: 2019:12:09 00:00:00
|
||||
Copyright: Derived from work by IGN France. Open License https://www.etalab.gouv.fr/wp-content/uploads/2014/05/Open_Licence.pdf
|
||||
Tag 33550: 0.100000,0.100000,0.000000
|
||||
Tag 33922: 0.000000,0.000000,0.000000,-5.500000,52.000000,0.000000
|
||||
Tag 34735: 1,1,1,3,1024,0,1,2,1025,0,1,2,2048,0,1,4275
|
||||
Tag 42112: <GDALMetadata>
|
||||
<Item name="grid_name">FRANCE</Item>
|
||||
<Item name="target_crs_epsg_code">4171</Item>
|
||||
<Item name="TYPE">HORIZONTAL_OFFSET</Item>
|
||||
<Item name="UNITTYPE" sample="0" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="0" role="description">latitude_offset</Item>
|
||||
<Item name="positive_value" sample="1">east</Item>
|
||||
<Item name="UNITTYPE" sample="1" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="1" role="description">longitude_offset</Item>
|
||||
<Item name="UNITTYPE" sample="2" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="2" role="description">latitude_offset_accuracy</Item>
|
||||
<Item name="UNITTYPE" sample="3" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="3" role="description">longitude_offset_accuracy</Item>
|
||||
</GDALMetadata>
|
||||
|
||||
Predictor: floating point predictor 3 (0x3)
|
||||
|
||||
|
||||
::
|
||||
|
||||
$ listgeo ntf_r93.tif
|
||||
|
||||
Geotiff_Information:
|
||||
Version: 1
|
||||
Key_Revision: 1.1
|
||||
Tagged_Information:
|
||||
ModelTiepointTag (2,3):
|
||||
0 0 0
|
||||
-5.5 52 0
|
||||
ModelPixelScaleTag (1,3):
|
||||
0.1 0.1 0
|
||||
End_Of_Tags.
|
||||
Keyed_Information:
|
||||
GTModelTypeGeoKey (Short,1): ModelTypeGeographic
|
||||
GTRasterTypeGeoKey (Short,1): RasterPixelIsPoint
|
||||
GeodeticCRSGeoKey (Short,1): Code-4275 (NTF)
|
||||
End_Of_Keys.
|
||||
End_Of_Geotiff.
|
||||
|
||||
GCS: 4275/NTF
|
||||
Datum: 6275/Nouvelle Triangulation Francaise
|
||||
Ellipsoid: 7011/Clarke 1880 (IGN) (6378249.20,6356515.00)
|
||||
Prime Meridian: 8901/Greenwich (0.000000/ 0d 0' 0.00"E)
|
||||
Projection Linear Units: User-Defined (1.000000m)
|
||||
|
||||
Corner Coordinates:
|
||||
Upper Left ( 5d30' 0.00"W, 52d 0' 0.00"N)
|
||||
Lower Left ( 5d30' 0.00"W, 40d54' 0.00"N)
|
||||
Upper Right ( 10d 6' 0.00"E, 52d 0' 0.00"N)
|
||||
Lower Right ( 10d 6' 0.00"E, 40d54' 0.00"N)
|
||||
Center ( 2d18' 0.00"E, 46d27' 0.00"N)
|
||||
|
||||
::
|
||||
|
||||
$ gdalinfo ntf_r93.tif
|
||||
|
||||
Driver: GTiff/GeoTIFF
|
||||
Files: ntf_r93.tif
|
||||
Size is 156, 111
|
||||
Coordinate System is:
|
||||
GEOGCRS["NTF",
|
||||
DATUM["Nouvelle Triangulation Francaise",
|
||||
ELLIPSOID["Clarke 1880 (IGN)",6378249.2,293.466021293627,
|
||||
LENGTHUNIT["metre",1]]],
|
||||
PRIMEM["Greenwich",0,
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
CS[ellipsoidal,2],
|
||||
AXIS["geodetic latitude (Lat)",north,
|
||||
ORDER[1],
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
AXIS["geodetic longitude (Lon)",east,
|
||||
ORDER[2],
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
ID["EPSG",4275]]
|
||||
Data axis to CRS axis mapping: 2,1
|
||||
Origin = (-5.550000000000000,52.049999999999997)
|
||||
Pixel Size = (0.100000000000000,-0.100000000000000)
|
||||
Metadata:
|
||||
AREA_OR_POINT=Point
|
||||
grid_name=FRANCE
|
||||
target_crs_epsg_code=4171
|
||||
TIFFTAG_DATETIME=2019:12:09 00:00:00
|
||||
TIFFTAG_IMAGEDESCRIPTION=NTF (EPSG:4275) to RGF93 (EPSG:4171). Converted from ntf_r93.gsb (version IGN07_01, last updated on 2007-10-31)
|
||||
TYPE=HORIZONTAL_OFFSET
|
||||
Image Structure Metadata:
|
||||
COMPRESSION=DEFLATE
|
||||
INTERLEAVE=BAND
|
||||
Corner Coordinates:
|
||||
Upper Left ( -5.5500000, 52.0500000) ( 5d33' 0.00"W, 52d 3' 0.00"N)
|
||||
Lower Left ( -5.5500000, 40.9500000) ( 5d33' 0.00"W, 40d57' 0.00"N)
|
||||
Upper Right ( 10.0500000, 52.0500000) ( 10d 3' 0.00"E, 52d 3' 0.00"N)
|
||||
Lower Right ( 10.0500000, 40.9500000) ( 10d 3' 0.00"E, 40d57' 0.00"N)
|
||||
Center ( 2.2500000, 46.5000000) ( 2d15' 0.00"E, 46d30' 0.00"N)
|
||||
Band 1 Block=156x111 Type=Float32, ColorInterp=Gray
|
||||
Description = latitude_offset
|
||||
Unit Type: arc-second
|
||||
Band 2 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = longitude_offset
|
||||
Unit Type: arc-second
|
||||
Metadata:
|
||||
positive_value=east
|
||||
Band 3 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = latitude_offset_accuracy
|
||||
Unit Type: arc-second
|
||||
Band 4 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = longitude_offset_accuracy
|
||||
Unit Type: arc-second
|
||||
|
||||
Multi-grid storage
|
||||
Format description
|
||||
++++++++++++++++++
|
||||
|
||||
Formats like NTv2 can contain multiple subgrids. This can be transposed to
|
||||
TIFF by using several IFD chained together with the last 4 bytes (or 8 bytes
|
||||
for BigTIFF) of an IFD pointing to the offset of the next one.
|
||||
|
||||
The first IFD should have a full description according to the
|
||||
:ref:`Description of the PROJ GeoTIFF format <description_geotiff_format>`.
|
||||
Subsequent IFD might have a more compact description, omitting for example, CRS
|
||||
information if it is identical to the main IFD (which should be the case for
|
||||
the currently envisionned use cases), or Copyright / ImageDescription metadata
|
||||
items.
|
||||
|
||||
Each IFD will have its
|
||||
`NewSubfileType <https://www.awaresystems.be/imaging/tiff/tifftags/newsubfiletype.html>`_
|
||||
tag set to 0.
|
||||
|
||||
If a low-resolution grid is available, it should be put before subgrids of
|
||||
higher-resolution in the chain of IFD linking. On reading, PROJ will use the
|
||||
value from the highest-resoluted grid that contains the point of interest.
|
||||
|
||||
For efficient reading from the network, files hosted on the CDN will use
|
||||
a layout similar to the one described in the `low level paragraph of the Cloud Optimized GeoTIFF
|
||||
GDAL driver page <https://gdal.org/drivers/raster/cog.html#low-level>`_
|
||||
|
||||
The layout for a file converted from NTv2 will for example be:
|
||||
|
||||
- TIFF/BigTIFF header/signature and pointer to first IFD (Image File Directory)
|
||||
- "ghost area" indicating the generated process
|
||||
- IFD of the first grid, followed by TIFF tags values, excluding the TileOffsets and TileByteCounts arrays
|
||||
- ...
|
||||
- IFD of the last grid, followed by TIFF tags values, excluding the GDAL_METADATA tag, TileOffsets and TileByteCounts arrays
|
||||
- TileOffsets and TileByteCounts arrays for first IFD
|
||||
- ...
|
||||
- TileOffsets and TileByteCounts arrays for last IFD
|
||||
- Value of GDAL_METADATA tag for IFDs following the first IFD
|
||||
- First IFD: Data corresponding to latitude offset of Block_0_0
|
||||
- First IFD: Data corresponding to longitude offset of Block_0_0
|
||||
- First IFD: Data corresponding to latitude offset of Block_0_1
|
||||
- First IFD: Data corresponding to longitude offset of Block_0_1
|
||||
- ...
|
||||
- First IFD: Data corresponding to latitude offset of Block_n_m
|
||||
- First IFD: Data corresponding to longitude offset of Block_n_m
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset of Block_0_0
|
||||
- Last IFD: Data corresponding to longitude offset of Block_0_0
|
||||
- Last IFD: Data corresponding to latitude offset of Block_0_1
|
||||
- Last IFD: Data corresponding to longitude offset of Block_0_1
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset of Block_n_m
|
||||
- Last IFD: Data corresponding to longitude offset of Block_n_m
|
||||
|
||||
If longitude_offset_accuracy and latitude_offset_accuracy are present, this
|
||||
will be followed by:
|
||||
|
||||
- First IFD: Data corresponding to latitude offset accuracy of Block_0_0
|
||||
- First IFD: Data corresponding to longitude offset accuracy of Block_0_0
|
||||
- ...
|
||||
- First IFD: Data corresponding to latitude offset accuracy of Block_n_m
|
||||
- First IFD: Data corresponding to longitude offset accuracy of Block_n_m
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset accuracy of Block_0_0
|
||||
- Last IFD: Data corresponding to longitude offset accuracy of Block_0_0
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset accuracy of Block_n_m
|
||||
- Last IFD: Data corresponding to longitude offset accuracy of Block_n_m
|
||||
|
||||
.. note::
|
||||
|
||||
TIFF has another mechanism to link IFDs, the SubIFD tag. This potentially
|
||||
enables to define a hiearchy of IFDs (similar to HDF5 groups). There is no
|
||||
support for that in most TIFF-using software, notably GDAL, and no compelling
|
||||
need to have a nested hiearchy, so "flat" organization with the standard IFD chaining
|
||||
mechanism is adopted.
|
||||
|
||||
Examples of multi-grid dataset
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/GDA94_GDA2020_conformal.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/oceania/GDA94_GDA2020_conformal.gsb
|
||||
with https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_to_gtiff.py
|
||||
|
||||
It contains 5 subgrids. All essential metadata to list the subgrids and their
|
||||
georeferencing is contained within the first 3 KB of the file.
|
||||
|
||||
The file size is 4.8 MB using DEFLATE compression and floating-point predictor.
|
||||
To be compared with the 83 MB of the original .gsb file.
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_0.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/north-america/ntv2_0.gsb
|
||||
|
||||
It contains 114 subgrids. All essential metadata to list the subgrids and their
|
||||
georeferencing is contained within the first 40 KB of the file.
|
||||
|
||||
The format description is available in a dedicated :ref:`geodetictiffgrids`
|
||||
document.
|
||||
|
||||
Tooling
|
||||
+++++++
|
||||
|
||||
+1
-1
@@ -376,7 +376,7 @@ texinfo_documents = [
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
breathe_projects = {
|
||||
"cpp_stuff":"../build/xml/",
|
||||
"doxygen_api":"../build/xml/",
|
||||
}
|
||||
|
||||
import redirects
|
||||
|
||||
@@ -4,5 +4,5 @@ common namespace
|
||||
----------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::common
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,4 +4,4 @@ General documentation
|
||||
---------------------
|
||||
|
||||
.. doxygenfile:: general_doc.dox.reworked.h
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
|
||||
@@ -4,5 +4,5 @@ crs namespace
|
||||
-------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::crs
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ cs namespace
|
||||
------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::cs
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ datum namespace
|
||||
---------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::datum
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ io namespace
|
||||
------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::io
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ metadata namespace
|
||||
------------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::metadata
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ operation namespace
|
||||
-------------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::operation
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -4,5 +4,5 @@ util namespace
|
||||
--------------
|
||||
|
||||
.. doxygennamespace:: osgeo::proj::util
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
@@ -797,11 +797,48 @@ Logging
|
||||
.. versionadded:: 5.1.0
|
||||
|
||||
|
||||
Setting custom I/O functions
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
.. doxygenstruct:: PROJ_FILE_API
|
||||
:project: doxygen_api
|
||||
:members:
|
||||
|
||||
.. doxygentypedef:: PROJ_FILE_HANDLE
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenenum:: PROJ_OPEN_ACCESS
|
||||
:project: doxygen_api
|
||||
|
||||
|
||||
Network related functionality
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
.. doxygentypedef:: PROJ_NETWORK_HANDLE
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygentypedef:: proj_network_open_cbk_type
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygentypedef:: proj_network_close_cbk_type
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygentypedef:: proj_network_get_header_value_cbk_type
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygentypedef:: proj_network_read_range_type
|
||||
:project: doxygen_api
|
||||
|
||||
|
||||
C API for ISO-19111 functionality
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. doxygengroup:: iso19111_types
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:content-only:
|
||||
|
||||
|
||||
|
||||
@@ -697,6 +697,54 @@ Various
|
||||
:returns: :c:type:`int` 1 if output units is expected in radians, otherwise 0
|
||||
|
||||
|
||||
Setting custom I/O functions
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
.. doxygenfunction:: proj_context_set_fileapi
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_context_set_sqlite3_vfs_name
|
||||
:project: doxygen_api
|
||||
|
||||
|
||||
Network related functionality
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
.. doxygenfunction:: proj_context_set_network_callbacks
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_context_set_enable_network
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_context_set_url_endpoint
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_grid_cache_set_enable
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_grid_cache_set_filename
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_grid_cache_set_max_size
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_grid_cache_set_ttl
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_grid_cache_clear
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_is_download_needed
|
||||
:project: doxygen_api
|
||||
|
||||
.. doxygenfunction:: proj_download_file
|
||||
:project: doxygen_api
|
||||
|
||||
|
||||
Cleanup
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
@@ -727,6 +775,6 @@ which are not of type CRS (can be tested with :c:func:`proj_is_crs`),
|
||||
will return an error when used with functions of this section.
|
||||
|
||||
.. doxygengroup:: iso19111_functions
|
||||
:project: cpp_stuff
|
||||
:project: doxygen_api
|
||||
:content-only:
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ PROJ
|
||||
resource_files
|
||||
geodesic
|
||||
development/index
|
||||
specifications/index
|
||||
community/index
|
||||
faq
|
||||
glossary
|
||||
|
||||
@@ -35,6 +35,9 @@ GTX format. Both grids are expected to contain grid-values in units of
|
||||
mm/year. GDAL both reads and writes both file formats. Using GDAL for
|
||||
construction of new grids is recommended.
|
||||
|
||||
Starting with PROJ 7.0, use of a GeoTIFF format is recommended to store both
|
||||
the horizontal and vertical velocities.
|
||||
|
||||
Example
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -89,13 +92,15 @@ Parameters
|
||||
|
||||
.. option:: +xy_grids=<list>
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an `@` the
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an ``@`` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids for the horizontla component of a deformation model is expected to be
|
||||
Grids for the horizontal component of a deformation model is expected to be
|
||||
in CTable2 format.
|
||||
|
||||
.. note:: :option:`+xy_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
.. option:: +z_grids=<list>
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an `@` the
|
||||
@@ -105,6 +110,36 @@ Parameters
|
||||
Grids for the vertical component of a deformation model is expected to be
|
||||
in either GTX format.
|
||||
|
||||
.. note:: :option:`+z_grids` is mutually exclusive with :option:`+grids`
|
||||
|
||||
.. option:: +grids=<list>
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an `@` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids should be in GeoTIFF format with the first 3 components being
|
||||
respectively the easting, northing and up velocities in mm/year.
|
||||
Setting the Description and Unit Type GDAL band metadata items is strongly
|
||||
recommended, so that gdalinfo reports:
|
||||
|
||||
::
|
||||
|
||||
Band 1 Block=... Type=Float32, ColorInterp=Gray
|
||||
Description = east_velocity
|
||||
Unit Type: mm/year
|
||||
Band 2 Block=... Type=Float32, ColorInterp=Undefined
|
||||
Description = north_velocity
|
||||
Unit Type: mm/year
|
||||
Band 3 Block=... Type=Float32, ColorInterp=Undefined
|
||||
Description = up_velocity
|
||||
Unit Type: mm/year
|
||||
|
||||
.. note:: :option:`+grids` is mutually exclusive with :option:`+xy_grids`
|
||||
and :option:`+z_grids`
|
||||
|
||||
.. option:: +t_epoch=<value>
|
||||
|
||||
Central epoch of transformation given in decimalyears. Will be used in
|
||||
|
||||
@@ -19,3 +19,4 @@ systems are based on different datums.
|
||||
molobadekas
|
||||
hgridshift
|
||||
vgridshift
|
||||
xyzgridshift
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
.. _xyzgridshift:
|
||||
|
||||
================================================================================
|
||||
Geocentric grid shift
|
||||
================================================================================
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
Geocentric translation using a grid shift
|
||||
|
||||
+-----------------+-------------------------------------------------------------------+
|
||||
| **Domain** | 3D |
|
||||
+-----------------+-------------------------------------------------------------------+
|
||||
| **Input type** | Cartesian coordinates |
|
||||
+-----------------+-------------------------------------------------------------------+
|
||||
| **Output type** | Cartesian coordinates |
|
||||
+-----------------+-------------------------------------------------------------------+
|
||||
|
||||
Perform a geocentric translation by bilinear interpolation of dx, dy, dz
|
||||
translation values from a grid. The grid is referenced against either the
|
||||
2D geographic CRS corresponding to the input (or sometimes output) CRS.
|
||||
|
||||
This method is described (in French) in :cite:`NTF_88`
|
||||
and as EPSG operation method code 9655 in :cite:`IOGP2018` (§2.4.4.1.1
|
||||
France geocentric interpolation).
|
||||
|
||||
The translation in the grids are added to the input coordinates in the forward direction,
|
||||
and subtracted in the reverse direction.
|
||||
By default (if ``grid_ref=input_crs``), in the forward direction, the input coordinates
|
||||
are converted to their geographic equivalent to directly read and interpolate from
|
||||
the grid. In the reverse direction, an iterative method is used to be able to find
|
||||
the grid locations to read.
|
||||
If ``grid_ref=output_crs`` is used, then the reverse strategy is applied: iterative
|
||||
method in the forward direction, and direct read in the reverse direction.
|
||||
|
||||
Example
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
NTF to RGF93 transformation using gr3df97a.tif grid
|
||||
|
||||
::
|
||||
|
||||
+proj=pipeline
|
||||
+step +proj=push +v_3
|
||||
+step +proj=cart +ellps=clrk80ign
|
||||
+step +proj=xyzgridshift +grids=gr3df97a.tif +grid_ref=output_crs +ellps=GRS80
|
||||
+step +proj=cart +ellps=GRS80 +inv
|
||||
+step +proj=pop +v_3
|
||||
|
||||
Parameters
|
||||
################################################################################
|
||||
|
||||
The ellipsoid parameters should be the ones consistent with ``grid_ref``.
|
||||
They are used to perform a geocentric to geographic conversion to find the
|
||||
translation parameters.
|
||||
|
||||
|
||||
Required
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. include:: ../options/ellps.rst
|
||||
|
||||
.. option:: +grids=<list>
|
||||
|
||||
Comma-separated list of grids to load. If a grid is prefixed by an ``@`` the
|
||||
grid is considered optional and PROJ will the not complain if the grid is
|
||||
not available.
|
||||
|
||||
Grids are expected to be in GeoTIFF format. If no metadata is provided,
|
||||
the first, second and third samples are assumed to be the geocentric
|
||||
translation along X, Y and Z axis respectively, in metres.
|
||||
|
||||
Optional
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
.. option:: +grid_ref=input_crs/output_crs
|
||||
|
||||
Specify in which CRS the grid is referenced to. The default value is
|
||||
input_crs. That is the grid is referenced in the geographic CRS corresponding
|
||||
to the input geocentric CRS.
|
||||
|
||||
If output_crs is specified, the grid is referenced in the geographic CRS corresponding
|
||||
to the output geocentric CRS. This is for example the case for the French
|
||||
gr3df97a.tif grid converting from NTF to RGF93, but referenced against RGF93.
|
||||
Thus in the forward direction (NTF->RGF93), an iterative method is used to find
|
||||
the appropriate shift.
|
||||
|
||||
.. option:: +multiplier=<value>
|
||||
|
||||
Specify the multiplier to apply to the grid values. Defaults to 1.0
|
||||
|
||||
@@ -229,6 +229,15 @@
|
||||
Doi = {10.2312/PE/PG/PG2012short/005-010}
|
||||
}
|
||||
|
||||
@TechReport{NTF_88,
|
||||
Title = {Grille de parametres de transformation de coordonnees - {GR3DF97A} - Notice d'utilisation},
|
||||
Author = {IGN},
|
||||
Institution = {Service de Geodesie et Nivellement, Institut Geographique National},
|
||||
Year = {1997},
|
||||
|
||||
Url = {https://geodesie.ign.fr/contenu/fichiers/documentation/algorithmes/notice/NTG_88.pdf}
|
||||
}
|
||||
|
||||
@TechReport{ONeilLaubscher1976,
|
||||
Title = {Extended Studies of a Quadrilateralized Spherical Cube Earth Data Base},
|
||||
Author = {E. M. O'Neill and R. E. Laubscher},
|
||||
|
||||
@@ -14,6 +14,8 @@ In addition to the bundled init-files the PROJ project also distributes a number
|
||||
of packages containing transformation grids and additional init-files not included
|
||||
in the main PROJ package.
|
||||
|
||||
.. _resource_file_paths:
|
||||
|
||||
Where are PROJ resource files looked for ?
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
@@ -23,23 +25,43 @@ The following paths are checked in order:
|
||||
|
||||
- For transformation grids that have an explict relative or absolute path,
|
||||
the directory specified in the grid filename.
|
||||
|
||||
- Path resolved by the callback function set with
|
||||
the :c:func:`proj_context_set_file_finder`. If it is set, the next tests
|
||||
will not be run.
|
||||
|
||||
- Path(s) set with the :c:func:`proj_context_set_search_paths`. If set, the
|
||||
next tests will not be run.
|
||||
|
||||
.. _user_writable_directory:
|
||||
|
||||
- The PROJ user writable directory, which is :
|
||||
|
||||
* on Windows, ${LOCALAPPDATA}/proj
|
||||
* on MacOSX, ${HOME}/Library/Application Support/proj
|
||||
* on other platforms (Linux), ${XDG_DATA_HOME}/proj if :envvar:`XDG_DATA_HOME`
|
||||
is defined. Else ${HOME}/.local/share/proj
|
||||
|
||||
- Path(s) set with by the environment variable :envvar:`PROJ_LIB`.
|
||||
On Linux/MacOSX/Unix, use ``:`` to separate paths. On Windows, ``;``
|
||||
|
||||
- On Windows, the *..\\share\\proj\\* and its contents are found automatically
|
||||
at run-time if the installation respects the build structure. That is, the
|
||||
binaries and proj.dll are installed under *..\\bin\\*, and resource files
|
||||
are in *..\\share\\proj\\*.
|
||||
|
||||
- A path built into PROJ as its resource installation directory (whose value is
|
||||
$(pkgdatadir)), for builds using the Makefile build system. Note, however,
|
||||
that since this is a hard-wired path setting, it only works if the whole
|
||||
PROJ installation is not moved somewhere else.
|
||||
|
||||
- The current directory
|
||||
|
||||
When networking capabilities are enabled, either by API with the
|
||||
:c:func:`proj_context_set_enable_network` function or when the
|
||||
:envvar:`PROJ_NETWORK` environment variable is set to ``ON``, PROJ will
|
||||
attempt to use remote grids stored on CDN (Content Delivery Network) storage.
|
||||
|
||||
.. _proj-db:
|
||||
|
||||
proj.db
|
||||
@@ -49,6 +71,38 @@ A proj installation includes a SQLite database of transformation information
|
||||
that must be accessible for the library to work properly. The library will
|
||||
print an error if the database can't be found.
|
||||
|
||||
.. _proj-ini:
|
||||
|
||||
proj.ini
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 7.0
|
||||
|
||||
proj.ini is a text configuration file, mostly dedicated at setting up network
|
||||
related parameters.
|
||||
|
||||
Its default content is:
|
||||
|
||||
::
|
||||
|
||||
[general]
|
||||
; Lines starting by ; are commented lines.
|
||||
;
|
||||
|
||||
; Network capabilities disabled by default.
|
||||
; Can be overriden with the PROJ_NETWORK=ON environment variable.
|
||||
; network = on
|
||||
|
||||
; Can be overriden with the PROJ_NETWORK_ENDPOINT environment variable.
|
||||
cdn_endpoint = https://cdn.proj.org
|
||||
|
||||
cache_enabled = on
|
||||
|
||||
cache_size_MB = 300
|
||||
|
||||
cache_ttl_sec = 86400
|
||||
|
||||
|
||||
Transformation grids
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,626 @@
|
||||
.. _geodetictiffgrids:
|
||||
|
||||
================================================================================
|
||||
Geodetic TIFF grids (GTG)
|
||||
================================================================================
|
||||
|
||||
.. versionadded:: 7.0
|
||||
|
||||
Introduction
|
||||
++++++++++++
|
||||
|
||||
The Geodetic TIFF grid format has been introduced per :ref:`rfc4`. It is a
|
||||
profile of the TIFF and GeoTIFF formats that addresses the specific requirements
|
||||
of geodetic grids: horizontal shifts, vertical shifts, velocity grids, etc...
|
||||
It also follows the `Cloud Optimized GeoTIFF <http://cogeo.org>`_ principles.
|
||||
|
||||
Such grids are available on a :ref:`CDN of GeoTIFF grids <cdn_grids>`.
|
||||
|
||||
.. _gtg_general_description:
|
||||
|
||||
General description
|
||||
+++++++++++++++++++
|
||||
|
||||
The general principles that guide the following requirements and recommendations
|
||||
are such that files will be properly recognized by PROJ, and also by GDAL which
|
||||
is an easy way to inspect such grid files:
|
||||
|
||||
- `TIFF 6.0 <https://www.awaresystems.be/imaging/tiff/specification/TIFF6.pdf>`_
|
||||
based (could possibly be BigTIFF without code changes, if we ever
|
||||
need some day to handle grids larger than 4GB)
|
||||
|
||||
- `GeoTIFF 1.1 <http://docs.opengeospatial.org/is/19-008r4/19-008r4.html>`_ for the georeferencing.
|
||||
GeoTIFF 1.1 is a recent standard, compared to the original GeoTIFF 1.0 version,
|
||||
but its backward compatibility is excellent, so that should not cause much trouble
|
||||
to readers that are not official GeoTIFF 1.1 compliant.
|
||||
|
||||
- Files hosted on the CDN will use a Geographic 2D CRS for the GeoTIFF GeoKeys.
|
||||
That CRS is intended to be the interpolation CRS as defined in
|
||||
`OGC Abstract Specification Topic 2 <http://docs.opengeospatial.org/as/18-005r4/18-005r4.html>`_,
|
||||
that is the CRS to which grid values are refered to.
|
||||
|
||||
Given that they will nominally be related to the EPSG dataset, the `GeodeticCRSGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_geodeticcrsgeokey>`_
|
||||
will be used to store the EPSG code of the CRS. If the CRS cannot be reliably
|
||||
encoded through that key or other geokeys, the ``interpolation_crs_wkt`` metadata
|
||||
item detailed afterwards should be used.
|
||||
|
||||
This CRS will be generally the source CRS (for geographic to
|
||||
geographic horizontal shift grids, or geographic to vertical shift grids), but
|
||||
for vertical to vertical CRS adjustment, this will be the geographic CRS to
|
||||
which the grid is referenced. In some very rare cases of geographic to vertical
|
||||
shift grids, the interpolation CRS might be a geographic CRS that is not the
|
||||
same as the source CRS (into which ellipsoidal height are expressed). The only
|
||||
instance we have in mind is for the EPSG:7001 "ETRS89 to NAP height (1)" transformation
|
||||
using the naptrans2008 VDatum-grid which is referenced to Amersfoort EPSG:4289
|
||||
instead of ETRS89...
|
||||
|
||||
On the reading side, PROJ will ignore that information:
|
||||
the CRS is already stored in the source_crs or interpolation_crs column of the
|
||||
grid_transformation table.
|
||||
|
||||
For geographic to vertical shift files (geoid models), the GeoTIFF 1.1
|
||||
convention will be used to store the value of the `VerticalGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_verticalgeokey>`_
|
||||
So a geoid model that apply to WGS 84 EPSG:4979 will have GeodeticCRSGeoKey = 4326
|
||||
and VerticalGeoKey = 4979.
|
||||
|
||||
- Files hosted on the CDN will use the GeoTIFF defined `ModelTiepointTag and ModelPixelScaleTag
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_raster_to_model_coordinate_transformation_requirements>`_ TIFF tags
|
||||
to store the coordinates of the upper-left pixel and the resolution of the pixels.
|
||||
On the reading side, they will be required and ModelTransformationTag will be ignored.
|
||||
|
||||
.. note::
|
||||
|
||||
Regarding anti-meridian handling, a variety of possibilities exist.
|
||||
We do not attempt to standardize this and filesh hosted on the CDN will use
|
||||
a georeferencing close to the original data producer.
|
||||
For example, NOAA vertical grids that apply to Conterminous USA might even have a top-left
|
||||
longitude beyond 180 (for consistency with Alaska grids, whose origin is < 180)
|
||||
Anti-meridian handling in PROJ has probably issues. This RFC does not attempt
|
||||
to address them in particular, as they are believed to be orthogonal to the
|
||||
topics it covers, and being mostly implementation issues.
|
||||
|
||||
- Files hosted on the CDN will use the `GTRasterTypeGeoKey
|
||||
<http://docs.opengeospatial.org/is/19-008r4/19-008r4.html#_requirements_class_gtrastertypegeokey>`_
|
||||
= PixelIsPoint convention.
|
||||
This is the convention used by most existing grid formats currently. Note that GDAL
|
||||
typically use a PixelIsArea convention (but can handle both conventions), so the
|
||||
georeferencing it displays when opening a .gsb or .gtx file appears to have a
|
||||
half-pixel shift regarding to the coordinates stored in the original grid file. On
|
||||
the reading side, PROJ will accept both conventions (for equivalent georeferencing,
|
||||
the value of the origin in a PixelIsArea convention is shifted by a half-pixel
|
||||
towards the upper-left direction). Unspecified behaviour if this GeoKey is absent.
|
||||
|
||||
- Files hosted on the CDN will be tiled, presumably with 256x256 tiles (small
|
||||
grids that are smaller than 256x256 will use a single strip). On the reading
|
||||
side, PROJ will accept TIFF files with any strip or tile organization.
|
||||
Tiling is expressed by specifying the TileWidth, TileHeight, TileOffsets
|
||||
and TileByteCounts tags. Strip organization is expressed by specifying the
|
||||
RowsPerStrip, StripByteCounts and StripOffsets tags.
|
||||
|
||||
- Files hosted on the CDN will use `Compression
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/compression.html>`_ = DEFLATE
|
||||
or LZW (to be determined, possibly with
|
||||
`Predictor <https://www.awaresystems.be/imaging/tiff/tifftags/predictor.html>`_ = 2
|
||||
or 3)
|
||||
On the reading side, PROJ will accept TIFF files with any compression method
|
||||
(appropriate for the data types and PhotometricInterpretation considered)
|
||||
supported by the libtiff build used by PROJ. Of course uncompressed files will be supported.
|
||||
|
||||
- Files hosted on the CDN will use little-endian byte ordering. On the reading
|
||||
side, libtiff will transparently handle both little-endian and big-endian
|
||||
ordering.
|
||||
|
||||
- Files hosted on the CDN will use PlanarConfiguration=Separate.
|
||||
The tools described in a later section will order blocks so that blocks needed
|
||||
for a given location are close to each other.
|
||||
On the reading side, PROJ will handle also PlanarConfiguration=Contig.
|
||||
|
||||
- Files hosted on the CDN will generally use Float32 (BitsPerSample=32 and SampleFormat=IEEEFP)
|
||||
Files may be created using Signed Int 16 (
|
||||
`BitsPerSample <https://www.awaresystems.be/imaging/tiff/tifftags/bitspersample.html>`_ =16 and
|
||||
`SampleFormat <https://www.awaresystems.be/imaging/tiff/tifftags/sampleformat.html>`_ = INT),
|
||||
Unsigned Int 16 (BitsPerSample=16 and SampleFormat=UINT), Signed Int 32 or Unsigned Int 32 generally with an
|
||||
associate scale/offset.
|
||||
On the reading side, only those three data types will be supported as well.
|
||||
|
||||
- Files hosted on the CDN will have a `PhotometricInterpretation
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/photometricinterpretation.html>`_ = MinIsBlack.
|
||||
It will be assumed, and ignored on the reading side.
|
||||
|
||||
- Files hosted on the CDN will nominally have:
|
||||
|
||||
* `SamplesPerPixel <https://www.awaresystems.be/imaging/tiff/tifftags/samplesperpixel.html>`_ = 2
|
||||
for horizontal shift grid, with the first sample being the longitude offset
|
||||
and the second sample being the latitude offset.
|
||||
|
||||
* SamplesPerPixel = 1 for vertical shift grids.
|
||||
|
||||
In the future, different values of SamplesPerPixel may be used to accomodate
|
||||
for other needs. For example for deformation models, SamplesPerPixel = 3 to combine
|
||||
horizontal and vertical adjustments.
|
||||
And even for the current identified needs of horizontal or vertical shifts,
|
||||
more samples may be present (to indicate for example uncertainties), but
|
||||
will be ignored by PROJ.
|
||||
|
||||
The `ExtraSamples <https://www.awaresystems.be/imaging/tiff/tifftags/extrasamples.html>`_
|
||||
tag should be set to a value of SamplesPerPixel - 1 (given the rules that
|
||||
apply for PhotometricInterpretation = MinIsBlack)
|
||||
|
||||
- The `ImageDescription <https://www.awaresystems.be/imaging/tiff/tifftags/imagedescription.html>`_
|
||||
tag may be used to convey extra information about the name, provenance, version
|
||||
and last updated date of the grid.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- The `Copyright <https://www.awaresystems.be/imaging/tiff/tifftags/copyright.html>`_
|
||||
tag may be used to convey extra information about the copyright and license of the grid.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- The `DateTime <https://www.awaresystems.be/imaging/tiff/tifftags/datetime.html>`_
|
||||
tag may be used to convey the date at which the file has been created or
|
||||
converted. In case of a file conversion, for example from NTv2, this will be
|
||||
the date at which the conversion has been performed. The ``ImageDescription``
|
||||
tag however will contain the latest of the CREATED or UPDATED fields from the NTv2 file.
|
||||
Will be set when possible fo files hosted on the CDN.
|
||||
Ignored by PROJ.
|
||||
|
||||
- Files hosted on the CDN will use the `GDAL_NODATA
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/gdal_nodata.html>`_ tag to encode
|
||||
the value of the nodata / missing value, when it applies to the grid.
|
||||
|
||||
If offset and/or scaling is used, the nodata value corresponds to the raw value,
|
||||
before applying offset and scaling.
|
||||
The value found in this tag, if present, will be honoured (to the extent to
|
||||
which current PROJ code makes use of nodata).
|
||||
For floating point data, writers are strongly discouraged to use non-finite values
|
||||
(+/- infinity, NaN) of nodata to maximimize interoperability.
|
||||
The GDAL_NODATA value applies to all samples of a given TIFF IFD.
|
||||
|
||||
- Files hosted on the CDN will use the `GDAL_METADATA
|
||||
<https://www.awaresystems.be/imaging/tiff/tifftags/gdal_metadata.html>`_ tag to encode extra
|
||||
metadata not supported by baseline or extended TIFF.
|
||||
|
||||
* The root XML node should be ``GDALMetadata``
|
||||
|
||||
* Zero, one or several child XML nodes ``Item`` may be present.
|
||||
|
||||
* A Item should have a ``name`` attribute, and a child text node with its value.
|
||||
``role`` and ``sample`` attributes may be present for attributes that have
|
||||
a special semantics (recognized by GDAL). The value of `sample` should be
|
||||
a integer value between 0 and number_of_samples - 1.
|
||||
|
||||
* Scale and offset to convert integer raw values to floating point values
|
||||
may be expressed with XML `Item` elements whose name attribute is respectively
|
||||
``SCALE`` and ``OFFSET``, and their ``role`` attribute is respectively ``scale``
|
||||
and ``offset``. The decoded value will be: {offset} + {scale} * raw_value_from_geotiff_file
|
||||
|
||||
For a offset value of 1 and scaling of 2, the following payload should be
|
||||
stored:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<GDALMetadata>
|
||||
<Item name="OFFSET" sample="0" role="offset">1</Item>
|
||||
<Item name="SCALE" sample="0" role="scale">2</Item>
|
||||
</GDALMetadata>
|
||||
|
||||
* The type of the grid must be specified with a `Item` whose ``name`` is set
|
||||
to ``TYPE``.
|
||||
|
||||
Values recognized by PROJ currently are:
|
||||
|
||||
- ``HORIZONTAL_OFFSET``: implies the presence of at least two samples.
|
||||
The first sample must contain the latitude offset and the second
|
||||
sample must contain the longitude offset.
|
||||
Corresponds to PROJ ``hgridshift`` method.
|
||||
|
||||
- ``VERTICAL_OFFSET_GEOGRAPHIC_TO_VERTICAL``: implies the presence of at least one sample.
|
||||
The first sample must contain the vertical adjustment. Must be used when
|
||||
the source/interpolation CRS is a Geographic CRS and the target CRS a Vertical CRS.
|
||||
Corresponds to PROJ ``vgridshift`` method.
|
||||
|
||||
- ``VERTICAL_OFFSET_VERTICAL_TO_VERTICAL``: implies the presence of at least one sample.
|
||||
The first sample must contain the vertical adjustment. Must be used when
|
||||
the source and target CRS are Vertical CRS.
|
||||
Corresponds to PROJ ``vgridshift`` method.
|
||||
|
||||
- ``GEOCENTRIC_TRANSLATION``: implies the presence of at least 3 samples.
|
||||
The first 3 samples must be respectively the geocentric adjustments along
|
||||
the X, Y and Z axis. Must be used when the source and target CRS are
|
||||
geocentric CRS. The interpolation CRS must be a geographic CRS.
|
||||
Corresponds to PROJ ``xyzgridshift`` method.
|
||||
|
||||
- ``VELOCITY``: implies the presence of at least 3 samples.
|
||||
The first 3 samples must be respectively the velocities along
|
||||
the E(ast), N(orth), U(p) axis in the local topocentric coordinate system.
|
||||
Corresponds to PROJ ``deformation`` method.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="TYPE">HORIZONTAL_OFFSET</Item>
|
||||
|
||||
* The description of each sample must be specified with a Item whose ``name``
|
||||
attribute is set to ``DESCRIPTION`` and ``role`` attribute to ``description``.
|
||||
|
||||
Values recognized by PROJ for this Item are currently:
|
||||
|
||||
+ ``latitude_offset``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the value to add a latitude expressed in the CRS encoded in the GeoKeys
|
||||
to obtain a latitude value expressed in the target CRS.
|
||||
|
||||
+ ``longitude_offset``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the value to add a longitude expressed in the CRS encoded in the GeoKeys
|
||||
to obtain a longitude value expressed in the target CRS.
|
||||
|
||||
+ ``geoid_undulation``: valid for TYPE=VERTICAL_OFFSET_GEOGRAPHIC_TO_VERTICAL.
|
||||
For a source CRS being a geographic CRS and a target CRS being a vertical CRS,
|
||||
sample values should be the value to add to a geoid-related height (that
|
||||
is expressed in the target CRS) to
|
||||
get an ellipsoidal height (that is expressed in the source CRS), also
|
||||
called the geoid undulation.
|
||||
Note the possible confusion related to what is the source CRS and target CRS and
|
||||
the semantics of the value stored (to convert from the source to the target,
|
||||
one must subtract the value contained in the grid). This is the convention
|
||||
used by the `EPSG:9665 <https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::9665>`_
|
||||
operation method.
|
||||
|
||||
+ ``vertical_offset``: valid for TYPE=VERTICAL_OFFSET_VERTICAL_TO_VERTICAL.
|
||||
For a source and target CRS being vertical CRS,
|
||||
sample values should be the value to add to an elevation expressed in the
|
||||
source CRS to obtain a longitude value expressed in the target CRS.
|
||||
|
||||
+ ``x_translation`` / ``y_translation`` / ``z_translation``: valid for
|
||||
TYPE=GEOCENTRIC_TRANSLATION.
|
||||
Sample values should be the value to add to the input geocentric coordinates
|
||||
expressed in the source CRS to geocentric coordinates expressed in the target CRS.
|
||||
|
||||
+ ``east_velocity`` / ``north_velocity`` / ``up_velocity``: valid for
|
||||
TYPE=VELOCITY.
|
||||
Sample values should be the velocity in a linear/time unit in a ENU local
|
||||
topocentric coordinate system.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="DESCRIPTION" sample="0" role="description">latitude_offset</Item>
|
||||
<Item name="DESCRIPTION" sample="1" role="description">longitude_offset</Item>
|
||||
|
||||
Other values may be used (not used by PROJ):
|
||||
|
||||
+ ``latitude_offset_accuracy``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the accuracy of corresponding latitude_offset samples. Generally in metre (if converted from NTv2)
|
||||
|
||||
+ ``longitude_offset_accuracy``: valid for TYPE=HORIZONTAL_OFFSET. Sample values should be
|
||||
the accuracy of corresponding longitude_offset samples. Generally in metre (if converted from NTv2)
|
||||
|
||||
* The sign convention for the values of the ``longitude_offset`` channel
|
||||
should be indicated with an Item named ``positive_value`` whose value
|
||||
can be ``west`` or ``east``. NTv2 products originally use a ``west``
|
||||
convention, but when converting from them to GeoTIFF, the sign of those
|
||||
samples will be inverted so they use a more natural ``east`` convention.
|
||||
If this item is absent, the default value is ``east``.
|
||||
|
||||
* The unit of the values stored in the grid must be specified for each
|
||||
sample through an Item of name ``UNITTYPE`` and role ``unittype``
|
||||
Valid values should be the name of entries from the EPSG ``unitofmeasure``
|
||||
table. To maximize interoperability, writers are strongly encouraged to
|
||||
limit themselves to the following values:
|
||||
|
||||
For linear units:
|
||||
|
||||
- ``metre`` (default value assumed if absent for vertical shift grid files, and value used for files stored on PROJ CDN)
|
||||
- ``US survey foot``
|
||||
|
||||
For angular units:
|
||||
|
||||
- ``degree``
|
||||
- ``arc-second`` (default value assumed if absent for longitude and latitude offset samples of horizontal shift grid files, and value used for files stored on PROJ CDN)
|
||||
|
||||
For velocity units:
|
||||
|
||||
- ``millimetres per year``
|
||||
|
||||
The longitude and latitude offset samples should use the same unit.
|
||||
The geocentric translation samples should use the same unit.
|
||||
The velocity samples should use the same unit.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<Item name="UNITTYPE" sample="0" role="unittype">arc-second</Item>
|
||||
<Item name="UNITTYPE" sample="1" role="unittype">arc-second</Item>
|
||||
|
||||
* The ``target_crs_epsg_code`` metadata item should be present.
|
||||
For a horizontal shift grid, this is the EPSG
|
||||
code of the target geographic CRS. For a vertical shift grid, this is the
|
||||
EPSG code of a the target vertical CRS.
|
||||
If the target CRS has no associated EPSG code, ``target_crs_wkt`` must be
|
||||
used.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``target_crs_wkt`` metadata item must be present if the
|
||||
``target_crs_epsg_code`` cannot be used.
|
||||
Its value should be a valid WKT string according to
|
||||
`WKT:2015 <http://docs.opengeospatial.org/is/12-063r5/12-063r5.html>`_
|
||||
or `WKT:2019 <hhttp://docs.opengeospatial.org/is/18-010r7/18-010r7.html>`_
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``source_crs_epsg_code`` metadata item must be present if the source
|
||||
and interpolation CRS are not the same (typical use case is vertical CRS to vertical CRS
|
||||
transformation), because the GeoKeys encode the interpolation CRS and not the source CRS.
|
||||
If the source CRS has no associated EPSG code, ``source_crs_wkt`` must be
|
||||
used.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``source_crs_wkt`` metadata item must be present if the
|
||||
``source_crs_epsg_code`` cannot be used.
|
||||
Its value should be a valid WKT string according to WKT:2015 or WKT:2019.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``interpolation_crs_wkt`` metadata item may be present if the GeoKeys
|
||||
cannot be used to express reliably the interpolation CRS.
|
||||
Its value should be a valid WKT string according to WKT:2015 or WKT:2019.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``recommended_interpolation_method`` metadata item may be present to
|
||||
describe the method to use to interpolation values at locations not
|
||||
coincident with nodes stored in the grid file. Potential values: ``bilinear``,
|
||||
``bicubic``.
|
||||
Ignored by PROJ currently.
|
||||
|
||||
* The ``area_of_use`` metadata item can be used to indicate plain text information
|
||||
about the area of use of the grid (like "USA - Wisconsin"). In case of multiple
|
||||
subgrids, it should be set only on the first one, but applies to the whole
|
||||
set of grids, not just the first one.
|
||||
|
||||
* The ``grid_name`` metadata item should be present if there are
|
||||
subgrids for this grid (that is grids whose extent is contained in the extent
|
||||
of this grid), or if this is a subgrid.
|
||||
It is intended to be a relatively short identifier
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
* The ``parent_grid_name`` metadata item should be present if this is a
|
||||
subgrid and its value should be equal to the paren's ``grid_name``
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
* The ``number_of_nested_grids`` metadata item should be present if there are
|
||||
subgrids for this grid (that is grids whose extent is contained in the extent
|
||||
of this grid).
|
||||
Will be ignored by PROJ (this information can be inferred by the grids extent)
|
||||
|
||||
Example
|
||||
+++++++
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntf_r93.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/ntf_r93.gsb
|
||||
with https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_to_gtiff.py
|
||||
|
||||
::
|
||||
|
||||
$ tiffinfo ntf_r93.tif
|
||||
|
||||
TIFF Directory at offset 0x4e (78)
|
||||
Image Width: 156 Image Length: 111
|
||||
Bits/Sample: 32
|
||||
Sample Format: IEEE floating point
|
||||
Compression Scheme: AdobeDeflate
|
||||
Photometric Interpretation: min-is-black
|
||||
Extra Samples: 3<unspecified, unspecified, unspecified>
|
||||
Samples/Pixel: 4
|
||||
Rows/Strip: 111
|
||||
Planar Configuration: separate image planes
|
||||
ImageDescription: NTF (EPSG:4275) to RGF93 (EPSG:4171). Converted from ntf_r93.gsb (version IGN07_01, last updated on 2007-10-31)
|
||||
DateTime: 2019:12:09 00:00:00
|
||||
Copyright: Derived from work by IGN France. Open License https://www.etalab.gouv.fr/wp-content/uploads/2014/05/Open_Licence.pdf
|
||||
Tag 33550: 0.100000,0.100000,0.000000
|
||||
Tag 33922: 0.000000,0.000000,0.000000,-5.500000,52.000000,0.000000
|
||||
Tag 34735: 1,1,1,3,1024,0,1,2,1025,0,1,2,2048,0,1,4275
|
||||
Tag 42112: <GDALMetadata>
|
||||
<Item name="grid_name">FRANCE</Item>
|
||||
<Item name="target_crs_epsg_code">4171</Item>
|
||||
<Item name="TYPE">HORIZONTAL_OFFSET</Item>
|
||||
<Item name="UNITTYPE" sample="0" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="0" role="description">latitude_offset</Item>
|
||||
<Item name="positive_value" sample="1">east</Item>
|
||||
<Item name="UNITTYPE" sample="1" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="1" role="description">longitude_offset</Item>
|
||||
<Item name="UNITTYPE" sample="2" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="2" role="description">latitude_offset_accuracy</Item>
|
||||
<Item name="UNITTYPE" sample="3" role="unittype">arc-second</Item>
|
||||
<Item name="DESCRIPTION" sample="3" role="description">longitude_offset_accuracy</Item>
|
||||
</GDALMetadata>
|
||||
|
||||
Predictor: floating point predictor 3 (0x3)
|
||||
|
||||
|
||||
::
|
||||
|
||||
$ listgeo ntf_r93.tif
|
||||
|
||||
Geotiff_Information:
|
||||
Version: 1
|
||||
Key_Revision: 1.1
|
||||
Tagged_Information:
|
||||
ModelTiepointTag (2,3):
|
||||
0 0 0
|
||||
-5.5 52 0
|
||||
ModelPixelScaleTag (1,3):
|
||||
0.1 0.1 0
|
||||
End_Of_Tags.
|
||||
Keyed_Information:
|
||||
GTModelTypeGeoKey (Short,1): ModelTypeGeographic
|
||||
GTRasterTypeGeoKey (Short,1): RasterPixelIsPoint
|
||||
GeodeticCRSGeoKey (Short,1): Code-4275 (NTF)
|
||||
End_Of_Keys.
|
||||
End_Of_Geotiff.
|
||||
|
||||
GCS: 4275/NTF
|
||||
Datum: 6275/Nouvelle Triangulation Francaise
|
||||
Ellipsoid: 7011/Clarke 1880 (IGN) (6378249.20,6356515.00)
|
||||
Prime Meridian: 8901/Greenwich (0.000000/ 0d 0' 0.00"E)
|
||||
Projection Linear Units: User-Defined (1.000000m)
|
||||
|
||||
Corner Coordinates:
|
||||
Upper Left ( 5d30' 0.00"W, 52d 0' 0.00"N)
|
||||
Lower Left ( 5d30' 0.00"W, 40d54' 0.00"N)
|
||||
Upper Right ( 10d 6' 0.00"E, 52d 0' 0.00"N)
|
||||
Lower Right ( 10d 6' 0.00"E, 40d54' 0.00"N)
|
||||
Center ( 2d18' 0.00"E, 46d27' 0.00"N)
|
||||
|
||||
::
|
||||
|
||||
$ gdalinfo ntf_r93.tif
|
||||
|
||||
Driver: GTiff/GeoTIFF
|
||||
Files: ntf_r93.tif
|
||||
Size is 156, 111
|
||||
Coordinate System is:
|
||||
GEOGCRS["NTF",
|
||||
DATUM["Nouvelle Triangulation Francaise",
|
||||
ELLIPSOID["Clarke 1880 (IGN)",6378249.2,293.466021293627,
|
||||
LENGTHUNIT["metre",1]]],
|
||||
PRIMEM["Greenwich",0,
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
CS[ellipsoidal,2],
|
||||
AXIS["geodetic latitude (Lat)",north,
|
||||
ORDER[1],
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
AXIS["geodetic longitude (Lon)",east,
|
||||
ORDER[2],
|
||||
ANGLEUNIT["degree",0.0174532925199433]],
|
||||
ID["EPSG",4275]]
|
||||
Data axis to CRS axis mapping: 2,1
|
||||
Origin = (-5.550000000000000,52.049999999999997)
|
||||
Pixel Size = (0.100000000000000,-0.100000000000000)
|
||||
Metadata:
|
||||
AREA_OR_POINT=Point
|
||||
grid_name=FRANCE
|
||||
target_crs_epsg_code=4171
|
||||
TIFFTAG_DATETIME=2019:12:09 00:00:00
|
||||
TIFFTAG_IMAGEDESCRIPTION=NTF (EPSG:4275) to RGF93 (EPSG:4171). Converted from ntf_r93.gsb (version IGN07_01, last updated on 2007-10-31)
|
||||
TYPE=HORIZONTAL_OFFSET
|
||||
Image Structure Metadata:
|
||||
COMPRESSION=DEFLATE
|
||||
INTERLEAVE=BAND
|
||||
Corner Coordinates:
|
||||
Upper Left ( -5.5500000, 52.0500000) ( 5d33' 0.00"W, 52d 3' 0.00"N)
|
||||
Lower Left ( -5.5500000, 40.9500000) ( 5d33' 0.00"W, 40d57' 0.00"N)
|
||||
Upper Right ( 10.0500000, 52.0500000) ( 10d 3' 0.00"E, 52d 3' 0.00"N)
|
||||
Lower Right ( 10.0500000, 40.9500000) ( 10d 3' 0.00"E, 40d57' 0.00"N)
|
||||
Center ( 2.2500000, 46.5000000) ( 2d15' 0.00"E, 46d30' 0.00"N)
|
||||
Band 1 Block=156x111 Type=Float32, ColorInterp=Gray
|
||||
Description = latitude_offset
|
||||
Unit Type: arc-second
|
||||
Band 2 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = longitude_offset
|
||||
Unit Type: arc-second
|
||||
Metadata:
|
||||
positive_value=east
|
||||
Band 3 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = latitude_offset_accuracy
|
||||
Unit Type: arc-second
|
||||
Band 4 Block=156x111 Type=Float32, ColorInterp=Undefined
|
||||
Description = longitude_offset_accuracy
|
||||
Unit Type: arc-second
|
||||
|
||||
Multi-grid storage
|
||||
++++++++++++++++++
|
||||
|
||||
Formats like NTv2 can contain multiple subgrids. This can be transposed to
|
||||
TIFF by using several IFD chained together with the last 4 bytes (or 8 bytes
|
||||
for BigTIFF) of an IFD pointing to the offset of the next one.
|
||||
|
||||
The first IFD should have a full description according to the
|
||||
:ref:`General description <gtg_general_description>`.
|
||||
Subsequent IFD might have a more compact description, omitting for example, CRS
|
||||
information if it is identical to the main IFD (which should be the case for
|
||||
the currently envisionned use cases), or Copyright / ImageDescription metadata
|
||||
items.
|
||||
|
||||
Each IFD will have its
|
||||
`NewSubfileType <https://www.awaresystems.be/imaging/tiff/tifftags/newsubfiletype.html>`_
|
||||
tag set to 0.
|
||||
|
||||
If a low-resolution grid is available, it should be put before subgrids of
|
||||
higher-resolution in the chain of IFD linking. On reading, PROJ will use the
|
||||
value from the highest-resoluted grid that contains the point of interest.
|
||||
|
||||
For efficient reading from the network, files hosted on the CDN will use
|
||||
a layout similar to the one described in the `low level paragraph of the Cloud Optimized GeoTIFF
|
||||
GDAL driver page <https://gdal.org/drivers/raster/cog.html#low-level>`_
|
||||
|
||||
The layout for a file converted from NTv2 will for example be:
|
||||
|
||||
- TIFF/BigTIFF header/signature and pointer to first IFD (Image File Directory)
|
||||
- "ghost area" indicating the generated process
|
||||
- IFD of the first grid, followed by TIFF tags values, excluding the TileOffsets and TileByteCounts arrays
|
||||
- ...
|
||||
- IFD of the last grid, followed by TIFF tags values, excluding the GDAL_METADATA tag, TileOffsets and TileByteCounts arrays
|
||||
- TileOffsets and TileByteCounts arrays for first IFD
|
||||
- ...
|
||||
- TileOffsets and TileByteCounts arrays for last IFD
|
||||
- Value of GDAL_METADATA tag for IFDs following the first IFD
|
||||
- First IFD: Data corresponding to latitude offset of Block_0_0
|
||||
- First IFD: Data corresponding to longitude offset of Block_0_0
|
||||
- First IFD: Data corresponding to latitude offset of Block_0_1
|
||||
- First IFD: Data corresponding to longitude offset of Block_0_1
|
||||
- ...
|
||||
- First IFD: Data corresponding to latitude offset of Block_n_m
|
||||
- First IFD: Data corresponding to longitude offset of Block_n_m
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset of Block_0_0
|
||||
- Last IFD: Data corresponding to longitude offset of Block_0_0
|
||||
- Last IFD: Data corresponding to latitude offset of Block_0_1
|
||||
- Last IFD: Data corresponding to longitude offset of Block_0_1
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset of Block_n_m
|
||||
- Last IFD: Data corresponding to longitude offset of Block_n_m
|
||||
|
||||
If longitude_offset_accuracy and latitude_offset_accuracy are present, this
|
||||
will be followed by:
|
||||
|
||||
- First IFD: Data corresponding to latitude offset accuracy of Block_0_0
|
||||
- First IFD: Data corresponding to longitude offset accuracy of Block_0_0
|
||||
- ...
|
||||
- First IFD: Data corresponding to latitude offset accuracy of Block_n_m
|
||||
- First IFD: Data corresponding to longitude offset accuracy of Block_n_m
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset accuracy of Block_0_0
|
||||
- Last IFD: Data corresponding to longitude offset accuracy of Block_0_0
|
||||
- ...
|
||||
- Last IFD: Data corresponding to latitude offset accuracy of Block_n_m
|
||||
- Last IFD: Data corresponding to longitude offset accuracy of Block_n_m
|
||||
|
||||
.. note::
|
||||
|
||||
TIFF has another mechanism to link IFDs, the SubIFD tag. This potentially
|
||||
enables to define a hiearchy of IFDs (similar to HDF5 groups). There is no
|
||||
support for that in most TIFF-using software, notably GDAL, and no compelling
|
||||
need to have a nested hiearchy, so "flat" organization with the standard IFD chaining
|
||||
mechanism is adopted.
|
||||
|
||||
Examples of multi-grid dataset
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/GDA94_GDA2020_conformal.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/oceania/GDA94_GDA2020_conformal.gsb
|
||||
with https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_to_gtiff.py
|
||||
|
||||
It contains 5 subgrids. All essential metadata to list the subgrids and their
|
||||
georeferencing is contained within the first 3 KB of the file.
|
||||
|
||||
The file size is 4.8 MB using DEFLATE compression and floating-point predictor.
|
||||
To be compared with the 83 MB of the original .gsb file.
|
||||
|
||||
https://github.com/rouault/sample_proj_gtiff_grids/blob/master/ntv2_0.tif has
|
||||
been converted from https://github.com/OSGeo/proj-datumgrid/blob/master/north-america/ntv2_0.gsb
|
||||
|
||||
It contains 114 subgrids. All essential metadata to list the subgrids and their
|
||||
georeferencing is contained within the first 40 KB of the file.
|
||||
@@ -0,0 +1,14 @@
|
||||
.. _specifications:
|
||||
|
||||
================================================================================
|
||||
Specifications
|
||||
================================================================================
|
||||
|
||||
PROJ implements a number of extensions to standards, that are described below
|
||||
for the sake of broader interoperability.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
projjson
|
||||
geodetictiffgrids
|
||||
@@ -139,3 +139,9 @@ cs2cs
|
||||
|
||||
Removed ``-ld`` option from application, since it promoted use of deprecated
|
||||
paramters like ``+towgs`` and ``+datum``.
|
||||
|
||||
UTF-8 adoption
|
||||
--------------
|
||||
|
||||
The value of all path, filenames passed to PROJ through function calls, PROJ
|
||||
strings or environment variables should be encoded in UTF-8.
|
||||
|
||||
@@ -56,3 +56,21 @@ done by setting the variable with no content::
|
||||
Set the debug level of PROJ. The default debug level is zero, which results
|
||||
in no debug output when using PROJ. A number from 1-3, whit 3 being the most
|
||||
verbose setting.
|
||||
|
||||
.. envvar:: PROJ_NETWORK
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
If set to ON, enable the capability to use remote grids stored on CDN
|
||||
(Content Delivery Network) storage, when grids are not available locally.
|
||||
Alternatively, the :c:func:`proj_context_set_enable_network` function can
|
||||
be used.
|
||||
|
||||
.. envvar:: PROJ_NETWORK_ENDPOINT
|
||||
|
||||
.. versionadded:: 7.0.0
|
||||
|
||||
Define the endpoint of the CDN storage. Normally defined through the proj.ini
|
||||
configuration file locale in :envvar:`PROJ_LIB`.
|
||||
Alternatively, the :c:func:`proj_context_set_url_endpoint` function can
|
||||
be used.
|
||||
|
||||
@@ -17,5 +17,4 @@ command line applications or the C API that is a part of the software package.
|
||||
transformation
|
||||
environmentvars
|
||||
differences
|
||||
projjson
|
||||
|
||||
network
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
.. _network:
|
||||
|
||||
================================================================================
|
||||
Network capabilities
|
||||
================================================================================
|
||||
|
||||
.. versionadded:: 7.0
|
||||
|
||||
PROJ 7.0 has introduced, per :ref:`rfc4`, the capability to work with grid files
|
||||
that are not installed on the local machine where PROJ is executed.
|
||||
|
||||
This enables to transparently download the parts of grids that are needed to
|
||||
perform a coordinate transformation.
|
||||
|
||||
.. _cdn_grids:
|
||||
|
||||
CDN of GeoTIFF grids
|
||||
--------------------
|
||||
|
||||
Files are accessed by default through a CDN (Content Delivery Network),
|
||||
accessible through https://cdn.proj.org, that contains :ref:`geodetictiffgrids`
|
||||
datasets which are mirrored and managed by the
|
||||
https://github.com/OSGeo/proj-datumgrid-geotiff/ GitHub project.
|
||||
Files in the CDN are designed to be used by PROJ 7 or later, but any software
|
||||
project wishing to use the CDN for shifting support are encouraged to
|
||||
participate in the project and leverage the CDN.
|
||||
|
||||
How to enable network capabilities ?
|
||||
------------------------------------
|
||||
|
||||
This capability assumes that PROJ has been build against `libcurl`, and that
|
||||
the user authorizes network access.
|
||||
|
||||
Authorizing network access can be done in multiple ways:
|
||||
|
||||
- enabling / uncommenting the ``network = on`` line of :ref:`proj-ini`
|
||||
- definiting the :envvar:`PROJ_NETWORK` environment variable to ON
|
||||
- or using the :cpp:func:`proj_context_set_enable_network` with a
|
||||
``enabled`` = TRUE value.
|
||||
|
||||
.. note::
|
||||
|
||||
Instead of using the `libcurl` implementation, an application using the PROJ
|
||||
API can supply its own network implementation through C function callbacks
|
||||
with :cpp:func:`proj_context_set_network_callbacks`. Enabling network use
|
||||
must still be done with one of the above mentionned method.
|
||||
|
||||
Setting endpoint
|
||||
----------------
|
||||
|
||||
When this is enabled, and a grid is not found in the various locations where
|
||||
:ref:`resource files are looked for <resource_file_paths>`, PROJ will then
|
||||
attempt at loading the file from a remote server, which defaults to
|
||||
https://cdn.proj.org in :ref:`proj-ini`. This location can be changed with
|
||||
the :envvar:`PROJ_NETWORK_ENDPOINT` environment variable or with
|
||||
:cpp:func:`proj_context_set_url_endpoint`.
|
||||
|
||||
Caching
|
||||
-------
|
||||
|
||||
To avoid repeated access to network, a local cache of downloaded chunks of grids
|
||||
is implemented as SQLite3 database, ``cache.db``, stored in the
|
||||
:ref:`PROJ user writable directory <user_writable_directory>`.
|
||||
|
||||
This local caching is enabled by default (can be changed in :ref:`proj-ini` or
|
||||
with :cpp:func:`proj_grid_cache_set_enable`). The default maximum size of the
|
||||
cache is 300 MB, which is more than half of the total size of grids available,
|
||||
at time of writing. This size can also be customized in :ref:`proj-ini` or
|
||||
with :cpp:func:`proj_grid_cache_set_max_size`
|
||||
|
||||
Download API
|
||||
------------
|
||||
|
||||
When on-demand loading of grid is not desirable, the PROJ API also offers the
|
||||
capability to download whole grids in the
|
||||
:ref:`PROJ user writable directory <user_writable_directory>` by using the
|
||||
:cpp:func:`proj_is_download_needed` and :cpp:func:`proj_download_file` functions.
|
||||
|
||||
|
||||
Mirroring
|
||||
---------
|
||||
|
||||
If you are able, you are encouraged to mirror the grids via AWS S3 command line:
|
||||
|
||||
::
|
||||
|
||||
aws s3 sync s3://cdn.proj.org .
|
||||
|
||||
If direct S3 access is not possible, you can also use wget to locally mirror the
|
||||
data:
|
||||
|
||||
::
|
||||
|
||||
wget --mirror https://cdn.proj.org/
|
||||
|
||||
Acknowledgments
|
||||
---------------
|
||||
|
||||
The s3://cdn.proj.org bucket is hosted by the
|
||||
`Amazon Public Datasets program <https://aws.amazon.com/opendata/public-datasets/>`_.
|
||||
CDN services are provided by the AWS Public Dataset team via
|
||||
`CloudFront <https://aws.amazon.com/cloudfront/>`_
|
||||
@@ -144,10 +144,12 @@ class PROJ_GCC_DLL CoordinateOperation : public common::ObjectUsage,
|
||||
|
||||
/** \brief Return grids needed by an operation. */
|
||||
PROJ_DLL virtual std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const = 0;
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const = 0;
|
||||
|
||||
PROJ_DLL bool
|
||||
isPROJInstantiable(const io::DatabaseContextPtr &databaseContext) const;
|
||||
isPROJInstantiable(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const;
|
||||
|
||||
PROJ_DLL bool hasBallparkTransformation() const;
|
||||
|
||||
@@ -601,7 +603,8 @@ class PROJ_GCC_DLL SingleOperation : virtual public CoordinateOperation {
|
||||
std::vector<metadata::PositionalAccuracyNNPtr>());
|
||||
|
||||
PROJ_DLL std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override;
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const override;
|
||||
|
||||
PROJ_DLL std::list<std::string> validateParameters() const;
|
||||
|
||||
@@ -1680,7 +1683,8 @@ class PROJ_GCC_DLL ConcatenatedOperation final : public CoordinateOperation {
|
||||
bool checkExtent); // throw InvalidOperation
|
||||
|
||||
PROJ_DLL std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override;
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const override;
|
||||
|
||||
PROJ_PRIVATE :
|
||||
|
||||
@@ -1810,6 +1814,12 @@ class PROJ_GCC_DLL CoordinateOperationContext {
|
||||
/** Ignore grid availability at all. Results will be presented as if
|
||||
* all grids were available. */
|
||||
IGNORE_GRID_AVAILABILITY,
|
||||
|
||||
/** Results will be presented as if grids known to PROJ (that is
|
||||
* registered in the grid_alternatives table of its database) were
|
||||
* available. Used typically when networking is enabled.
|
||||
*/
|
||||
KNOWN_AVAILABLE,
|
||||
};
|
||||
|
||||
PROJ_DLL void setGridAvailabilityUse(GridAvailabilityUse use);
|
||||
|
||||
@@ -180,8 +180,10 @@ class InverseConversion : public Conversion, public InverseCoordinateOperation {
|
||||
// 'osgeo::proj::operation::SingleOperation::osgeo::proj::operation::SingleOperation::gridsNeeded'
|
||||
// via dominance
|
||||
std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override {
|
||||
return SingleOperation::gridsNeeded(databaseContext);
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const override {
|
||||
return SingleOperation::gridsNeeded(databaseContext,
|
||||
considerKnownGridsAsAvailable);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -232,8 +234,10 @@ class InverseTransformation : public Transformation,
|
||||
// 'osgeo::proj::operation::SingleOperation::osgeo::proj::operation::SingleOperation::gridsNeeded'
|
||||
// via dominance
|
||||
std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override {
|
||||
return SingleOperation::gridsNeeded(databaseContext);
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const override {
|
||||
return SingleOperation::gridsNeeded(databaseContext,
|
||||
considerKnownGridsAsAvailable);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -274,7 +278,8 @@ class PROJBasedOperation : public SingleOperation {
|
||||
bool hasRoughTransformation);
|
||||
|
||||
std::set<GridDescription>
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext) const override;
|
||||
gridsNeeded(const io::DatabaseContextPtr &databaseContext,
|
||||
bool considerKnownGridsAsAvailable) const override;
|
||||
|
||||
protected:
|
||||
PROJBasedOperation(const PROJBasedOperation &) = default;
|
||||
|
||||
+5
-3
@@ -832,6 +832,7 @@ class PROJ_GCC_DLL DatabaseContext {
|
||||
bool &inverse) const;
|
||||
|
||||
PROJ_DLL bool lookForGridInfo(const std::string &projFilename,
|
||||
bool considerKnownGridsAsAvailable,
|
||||
std::string &fullFilename,
|
||||
std::string &packageName, std::string &url,
|
||||
bool &directDownload, bool &openLicense,
|
||||
@@ -1055,7 +1056,8 @@ class PROJ_GCC_DLL AuthorityFactory {
|
||||
const std::string &sourceCRSAuthName, const std::string &sourceCRSCode,
|
||||
const std::string &targetCRSAuthName, const std::string &targetCRSCode,
|
||||
bool usePROJAlternativeGridNames, bool discardIfMissingGrid,
|
||||
bool discardSuperseded, bool tryReverseOrder = false,
|
||||
bool considerKnownGridsAsAvailable, bool discardSuperseded,
|
||||
bool tryReverseOrder = false,
|
||||
bool reportOnlyIntersectingTransformations = false,
|
||||
const metadata::ExtentPtr &intersectingExtent1 = nullptr,
|
||||
const metadata::ExtentPtr &intersectingExtent2 = nullptr) const;
|
||||
@@ -1065,7 +1067,7 @@ class PROJ_GCC_DLL AuthorityFactory {
|
||||
const std::string &sourceCRSAuthName, const std::string &sourceCRSCode,
|
||||
const std::string &targetCRSAuthName, const std::string &targetCRSCode,
|
||||
bool usePROJAlternativeGridNames, bool discardIfMissingGrid,
|
||||
bool discardSuperseded,
|
||||
bool considerKnownGridsAsAvailable, bool discardSuperseded,
|
||||
const std::vector<std::pair<std::string, std::string>>
|
||||
&intermediateCRSAuthCodes,
|
||||
ObjectType allowedIntermediateObjectType = ObjectType::CRS,
|
||||
@@ -1131,7 +1133,7 @@ class PROJ_GCC_DLL AuthorityFactory {
|
||||
const std::string &sourceCRSCode, const crs::CRSNNPtr &targetCRS,
|
||||
const std::string &targetCRSAuthName, const std::string &targetCRSCode,
|
||||
bool usePROJAlternativeGridNames, bool discardIfMissingGrid,
|
||||
bool discardSuperseded,
|
||||
bool considerKnownGridsAsAvailable, bool discardSuperseded,
|
||||
const std::vector<std::string> &allowedAuthorities,
|
||||
const metadata::ExtentPtr &intersectingExtent1,
|
||||
const metadata::ExtentPtr &intersectingExtent2) const;
|
||||
|
||||
+9
-1
@@ -34,7 +34,11 @@ fi
|
||||
mkdir -p docs/build/tmp_breathe
|
||||
python scripts/generate_breathe_friendly_general_doc.py
|
||||
rm -rf docs/build/xml/
|
||||
(cat Doxyfile; printf "GENERATE_HTML=NO\nGENERATE_XML=YES\nINPUT= src/iso19111 include/proj src/proj.h docs/build/tmp_breathe/general_doc.dox.reworked.h") | doxygen - > docs/build/tmp_breathe/docs_log.txt 2>&1
|
||||
|
||||
# Ugly hack to workaround a bug of Doxygen 1.8.17 that erroneously detect proj_network_get_header_value_cbk_type/ as a variable
|
||||
sed "s/const char\* (\*proj_network_get_header_value_cbk_type/CONST_CHAR\* (\*proj_network_get_header_value_cbk_type/" < src/proj.h > docs/build/tmp_breathe/proj.h
|
||||
|
||||
(cat Doxyfile; printf "GENERATE_HTML=NO\nGENERATE_XML=YES\nINPUT= src/iso19111 include/proj docs/build/tmp_breathe/proj.h src/filemanager.cpp src/networkfilemanager.cpp docs/build/tmp_breathe/general_doc.dox.reworked.h") | doxygen - > docs/build/tmp_breathe/docs_log.txt 2>&1
|
||||
if grep -i warning docs/build/tmp_breathe/docs_log.txt; then
|
||||
echo "Doxygen warnings found" && cat docs/build/tmp_breathe/docs_log.txt && /bin/false;
|
||||
else
|
||||
@@ -56,5 +60,9 @@ done
|
||||
sed "s/Convention/Convention_/g" < ${TOPDIR}/docs/build/xml/classosgeo_1_1proj_1_1io_1_1WKTFormatter.xml | sed "s/WKT2_2018/_WKT2_2018/g" | sed "s/WKT2_2019/_WKT2_2019/g" | sed "s/WKT2_2015/_WKT2_2015/g" | sed "s/WKT1_GDAL/_WKT1_GDAL/g" | sed "s/WKT1_ESRI/_WKT1_ESRI/g" > ${TOPDIR}/docs/build/xml/classosgeo_1_1proj_1_1io_1_1WKTFormatter.xml.tmp
|
||||
mv ${TOPDIR}/docs/build/xml/classosgeo_1_1proj_1_1io_1_1WKTFormatter.xml.tmp ${TOPDIR}/docs/build/xml/classosgeo_1_1proj_1_1io_1_1WKTFormatter.xml
|
||||
|
||||
# Ugly hack to workaround a bug of Doxygen 1.8.17 that erroneously detect proj_network_get_header_value_cbk_type/ as a variable
|
||||
sed "s/CONST_CHAR/const char/" < ${TOPDIR}/docs/build/xml/proj_8h.xml > ${TOPDIR}/docs/build/xml/proj_8h.xml.tmp
|
||||
mv ${TOPDIR}/docs/build/xml/proj_8h.xml.tmp ${TOPDIR}/docs/build/xml/proj_8h.xml
|
||||
|
||||
popd > /dev/null || exit
|
||||
|
||||
|
||||
@@ -281,6 +281,26 @@ osgeo::proj::datum::TemporalDatum::temporalOrigin() const
|
||||
osgeo::proj::datum::VerticalReferenceFrame::create(osgeo::proj::util::PropertyMap const&, osgeo::proj::util::optional<std::string> const&, osgeo::proj::util::optional<osgeo::proj::datum::RealizationMethod> const&)
|
||||
osgeo::proj::datum::VerticalReferenceFrame::realizationMethod() const
|
||||
osgeo::proj::datum::VerticalReferenceFrame::~VerticalReferenceFrame()
|
||||
osgeo::proj::GenericShiftGrid::~GenericShiftGrid()
|
||||
osgeo::proj::GenericShiftGrid::GenericShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
|
||||
osgeo::proj::GenericShiftGrid::gridAt(double, double) const
|
||||
osgeo::proj::GenericShiftGridSet::~GenericShiftGridSet()
|
||||
osgeo::proj::GenericShiftGridSet::GenericShiftGridSet()
|
||||
osgeo::proj::GenericShiftGridSet::gridAt(double, double) const
|
||||
osgeo::proj::GenericShiftGridSet::open(projCtx_t*, std::string const&)
|
||||
osgeo::proj::GenericShiftGridSet::reassign_context(projCtx_t*)
|
||||
osgeo::proj::GenericShiftGridSet::reopen(projCtx_t*)
|
||||
osgeo::proj::Grid::~Grid()
|
||||
osgeo::proj::Grid::Grid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
|
||||
osgeo::proj::HorizontalShiftGrid::gridAt(double, double) const
|
||||
osgeo::proj::HorizontalShiftGrid::~HorizontalShiftGrid()
|
||||
osgeo::proj::HorizontalShiftGrid::HorizontalShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
|
||||
osgeo::proj::HorizontalShiftGridSet::gridAt(double, double) const
|
||||
osgeo::proj::HorizontalShiftGridSet::~HorizontalShiftGridSet()
|
||||
osgeo::proj::HorizontalShiftGridSet::HorizontalShiftGridSet()
|
||||
osgeo::proj::HorizontalShiftGridSet::open(projCtx_t*, std::string const&)
|
||||
osgeo::proj::HorizontalShiftGridSet::reassign_context(projCtx_t*)
|
||||
osgeo::proj::HorizontalShiftGridSet::reopen(projCtx_t*)
|
||||
osgeo::proj::internal::ci_equal(std::string const&, char const*)
|
||||
osgeo::proj::internal::ci_equal(std::string const&, std::string const&)
|
||||
osgeo::proj::internal::ci_find(std::string const&, char const*)
|
||||
@@ -301,8 +321,8 @@ osgeo::proj::io::AuthorityFactory::create(dropbox::oxygen::nn<std::shared_ptr<os
|
||||
osgeo::proj::io::AuthorityFactory::createEllipsoid(std::string const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createExtent(std::string const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createFromCoordinateReferenceSystemCodes(std::string const&, std::string const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createFromCoordinateReferenceSystemCodes(std::string const&, std::string const&, std::string const&, std::string const&, bool, bool, bool, bool, bool, std::shared_ptr<osgeo::proj::metadata::Extent> const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createFromCRSCodesWithIntermediates(std::string const&, std::string const&, std::string const&, std::string const&, bool, bool, bool, std::vector<std::pair<std::string, std::string>, std::allocator<std::pair<std::string, std::string> > > const&, osgeo::proj::io::AuthorityFactory::ObjectType, std::vector<std::string, std::allocator<std::string> > const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createFromCoordinateReferenceSystemCodes(std::string const&, std::string const&, std::string const&, std::string const&, bool, bool, bool, bool, bool, bool, std::shared_ptr<osgeo::proj::metadata::Extent> const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createFromCRSCodesWithIntermediates(std::string const&, std::string const&, std::string const&, std::string const&, bool, bool, bool, bool, std::vector<std::pair<std::string, std::string>, std::allocator<std::pair<std::string, std::string> > > const&, osgeo::proj::io::AuthorityFactory::ObjectType, std::vector<std::string, std::allocator<std::string> > const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&, std::shared_ptr<osgeo::proj::metadata::Extent> const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createGeodeticCRS(std::string const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createGeodeticDatum(std::string const&) const
|
||||
osgeo::proj::io::AuthorityFactory::createGeographicCRS(std::string const&) const
|
||||
@@ -332,7 +352,7 @@ osgeo::proj::io::DatabaseContext::getDatabaseStructure() const
|
||||
osgeo::proj::io::DatabaseContext::getMetadata(char const*) const
|
||||
osgeo::proj::io::DatabaseContext::getPath() const
|
||||
osgeo::proj::io::DatabaseContext::getSqliteHandle() const
|
||||
osgeo::proj::io::DatabaseContext::lookForGridInfo(std::string const&, std::string&, std::string&, std::string&, bool&, bool&, bool&) const
|
||||
osgeo::proj::io::DatabaseContext::lookForGridInfo(std::string const&, bool, std::string&, std::string&, std::string&, bool&, bool&, bool&) const
|
||||
osgeo::proj::io::FactoryException::~FactoryException()
|
||||
osgeo::proj::io::FactoryException::FactoryException(char const*)
|
||||
osgeo::proj::io::FactoryException::FactoryException(osgeo::proj::io::FactoryException const&)
|
||||
@@ -467,7 +487,7 @@ osgeo::proj::metadata::VerticalExtent::~VerticalExtent()
|
||||
osgeo::proj::operation::ConcatenatedOperation::~ConcatenatedOperation()
|
||||
osgeo::proj::operation::ConcatenatedOperation::createComputeMetadata(std::vector<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::CoordinateOperation> >, std::allocator<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::CoordinateOperation> > > > const&, bool)
|
||||
osgeo::proj::operation::ConcatenatedOperation::create(osgeo::proj::util::PropertyMap const&, std::vector<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::CoordinateOperation> >, std::allocator<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::operation::CoordinateOperation> > > > const&, std::vector<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::metadata::PositionalAccuracy> >, std::allocator<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::metadata::PositionalAccuracy> > > > const&)
|
||||
osgeo::proj::operation::ConcatenatedOperation::gridsNeeded(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&) const
|
||||
osgeo::proj::operation::ConcatenatedOperation::gridsNeeded(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&, bool) const
|
||||
osgeo::proj::operation::ConcatenatedOperation::inverse() const
|
||||
osgeo::proj::operation::ConcatenatedOperation::operations() const
|
||||
osgeo::proj::operation::Conversion::~Conversion()
|
||||
@@ -577,7 +597,7 @@ osgeo::proj::operation::CoordinateOperationFactory::createOperation(dropbox::oxy
|
||||
osgeo::proj::operation::CoordinateOperationFactory::createOperations(dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::crs::CRS> > const&, dropbox::oxygen::nn<std::unique_ptr<osgeo::proj::operation::CoordinateOperationContext, std::default_delete<osgeo::proj::operation::CoordinateOperationContext> > > const&) const
|
||||
osgeo::proj::operation::CoordinateOperation::hasBallparkTransformation() const
|
||||
osgeo::proj::operation::CoordinateOperation::interpolationCRS() const
|
||||
osgeo::proj::operation::CoordinateOperation::isPROJInstantiable(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&) const
|
||||
osgeo::proj::operation::CoordinateOperation::isPROJInstantiable(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&, bool) const
|
||||
osgeo::proj::operation::CoordinateOperation::normalizeForVisualization() const
|
||||
osgeo::proj::operation::CoordinateOperation::operationVersion() const
|
||||
osgeo::proj::operation::CoordinateOperation::shallowClone() const
|
||||
@@ -623,7 +643,7 @@ osgeo::proj::operation::ParameterValue::value() const
|
||||
osgeo::proj::operation::ParameterValue::valueFile() const
|
||||
osgeo::proj::operation::PointMotionOperation::~PointMotionOperation()
|
||||
osgeo::proj::operation::SingleOperation::createPROJBased(osgeo::proj::util::PropertyMap const&, std::string const&, std::shared_ptr<osgeo::proj::crs::CRS> const&, std::shared_ptr<osgeo::proj::crs::CRS> const&, std::vector<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::metadata::PositionalAccuracy> >, std::allocator<dropbox::oxygen::nn<std::shared_ptr<osgeo::proj::metadata::PositionalAccuracy> > > > const&)
|
||||
osgeo::proj::operation::SingleOperation::gridsNeeded(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&) const
|
||||
osgeo::proj::operation::SingleOperation::gridsNeeded(std::shared_ptr<osgeo::proj::io::DatabaseContext> const&, bool) const
|
||||
osgeo::proj::operation::SingleOperation::method() const
|
||||
osgeo::proj::operation::SingleOperation::parameterValue(int) const
|
||||
osgeo::proj::operation::SingleOperation::parameterValueMeasure(int) const
|
||||
@@ -698,6 +718,15 @@ osgeo::proj::util::PropertyMap::set(std::string const&, std::string const&)
|
||||
osgeo::proj::util::PropertyMap::set(std::string const&, std::vector<std::string, std::allocator<std::string> > const&)
|
||||
osgeo::proj::util::UnsupportedOperationException::~UnsupportedOperationException()
|
||||
osgeo::proj::util::UnsupportedOperationException::UnsupportedOperationException(osgeo::proj::util::UnsupportedOperationException const&)
|
||||
osgeo::proj::VerticalShiftGrid::gridAt(double, double) const
|
||||
osgeo::proj::VerticalShiftGridSet::gridAt(double, double) const
|
||||
osgeo::proj::VerticalShiftGridSet::open(projCtx_t*, std::string const&)
|
||||
osgeo::proj::VerticalShiftGridSet::reassign_context(projCtx_t*)
|
||||
osgeo::proj::VerticalShiftGridSet::reopen(projCtx_t*)
|
||||
osgeo::proj::VerticalShiftGridSet::~VerticalShiftGridSet()
|
||||
osgeo::proj::VerticalShiftGridSet::VerticalShiftGridSet()
|
||||
osgeo::proj::VerticalShiftGrid::~VerticalShiftGrid()
|
||||
osgeo::proj::VerticalShiftGrid::VerticalShiftGrid(std::string const&, int, int, osgeo::proj::ExtentAndRes const&)
|
||||
pj_acquire_lock
|
||||
pj_add_type_crs_if_needed(std::string const&)
|
||||
pj_apply_gridshift
|
||||
@@ -709,6 +738,9 @@ pj_chomp(char*)
|
||||
pj_cleanup_lock
|
||||
pj_clear_initcache
|
||||
pj_compare_datums
|
||||
pj_context_get_grid_cache_filename(projCtx_t*)
|
||||
pj_context_get_user_writable_directory(projCtx_t*, bool)
|
||||
pj_context_is_network_enabled(projCtx_t*)
|
||||
pj_ctx_alloc
|
||||
pj_ctx_fclose
|
||||
pj_ctx_fgets
|
||||
@@ -796,9 +828,14 @@ proj_context_get_use_proj4_init_rules
|
||||
proj_context_guess_wkt_dialect
|
||||
proj_context_set_autoclose_database
|
||||
proj_context_set_database_path
|
||||
proj_context_set_enable_network
|
||||
proj_context_set_fileapi
|
||||
proj_context_set_file_finder
|
||||
proj_context_set_network_callbacks
|
||||
proj_context_set(PJconsts*, projCtx_t*)
|
||||
proj_context_set_search_paths
|
||||
proj_context_set_sqlite3_vfs_name
|
||||
proj_context_set_url_endpoint
|
||||
proj_context_use_proj4_init_rules
|
||||
proj_convert_conversion_to_other_method
|
||||
proj_coord
|
||||
@@ -928,6 +965,7 @@ proj_cs_get_axis_info
|
||||
proj_cs_get_type
|
||||
proj_destroy
|
||||
proj_dmstor
|
||||
proj_download_file
|
||||
proj_ellipsoid_get_parameters
|
||||
proj_errno
|
||||
proj_errno_reset
|
||||
@@ -953,6 +991,11 @@ proj_get_scope
|
||||
proj_get_source_crs
|
||||
proj_get_target_crs
|
||||
proj_get_type
|
||||
proj_grid_cache_clear
|
||||
proj_grid_cache_set_enable
|
||||
proj_grid_cache_set_filename
|
||||
proj_grid_cache_set_max_size
|
||||
proj_grid_cache_set_ttl
|
||||
proj_grid_get_info_from_database
|
||||
proj_grid_info
|
||||
proj_identify
|
||||
@@ -962,6 +1005,7 @@ proj_int_list_destroy
|
||||
proj_is_crs
|
||||
proj_is_deprecated
|
||||
proj_is_derived_crs
|
||||
proj_is_download_needed
|
||||
proj_is_equivalent_to
|
||||
proj_is_equivalent_to_with_ctx
|
||||
proj_list_angular_units
|
||||
|
||||
@@ -15,7 +15,11 @@ esac
|
||||
|
||||
TOPDIR="$SCRIPT_DIR/.."
|
||||
|
||||
for i in "$TOPDIR"/include/proj/*.hpp "$TOPDIR"/include/proj/internal/*.hpp "$TOPDIR"/src/iso19111/*.cpp "$TOPDIR"/test/unit/*.cpp "$TOPDIR"/src/apps/projinfo.cpp "$TOPDIR"/src/tracing.cpp; do
|
||||
for i in "$TOPDIR"/include/proj/*.hpp "$TOPDIR"/include/proj/internal/*.hpp \
|
||||
"$TOPDIR"/src/iso19111/*.cpp "$TOPDIR"/test/unit/*.cpp "$TOPDIR"/src/apps/projinfo.cpp \
|
||||
"$TOPDIR"/src/tracing.cpp "$TOPDIR"/src/grids.hpp "$TOPDIR"/src/grids.cpp \
|
||||
"$TOPDIR"/src/filemanager.hpp "$TOPDIR"/src/filemanager.cpp \
|
||||
"$TOPDIR"/src/sqlite3_utils.hpp "$TOPDIR"/src/sqlite3_utils.cpp ; do
|
||||
if ! echo "$i" | grep -q "lru_cache.hpp"; then
|
||||
"$SCRIPT_DIR"/reformat.sh "$i";
|
||||
fi
|
||||
|
||||
+79
-38
@@ -47,6 +47,8 @@
|
||||
#include "proj_internal.h"
|
||||
#include <math.h>
|
||||
#include "geodesic.h"
|
||||
#include "grids.hpp"
|
||||
#include "filemanager.hpp"
|
||||
|
||||
#include "proj/common.hpp"
|
||||
#include "proj/coordinateoperation.hpp"
|
||||
@@ -262,6 +264,9 @@ similarly, but prefers the 2D resp. 3D interfaces if available.
|
||||
}
|
||||
PJ_COORD res = direction == PJ_FWD ?
|
||||
pj_fwd4d( coord, alt.pj ) : pj_inv4d( coord, alt.pj );
|
||||
if( proj_errno(alt.pj) == PJD_ERR_NETWORK_ERROR ) {
|
||||
return proj_coord_error ();
|
||||
}
|
||||
if( res.xyzt.x != HUGE_VAL ) {
|
||||
return res;
|
||||
}
|
||||
@@ -290,7 +295,7 @@ similarly, but prefers the 2D resp. 3D interfaces if available.
|
||||
auto coordOperation = dynamic_cast<
|
||||
NS_PROJ::operation::CoordinateOperation*>(alt.pj->iso_obj.get());
|
||||
if( coordOperation ) {
|
||||
if( coordOperation->gridsNeeded(dbContext).empty() ) {
|
||||
if( coordOperation->gridsNeeded(dbContext, true).empty() ) {
|
||||
if( P->iCurCoordOp != i ) {
|
||||
if (proj_log_level(P->ctx, PJ_LOG_TELL) >= PJ_LOG_DEBUG) {
|
||||
std::string msg("Using coordinate operation ");
|
||||
@@ -1146,7 +1151,10 @@ PJ *proj_create_crs_to_crs_from_pj (PJ_CONTEXT *ctx, const PJ *source_crs, cons
|
||||
proj_operation_factory_context_set_spatial_criterion(
|
||||
ctx, operation_ctx, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);
|
||||
proj_operation_factory_context_set_grid_availability_use(
|
||||
ctx, operation_ctx, PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID);
|
||||
ctx, operation_ctx,
|
||||
pj_context_is_network_enabled(ctx) ?
|
||||
PROJ_GRID_AVAILABILITY_KNOWN_AVAILABLE:
|
||||
PROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID);
|
||||
|
||||
auto op_list = proj_create_operations(ctx, source_crs, target_crs, operation_ctx);
|
||||
|
||||
@@ -1476,10 +1484,20 @@ PJ_INFO proj_info (void) {
|
||||
/* build search path string */
|
||||
auto ctx = pj_get_default_ctx();
|
||||
if (!ctx || ctx->search_paths.empty()) {
|
||||
const char *envPROJ_LIB = getenv("PROJ_LIB");
|
||||
buf = path_append(buf, envPROJ_LIB, &buf_size);
|
||||
// Env var mostly for testing purposes and being independent from
|
||||
// an existing installation
|
||||
const char* ignoreUserWritableDirectory =
|
||||
getenv("PROJ_SKIP_READ_USER_WRITABLE_DIRECTORY");
|
||||
if( ignoreUserWritableDirectory == nullptr ||
|
||||
ignoreUserWritableDirectory[0] == '\0' ) {
|
||||
buf = path_append(buf,
|
||||
pj_context_get_user_writable_directory(ctx, false).c_str(),
|
||||
&buf_size);
|
||||
}
|
||||
const std::string envPROJ_LIB = NS_PROJ::FileManager::getProjLibEnvVar(ctx);
|
||||
buf = path_append(buf, envPROJ_LIB.empty() ? nullptr : envPROJ_LIB.c_str(), &buf_size);
|
||||
#ifdef PROJ_LIB
|
||||
if (envPROJ_LIB == nullptr) {
|
||||
if (envPROJ_LIB.empty()) {
|
||||
buf = path_append(buf, PROJ_LIB, &buf_size);
|
||||
}
|
||||
#endif
|
||||
@@ -1583,43 +1601,65 @@ PJ_GRID_INFO proj_grid_info(const char *gridname) {
|
||||
|
||||
/*PJ_CONTEXT *ctx = proj_context_create(); */
|
||||
PJ_CONTEXT *ctx = pj_get_default_ctx();
|
||||
PJ_GRIDINFO *gridinfo = pj_gridinfo_init(ctx, gridname);
|
||||
memset(&grinfo, 0, sizeof(PJ_GRID_INFO));
|
||||
|
||||
/* in case the grid wasn't found */
|
||||
if (gridinfo->filename == nullptr || gridinfo->ct == nullptr) {
|
||||
pj_gridinfo_free(ctx, gridinfo);
|
||||
strcpy(grinfo.format, "missing");
|
||||
return grinfo;
|
||||
const auto fillGridInfo = [&grinfo, ctx, gridname]
|
||||
(const NS_PROJ::Grid& grid, const std::string& format)
|
||||
{
|
||||
const auto& extent = grid.extentAndRes();
|
||||
|
||||
/* name of grid */
|
||||
strncpy (grinfo.gridname, gridname, sizeof(grinfo.gridname) - 1);
|
||||
|
||||
/* full path of grid */
|
||||
pj_find_file(ctx, gridname, grinfo.filename, sizeof(grinfo.filename) - 1);
|
||||
|
||||
/* grid format */
|
||||
strncpy (grinfo.format, format.c_str(), sizeof(grinfo.format) - 1);
|
||||
|
||||
/* grid size */
|
||||
grinfo.n_lon = grid.width();
|
||||
grinfo.n_lat = grid.height();
|
||||
|
||||
/* cell size */
|
||||
grinfo.cs_lon = extent.resLon;
|
||||
grinfo.cs_lat = extent.resLat;
|
||||
|
||||
/* bounds of grid */
|
||||
grinfo.lowerleft.lam = extent.westLon;
|
||||
grinfo.lowerleft.phi = extent.southLat;
|
||||
grinfo.upperright.lam = extent.eastLon;
|
||||
grinfo.upperright.phi = extent.northLat;
|
||||
};
|
||||
|
||||
{
|
||||
const auto gridSet = NS_PROJ::VerticalShiftGridSet::open(ctx, gridname);
|
||||
if( gridSet )
|
||||
{
|
||||
const auto& grids = gridSet->grids();
|
||||
if( !grids.empty() )
|
||||
{
|
||||
const auto& grid = grids.front();
|
||||
fillGridInfo(*grid, gridSet->format());
|
||||
return grinfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The string copies below are automatically null-terminated due to */
|
||||
/* the memset above, so strncpy is safe */
|
||||
|
||||
/* name of grid */
|
||||
strncpy (grinfo.gridname, gridname, sizeof(grinfo.gridname) - 1);
|
||||
|
||||
/* full path of grid */
|
||||
pj_find_file(ctx, gridname, grinfo.filename, sizeof(grinfo.filename) - 1);
|
||||
|
||||
/* grid format */
|
||||
strncpy (grinfo.format, gridinfo->format, sizeof(grinfo.format) - 1);
|
||||
|
||||
/* grid size */
|
||||
grinfo.n_lon = gridinfo->ct->lim.lam;
|
||||
grinfo.n_lat = gridinfo->ct->lim.phi;
|
||||
|
||||
/* cell size */
|
||||
grinfo.cs_lon = gridinfo->ct->del.lam;
|
||||
grinfo.cs_lat = gridinfo->ct->del.phi;
|
||||
|
||||
/* bounds of grid */
|
||||
grinfo.lowerleft = gridinfo->ct->ll;
|
||||
grinfo.upperright.lam = grinfo.lowerleft.lam + grinfo.n_lon*grinfo.cs_lon;
|
||||
grinfo.upperright.phi = grinfo.lowerleft.phi + grinfo.n_lat*grinfo.cs_lat;
|
||||
|
||||
pj_gridinfo_free(ctx, gridinfo);
|
||||
|
||||
{
|
||||
const auto gridSet = NS_PROJ::HorizontalShiftGridSet::open(ctx, gridname);
|
||||
if( gridSet )
|
||||
{
|
||||
const auto& grids = gridSet->grids();
|
||||
if( !grids.empty() )
|
||||
{
|
||||
const auto& grid = grids.front();
|
||||
fillGridInfo(*grid, gridSet->format());
|
||||
return grinfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
strcpy(grinfo.format, "missing");
|
||||
return grinfo;
|
||||
}
|
||||
|
||||
@@ -1763,3 +1803,4 @@ PJ_FACTORS proj_factors(PJ *P, PJ_COORD lp) {
|
||||
|
||||
return factors;
|
||||
}
|
||||
|
||||
|
||||
+16
-9
@@ -7,7 +7,7 @@ TESTS = geodtest
|
||||
check_PROGRAMS = geodtest
|
||||
|
||||
AM_CPPFLAGS = -DPROJ_LIB=\"$(pkgdatadir)\" \
|
||||
-DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@
|
||||
-DMUTEX_@MUTEX_SETTING@ -I$(top_srcdir)/include @SQLITE3_CFLAGS@ @TIFF_CFLAGS@ @TIFF_ENABLED_FLAGS@ @CURL_CFLAGS@ @CURL_ENABLED_FLAGS@
|
||||
AM_CXXFLAGS = @CXX_WFLAGS@ @FLTO_FLAG@
|
||||
|
||||
include_HEADERS = proj.h proj_experimental.h proj_constants.h proj_api.h geodesic.h \
|
||||
@@ -43,7 +43,7 @@ geodtest_LDADD = libproj.la
|
||||
lib_LTLIBRARIES = libproj.la
|
||||
|
||||
libproj_la_LDFLAGS = -no-undefined -version-info 18:0:3
|
||||
libproj_la_LIBADD = @SQLITE3_LIBS@
|
||||
libproj_la_LIBADD = @SQLITE3_LIBS@ @TIFF_LIBS@ @CURL_LIBS@
|
||||
|
||||
libproj_la_SOURCES = \
|
||||
pj_list.h proj_internal.h \
|
||||
@@ -183,23 +183,22 @@ libproj_la_SOURCES = \
|
||||
transformations/horner.cpp \
|
||||
transformations/molodensky.cpp \
|
||||
transformations/vgridshift.cpp \
|
||||
transformations/xyzgridshift.cpp \
|
||||
\
|
||||
aasincos.cpp adjlon.cpp \
|
||||
dmstor.cpp auth.cpp \
|
||||
deriv.cpp ell_set.cpp ellps.cpp errno.cpp \
|
||||
factors.cpp fwd.cpp init.cpp inv.cpp \
|
||||
list.cpp malloc.cpp mlfn.cpp msfn.cpp proj_mdist.cpp \
|
||||
open_lib.cpp param.cpp phi2.cpp pr_list.cpp \
|
||||
param.cpp phi2.cpp pr_list.cpp \
|
||||
qsfn.cpp strerrno.cpp \
|
||||
tsfn.cpp units.cpp ctx.cpp log.cpp zpoly1.cpp rtodms.cpp \
|
||||
release.cpp gauss.cpp \
|
||||
fileapi.cpp \
|
||||
\
|
||||
gc_reader.cpp gridcatalog.cpp \
|
||||
nad_cvt.cpp nad_init.cpp nad_intr.cpp \
|
||||
apply_gridshift.cpp datums.cpp datum_set.cpp transform.cpp \
|
||||
geocent.cpp geocent.h utils.cpp gridinfo.cpp gridlist.cpp \
|
||||
mutex.cpp initcache.cpp apply_vgridshift.cpp geodesic.c \
|
||||
datums.cpp datum_set.cpp transform.cpp \
|
||||
geocent.cpp geocent.h utils.cpp \
|
||||
mutex.cpp initcache.cpp geodesic.c \
|
||||
strtod.cpp \
|
||||
\
|
||||
4D_api.cpp pipeline.cpp \
|
||||
@@ -213,7 +212,15 @@ libproj_la_SOURCES = \
|
||||
proj_json_streaming_writer.hpp \
|
||||
proj_json_streaming_writer.cpp \
|
||||
\
|
||||
tracing.cpp
|
||||
tracing.cpp \
|
||||
\
|
||||
grids.hpp \
|
||||
grids.cpp \
|
||||
filemanager.hpp \
|
||||
filemanager.cpp \
|
||||
networkfilemanager.cpp \
|
||||
sqlite3_utils.hpp \
|
||||
sqlite3_utils.cpp
|
||||
|
||||
|
||||
# The sed hack is to please MSVC
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Apply datum shifts based on grid shift files (normally NAD27 to
|
||||
* NAD83 or the reverse). This module is responsible for keeping
|
||||
* a list of loaded grids, and calling with each one that is
|
||||
* allowed for a given datum (expressed as the nadgrids= parameter).
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj_internal.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_apply_gridshift() */
|
||||
/* */
|
||||
/* This is the externally callable interface - part of the */
|
||||
/* public API - though it is not used internally any more and I */
|
||||
/* doubt it is used by any other applications. But we preserve */
|
||||
/* it to honour our public api. */
|
||||
/************************************************************************/
|
||||
|
||||
int pj_apply_gridshift( projCtx ctx, const char *nadgrids, int inverse,
|
||||
long point_count, int point_offset,
|
||||
double *x, double *y, double *z )
|
||||
|
||||
{
|
||||
PJ_GRIDINFO **gridlist;
|
||||
int grid_count;
|
||||
int ret;
|
||||
|
||||
gridlist = pj_gridlist_from_nadgrids( ctx, nadgrids, &grid_count );
|
||||
|
||||
if( gridlist == nullptr || grid_count == 0 )
|
||||
{
|
||||
pj_dalloc( gridlist );
|
||||
return ctx->last_errno;
|
||||
}
|
||||
|
||||
ret = pj_apply_gridshift_3( ctx, gridlist, grid_count, inverse,
|
||||
point_count, point_offset, x, y, z );
|
||||
|
||||
/*
|
||||
** Note this frees the array of grid list pointers, but not the grids
|
||||
** which is as intended. The grids themselves live on.
|
||||
*/
|
||||
pj_dalloc( gridlist );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_apply_gridshift_2() */
|
||||
/* */
|
||||
/* This implementation uses the gridlist from a coordinate */
|
||||
/* system definition. If the gridlist has not yet been */
|
||||
/* populated in the coordinate system definition we set it up */
|
||||
/* now. */
|
||||
/************************************************************************/
|
||||
|
||||
int pj_apply_gridshift_2( PJ *defn, int inverse,
|
||||
long point_count, int point_offset,
|
||||
double *x, double *y, double *z )
|
||||
|
||||
{
|
||||
if( defn->catalog_name != nullptr )
|
||||
return pj_gc_apply_gridshift( defn, inverse, point_count, point_offset,
|
||||
x, y, z );
|
||||
|
||||
if( defn->gridlist == nullptr )
|
||||
{
|
||||
defn->gridlist =
|
||||
pj_gridlist_from_nadgrids( pj_get_ctx( defn ),
|
||||
pj_param(defn->ctx, defn->params,"snadgrids").s,
|
||||
&(defn->gridlist_count) );
|
||||
|
||||
if( defn->gridlist == nullptr || defn->gridlist_count == 0 )
|
||||
return defn->ctx->last_errno;
|
||||
}
|
||||
|
||||
return pj_apply_gridshift_3( pj_get_ctx( defn ),
|
||||
defn->gridlist, defn->gridlist_count, inverse,
|
||||
point_count, point_offset, x, y, z );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* find_ctable() */
|
||||
/* */
|
||||
/* Determine which grid is the correct given an input coordinate. */
|
||||
/************************************************************************/
|
||||
|
||||
struct CTABLE* find_ctable(projCtx ctx, PJ_LP input, int grid_count, PJ_GRIDINFO **tables) {
|
||||
int itable;
|
||||
|
||||
/* keep trying till we find a table that works */
|
||||
for( itable = 0; itable < grid_count; itable++ )
|
||||
{
|
||||
|
||||
PJ_GRIDINFO *gi = tables[itable];
|
||||
struct CTABLE *ct = gi->ct;
|
||||
double epsilon = (fabs(ct->del.phi)+fabs(ct->del.lam))/10000.0;
|
||||
/* skip tables that don't match our point at all. */
|
||||
if ( ct->ll.phi - epsilon > input.phi
|
||||
|| ct->ll.lam - epsilon > input.lam
|
||||
|| (ct->ll.phi + (ct->lim.phi-1) * ct->del.phi + epsilon < input.phi)
|
||||
|| (ct->ll.lam + (ct->lim.lam-1) * ct->del.lam + epsilon < input.lam) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we have child nodes, check to see if any of them apply. */
|
||||
while( gi->child )
|
||||
{
|
||||
PJ_GRIDINFO *child;
|
||||
|
||||
for( child = gi->child; child != nullptr; child = child->next )
|
||||
{
|
||||
struct CTABLE *ct1 = child->ct;
|
||||
epsilon = (fabs(ct1->del.phi)+fabs(ct1->del.lam))/10000.0;
|
||||
|
||||
if( ct1->ll.phi - epsilon > input.phi
|
||||
|| ct1->ll.lam - epsilon > input.lam
|
||||
|| (ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi + epsilon < input.phi)
|
||||
|| (ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam + epsilon < input.lam) ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't find a child then nothing more to do */
|
||||
if( child == nullptr ) break;
|
||||
|
||||
/* Otherwise use the child, first checking it's children */
|
||||
gi = child;
|
||||
ct = child->ct;
|
||||
}
|
||||
/* load the grid shift info if we don't have it. */
|
||||
if( ct->cvs == nullptr) {
|
||||
if (!pj_gridinfo_load( ctx, gi ) ) {
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
/* if we get this far we have found a suitable grid */
|
||||
return ct;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_apply_gridshift_3() */
|
||||
/* */
|
||||
/* This is the real workhorse, given a gridlist. */
|
||||
/************************************************************************/
|
||||
|
||||
int pj_apply_gridshift_3( projCtx ctx, PJ_GRIDINFO **gridlist, int gridlist_count,
|
||||
int inverse, long point_count, int point_offset,
|
||||
double *x, double *y, double *z )
|
||||
{
|
||||
int i;
|
||||
struct CTABLE *ct;
|
||||
static int debug_count = 0;
|
||||
(void) z;
|
||||
|
||||
if( gridlist== nullptr || gridlist_count == 0 )
|
||||
{
|
||||
pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
|
||||
ctx->last_errno = 0;
|
||||
|
||||
for( i = 0; i < point_count; i++ )
|
||||
{
|
||||
long io = i * point_offset;
|
||||
PJ_LP input, output;
|
||||
int itable;
|
||||
|
||||
input.phi = y[io];
|
||||
input.lam = x[io];
|
||||
output.phi = HUGE_VAL;
|
||||
output.lam = HUGE_VAL;
|
||||
|
||||
ct = find_ctable(ctx, input, gridlist_count, gridlist);
|
||||
if( ct != nullptr )
|
||||
{
|
||||
output = nad_cvt( ctx, input, inverse, ct, gridlist_count, gridlist);
|
||||
|
||||
if ( output.lam != HUGE_VAL && debug_count++ < 20 )
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MINOR, "pj_apply_gridshift(): used %s", ct->id );
|
||||
}
|
||||
|
||||
if ( output.lam == HUGE_VAL )
|
||||
{
|
||||
if( ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"pj_apply_gridshift(): failed to find a grid shift table for\n"
|
||||
" location (%.7fdW,%.7fdN)",
|
||||
x[io] * RAD_TO_DEG,
|
||||
y[io] * RAD_TO_DEG );
|
||||
for( itable = 0; itable < gridlist_count; itable++ )
|
||||
{
|
||||
PJ_GRIDINFO *gi = gridlist[itable];
|
||||
if( itable == 0 )
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR, " tried: %s", gi->gridname );
|
||||
else
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR, ",%s", gi->gridname );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't actually have any machinery currently to set the
|
||||
* following macro, so this is mostly kept here to make it clear
|
||||
* how we ought to operate if we wanted to make it super clear
|
||||
* that an error has occurred when points are outside our available
|
||||
* datum shift areas. But if this is on, we will find that "low
|
||||
* value" points on the fringes of some datasets will completely
|
||||
* fail causing lots of problems when it is more or less ok to
|
||||
* just not apply a datum shift. So rather than deal with
|
||||
* that we just fallback to no shift. (see also bug #45).
|
||||
*/
|
||||
#ifdef ERR_GRID_AREA_TRANSIENT_SEVERE
|
||||
y[io] = HUGE_VAL;
|
||||
x[io] = HUGE_VAL;
|
||||
#else
|
||||
/* leave x/y unshifted. */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
y[io] = output.phi;
|
||||
x[io] = output.lam;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
int proj_hgrid_init(PJ* P, const char *grids) {
|
||||
/**********************************************
|
||||
|
||||
Initizalize and populate list of horizontal
|
||||
grids.
|
||||
|
||||
Takes a PJ-object and the plus-parameter
|
||||
name that is used in the proj-string to
|
||||
specify the grids to load, e.g. "+grids".
|
||||
The + should be left out here.
|
||||
|
||||
Returns the number of loaded grids.
|
||||
|
||||
***********************************************/
|
||||
|
||||
/* prepend "s" to the "grids" string to allow usage with pj_param */
|
||||
char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) );
|
||||
sprintf(sgrids, "%s%s", "s", grids);
|
||||
|
||||
if (P->gridlist == nullptr) {
|
||||
P->gridlist = pj_gridlist_from_nadgrids(
|
||||
P->ctx,
|
||||
pj_param(P->ctx, P->params, sgrids).s,
|
||||
&(P->gridlist_count)
|
||||
);
|
||||
|
||||
if( P->gridlist == nullptr || P->gridlist_count == 0 ) {
|
||||
pj_dealloc(sgrids);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (P->gridlist_count == 0) {
|
||||
proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID);
|
||||
}
|
||||
|
||||
pj_dealloc(sgrids);
|
||||
return P->gridlist_count;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
/* proj_hgrid_value() */
|
||||
/* */
|
||||
/* Return coordinate offset in grid */
|
||||
/********************************************/
|
||||
PJ_LP proj_hgrid_value(PJ *P, PJ_LP lp) {
|
||||
struct CTABLE *ct;
|
||||
PJ_LP out = proj_coord_error().lp;
|
||||
|
||||
ct = find_ctable(P->ctx, lp, P->gridlist_count, P->gridlist);
|
||||
if (ct == nullptr) {
|
||||
pj_ctx_set_errno( P->ctx, PJD_ERR_GRID_AREA);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* normalize input to ll origin */
|
||||
lp.lam -= ct->ll.lam;
|
||||
lp.phi -= ct->ll.phi;
|
||||
|
||||
lp.lam = adjlon(lp.lam - M_PI) + M_PI;
|
||||
|
||||
out = nad_intr(lp, ct);
|
||||
|
||||
if (out.lam == HUGE_VAL || out.phi == HUGE_VAL) {
|
||||
pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
PJ_LP proj_hgrid_apply(PJ *P, PJ_LP lp, PJ_DIRECTION direction) {
|
||||
struct CTABLE *ct;
|
||||
int inverse;
|
||||
PJ_LP out;
|
||||
|
||||
out.lam = HUGE_VAL; out.phi = HUGE_VAL;
|
||||
|
||||
ct = find_ctable(P->ctx, lp, P->gridlist_count, P->gridlist);
|
||||
|
||||
if (ct == nullptr || ct->cvs == nullptr) {
|
||||
if( P->gridlist_count == 1 &&
|
||||
strcmp(P->gridlist[0]->gridname, "null") == 0) {
|
||||
// TODO: remove this particular case that is put there just to be
|
||||
// able to handle longitudes outside of -180,180
|
||||
out = lp;
|
||||
} else {
|
||||
pj_ctx_set_errno( P->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
inverse = direction == PJ_FWD ? 0 : 1;
|
||||
out = nad_cvt(P->ctx, lp, inverse, ct, P->gridlist_count, P->gridlist);
|
||||
|
||||
if (out.lam == HUGE_VAL || out.phi == HUGE_VAL)
|
||||
pj_ctx_set_errno(P->ctx, PJD_ERR_GRID_AREA);
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
@@ -1,361 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Apply vertical datum shifts based on grid shift files, normally
|
||||
* geoid grids mapping WGS84 to NAVD88 or something similar.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
#include "proj_internal.h"
|
||||
|
||||
static int is_nodata(float value, double vmultiplier)
|
||||
{
|
||||
/* nodata? */
|
||||
/* GTX official nodata value if -88.88880f, but some grids also */
|
||||
/* use other big values for nodata (e.g naptrans2008.gtx has */
|
||||
/* nodata values like -2147479936), so test them too */
|
||||
return value * vmultiplier > 1000 || value * vmultiplier < -1000 || value == -88.88880f;
|
||||
}
|
||||
|
||||
static double read_vgrid_value( PJ *defn, PJ_LP input, double vmultiplier, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) {
|
||||
int itable = 0;
|
||||
double value = HUGE_VAL;
|
||||
double grid_x, grid_y;
|
||||
long grid_ix, grid_iy;
|
||||
long grid_ix2, grid_iy2;
|
||||
float *cvs;
|
||||
/* do not deal with NaN coordinates */
|
||||
/* cppcheck-suppress duplicateExpression */
|
||||
if( isnan(input.phi) || isnan(input.lam) )
|
||||
itable = *gridlist_count_p;
|
||||
|
||||
/* keep trying till we find a table that works */
|
||||
for ( ; itable < *gridlist_count_p; itable++ )
|
||||
{
|
||||
PJ_GRIDINFO *gi = tables[itable];
|
||||
|
||||
ct = gi->ct;
|
||||
|
||||
/* skip tables that don't match our point at all (latitude check). */
|
||||
if( ct->ll.phi > input.phi
|
||||
|| ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi )
|
||||
continue;
|
||||
|
||||
bool fullWorldLongExtent = false;
|
||||
if( fabs(ct->lim.lam * ct->del.lam - 2 * M_PI) < 1e-10 )
|
||||
{
|
||||
fullWorldLongExtent = true;
|
||||
}
|
||||
|
||||
/* skip tables that don't match our point at all (longitude check). */
|
||||
else if( ct->ll.lam > input.lam
|
||||
|| ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam )
|
||||
continue;
|
||||
|
||||
/* If we have child nodes, check to see if any of them apply. */
|
||||
while( gi->child != nullptr )
|
||||
{
|
||||
PJ_GRIDINFO *child;
|
||||
|
||||
for( child = gi->child; child != nullptr; child = child->next )
|
||||
{
|
||||
struct CTABLE *ct1 = child->ct;
|
||||
|
||||
fullWorldLongExtent = false;
|
||||
|
||||
if( ct1->ll.phi > input.phi
|
||||
|| ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi)
|
||||
continue;
|
||||
|
||||
if( fabs(ct1->lim.lam * ct1->del.lam - 2 * M_PI) < 1e-10 )
|
||||
{
|
||||
fullWorldLongExtent = true;
|
||||
}
|
||||
else if( ct1->ll.lam > input.lam
|
||||
|| ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* we didn't find a more refined child node to use, so go with current grid */
|
||||
if( child == nullptr )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise let's try for childrens children .. */
|
||||
gi = child;
|
||||
ct = child->ct;
|
||||
}
|
||||
|
||||
/* load the grid shift info if we don't have it. */
|
||||
if( ct->cvs == nullptr )
|
||||
{
|
||||
pj_gridinfo_load( pj_get_ctx(defn), gi );
|
||||
}
|
||||
if( ct->cvs == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
|
||||
/* Interpolation a location within the grid */
|
||||
grid_x = (input.lam - ct->ll.lam) / ct->del.lam;
|
||||
if( fullWorldLongExtent ) {
|
||||
// The first fmod goes to ]-lim, lim[ range
|
||||
// So we add lim again to be in ]0, 2*lim[ and fmod again
|
||||
grid_x = fmod(
|
||||
fmod(grid_x + ct->lim.lam, ct->lim.lam) + ct->lim.lam,
|
||||
ct->lim.lam);
|
||||
}
|
||||
grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
|
||||
grid_ix = lround(floor(grid_x));
|
||||
assert(grid_ix >= 0 && grid_ix < ct->lim.lam);
|
||||
grid_iy = lround(floor(grid_y));
|
||||
assert(grid_iy >= 0 && grid_iy < ct->lim.phi);
|
||||
grid_x -= grid_ix;
|
||||
grid_y -= grid_iy;
|
||||
|
||||
grid_ix2 = grid_ix + 1;
|
||||
if( grid_ix2 >= ct->lim.lam ) {
|
||||
if( fullWorldLongExtent ) {
|
||||
grid_ix2 = 0;
|
||||
} else {
|
||||
grid_ix2 = ct->lim.lam - 1;
|
||||
}
|
||||
}
|
||||
grid_iy2 = grid_iy + 1;
|
||||
if( grid_iy2 >= ct->lim.phi )
|
||||
grid_iy2 = ct->lim.phi - 1;
|
||||
|
||||
cvs = (float *) ct->cvs;
|
||||
{
|
||||
float value_a = cvs[grid_ix + grid_iy * ct->lim.lam];
|
||||
float value_b = cvs[grid_ix2 + grid_iy * ct->lim.lam];
|
||||
float value_c = cvs[grid_ix + grid_iy2 * ct->lim.lam];
|
||||
float value_d = cvs[grid_ix2 + grid_iy2 * ct->lim.lam];
|
||||
double total_weight = 0.0;
|
||||
int n_weights = 0;
|
||||
value = 0.0f;
|
||||
if( !is_nodata(value_a, vmultiplier) )
|
||||
{
|
||||
double weight = (1.0-grid_x) * (1.0-grid_y);
|
||||
value += value_a * weight;
|
||||
total_weight += weight;
|
||||
n_weights ++;
|
||||
}
|
||||
if( !is_nodata(value_b, vmultiplier) )
|
||||
{
|
||||
double weight = (grid_x) * (1.0-grid_y);
|
||||
value += value_b * weight;
|
||||
total_weight += weight;
|
||||
n_weights ++;
|
||||
}
|
||||
if( !is_nodata(value_c, vmultiplier) )
|
||||
{
|
||||
double weight = (1.0-grid_x) * (grid_y);
|
||||
value += value_c * weight;
|
||||
total_weight += weight;
|
||||
n_weights ++;
|
||||
}
|
||||
if( !is_nodata(value_d, vmultiplier) )
|
||||
{
|
||||
double weight = (grid_x) * (grid_y);
|
||||
value += value_d * weight;
|
||||
total_weight += weight;
|
||||
n_weights ++;
|
||||
}
|
||||
if( n_weights == 0 )
|
||||
value = HUGE_VAL;
|
||||
else if( n_weights != 4 )
|
||||
value /= total_weight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return value * vmultiplier;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_apply_vgridshift() */
|
||||
/* */
|
||||
/* This implementation takes uses the gridlist from a coordinate */
|
||||
/* system definition. If the gridlist has not yet been */
|
||||
/* populated in the coordinate system definition we set it up */
|
||||
/* now. */
|
||||
/************************************************************************/
|
||||
int pj_apply_vgridshift( PJ *defn, const char *listname,
|
||||
PJ_GRIDINFO ***gridlist_p,
|
||||
int *gridlist_count_p,
|
||||
int inverse,
|
||||
long point_count, int point_offset,
|
||||
double *x, double *y, double *z )
|
||||
|
||||
{
|
||||
int i;
|
||||
static int debug_count = 0;
|
||||
PJ_GRIDINFO **tables;
|
||||
struct CTABLE ct;
|
||||
|
||||
if( *gridlist_p == nullptr )
|
||||
{
|
||||
*gridlist_p =
|
||||
pj_gridlist_from_nadgrids( pj_get_ctx(defn),
|
||||
pj_param(defn->ctx,defn->params,listname).s,
|
||||
gridlist_count_p );
|
||||
|
||||
if( *gridlist_p == nullptr || *gridlist_count_p == 0 )
|
||||
return defn->ctx->last_errno;
|
||||
}
|
||||
|
||||
if( *gridlist_count_p == 0 )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
|
||||
tables = *gridlist_p;
|
||||
defn->ctx->last_errno = 0;
|
||||
|
||||
for( i = 0; i < point_count; i++ )
|
||||
{
|
||||
double value;
|
||||
long io = i * point_offset;
|
||||
PJ_LP input;
|
||||
|
||||
input.phi = y[io];
|
||||
input.lam = x[io];
|
||||
|
||||
value = read_vgrid_value(defn, input, 1.0, gridlist_count_p, tables, &ct);
|
||||
|
||||
if( inverse )
|
||||
z[io] -= value;
|
||||
else
|
||||
z[io] += value;
|
||||
if( value != HUGE_VAL )
|
||||
{
|
||||
if( debug_count++ < 20 ) {
|
||||
proj_log_trace(defn, "pj_apply_gridshift(): used %s", ct.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( value == HUGE_VAL )
|
||||
{
|
||||
int itable;
|
||||
std::string gridlist;
|
||||
|
||||
proj_log_debug(defn,
|
||||
"pj_apply_vgridshift(): failed to find a grid shift table for\n"
|
||||
" location (%.7fdW,%.7fdN)",
|
||||
x[io] * RAD_TO_DEG,
|
||||
y[io] * RAD_TO_DEG );
|
||||
|
||||
for( itable = 0; itable < *gridlist_count_p; itable++ )
|
||||
{
|
||||
PJ_GRIDINFO *gi = tables[itable];
|
||||
if( itable == 0 )
|
||||
gridlist += " tried: ";
|
||||
else
|
||||
gridlist += ',';
|
||||
gridlist += gi->gridname;
|
||||
}
|
||||
|
||||
proj_log_debug(defn, "%s", gridlist.c_str());
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA );
|
||||
|
||||
return PJD_ERR_GRID_AREA;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************************************/
|
||||
int proj_vgrid_init(PJ* P, const char *grids) {
|
||||
/**********************************************
|
||||
|
||||
Initizalize and populate gridlist.
|
||||
|
||||
Takes a PJ-object and the plus-parameter
|
||||
name that is used in the proj-string to
|
||||
specify the grids to load, e.g. "+grids".
|
||||
The + should be left out here.
|
||||
|
||||
Returns the number of loaded grids.
|
||||
|
||||
***********************************************/
|
||||
|
||||
/* prepend "s" to the "grids" string to allow usage with pj_param */
|
||||
char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) );
|
||||
sprintf(sgrids, "%s%s", "s", grids);
|
||||
|
||||
if (P->vgridlist_geoid == nullptr) {
|
||||
P->vgridlist_geoid = pj_gridlist_from_nadgrids(
|
||||
P->ctx,
|
||||
pj_param(P->ctx, P->params, sgrids).s,
|
||||
&(P->vgridlist_geoid_count)
|
||||
);
|
||||
|
||||
if( P->vgridlist_geoid == nullptr || P->vgridlist_geoid_count == 0 ) {
|
||||
pj_dealloc(sgrids);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (P->vgridlist_geoid_count == 0) {
|
||||
proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID);
|
||||
}
|
||||
|
||||
pj_dealloc(sgrids);
|
||||
return P->vgridlist_geoid_count;
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
double proj_vgrid_value(PJ *P, PJ_LP lp, double vmultiplier){
|
||||
/***********************************************
|
||||
|
||||
Read grid value at position lp in grids loaded
|
||||
with proj_grid_init.
|
||||
|
||||
Returns the grid value of the given coordinate.
|
||||
|
||||
************************************************/
|
||||
|
||||
struct CTABLE used_grid;
|
||||
double value;
|
||||
memset(&used_grid, 0, sizeof(struct CTABLE));
|
||||
|
||||
value = read_vgrid_value(P, lp, vmultiplier, &(P->vgridlist_geoid_count), P->vgridlist_geoid, &used_grid);
|
||||
proj_log_trace(P, "proj_vgrid_value: (%f, %f) = %f", lp.lam*RAD_TO_DEG, lp.phi*RAD_TO_DEG, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -1153,6 +1153,7 @@ static const struct errno_vs_err_const lookup[] = {
|
||||
{"pjd_err_inconsistent_unit" , -59},
|
||||
{"pjd_err_mutually_exclusive_args" , -60},
|
||||
{"pjd_err_generic_error" , -61},
|
||||
{"pjd_err_network_error" , -62},
|
||||
{"pjd_err_dont_skip" , 5555},
|
||||
{"pjd_err_unknown" , 9999},
|
||||
{"pjd_err_enomem" , ENOMEM},
|
||||
|
||||
+22
-8
@@ -87,7 +87,8 @@ static void usage() {
|
||||
<< " [--spatial-test contains|intersects]" << std::endl
|
||||
<< " [--crs-extent-use none|both|intersection|smallest]"
|
||||
<< std::endl
|
||||
<< " [--grid-check none|discard_missing|sort] "
|
||||
<< " [--grid-check "
|
||||
"none|discard_missing|sort|known_available] "
|
||||
"[--show-superseded]"
|
||||
<< std::endl
|
||||
<< " [--pivot-crs always|if_no_direct_transformation|"
|
||||
@@ -554,7 +555,7 @@ static void outputObject(
|
||||
auto op = dynamic_cast<CoordinateOperation *>(obj.get());
|
||||
if (op && dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) {
|
||||
try {
|
||||
auto setGrids = op->gridsNeeded(dbContext);
|
||||
auto setGrids = op->gridsNeeded(dbContext, false);
|
||||
bool firstWarning = true;
|
||||
for (const auto &grid : setGrids) {
|
||||
if (!grid.available) {
|
||||
@@ -570,6 +571,7 @@ static void outputObject(
|
||||
if (!grid.url.empty()) {
|
||||
std::cout << " at " << grid.url;
|
||||
}
|
||||
std::cout << ", or on CDN";
|
||||
} else if (!grid.url.empty()) {
|
||||
std::cout << " Can be obtained at " << grid.url;
|
||||
}
|
||||
@@ -584,8 +586,9 @@ static void outputObject(
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
static void outputOperationSummary(const CoordinateOperationNNPtr &op,
|
||||
const DatabaseContextPtr &dbContext) {
|
||||
static void outputOperationSummary(
|
||||
const CoordinateOperationNNPtr &op, const DatabaseContextPtr &dbContext,
|
||||
CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse) {
|
||||
auto ids = op->identifiers();
|
||||
if (!ids.empty()) {
|
||||
std::cout << *(ids[0]->codeSpace()) << ":" << ids[0]->code();
|
||||
@@ -631,10 +634,16 @@ static void outputOperationSummary(const CoordinateOperationNNPtr &op,
|
||||
|
||||
if (dbContext && getenv("PROJINFO_NO_GRID_CHECK") == nullptr) {
|
||||
try {
|
||||
auto setGrids = op->gridsNeeded(dbContext);
|
||||
auto setGrids = op->gridsNeeded(dbContext, false);
|
||||
for (const auto &grid : setGrids) {
|
||||
if (!grid.available) {
|
||||
std::cout << ", at least one grid missing";
|
||||
if (gridAvailabilityUse ==
|
||||
CoordinateOperationContext::GridAvailabilityUse::
|
||||
KNOWN_AVAILABLE &&
|
||||
!grid.packageName.empty()) {
|
||||
std::cout << " on the system, but available on CDN";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -731,7 +740,7 @@ static void outputOperations(
|
||||
}
|
||||
if (summary) {
|
||||
for (const auto &op : list) {
|
||||
outputOperationSummary(op, dbContext);
|
||||
outputOperationSummary(op, dbContext, gridAvailabilityUse);
|
||||
}
|
||||
} else {
|
||||
bool first = true;
|
||||
@@ -744,7 +753,7 @@ static void outputOperations(
|
||||
std::cout << "-------------------------------------" << std::endl;
|
||||
std::cout << "Operation No. " << (i + 1) << ":" << std::endl
|
||||
<< std::endl;
|
||||
outputOperationSummary(op, dbContext);
|
||||
outputOperationSummary(op, dbContext, gridAvailabilityUse);
|
||||
std::cout << std::endl;
|
||||
outputObject(dbContext, op, allowUseIntermediateCRS, outputOpt);
|
||||
}
|
||||
@@ -777,7 +786,9 @@ int main(int argc, char **argv) {
|
||||
CoordinateOperationContext::SourceTargetCRSExtentUse::SMALLEST;
|
||||
bool buildBoundCRSToWGS84 = false;
|
||||
CoordinateOperationContext::GridAvailabilityUse gridAvailabilityUse =
|
||||
CoordinateOperationContext::GridAvailabilityUse::USE_FOR_SORTING;
|
||||
pj_context_is_network_enabled(nullptr)
|
||||
? CoordinateOperationContext::GridAvailabilityUse::KNOWN_AVAILABLE
|
||||
: CoordinateOperationContext::GridAvailabilityUse::USE_FOR_SORTING;
|
||||
CoordinateOperationContext::IntermediateCRSUse allowUseIntermediateCRS =
|
||||
CoordinateOperationContext::IntermediateCRSUse::
|
||||
IF_NO_DIRECT_TRANSFORMATION;
|
||||
@@ -992,6 +1003,9 @@ int main(int argc, char **argv) {
|
||||
} else if (ci_equal(value, "sort")) {
|
||||
gridAvailabilityUse = CoordinateOperationContext::
|
||||
GridAvailabilityUse::USE_FOR_SORTING;
|
||||
} else if (ci_equal(value, "known_available")) {
|
||||
gridAvailabilityUse = CoordinateOperationContext::
|
||||
GridAvailabilityUse::KNOWN_AVAILABLE;
|
||||
} else {
|
||||
std::cerr << "Unrecognized value for option --grid-check: "
|
||||
<< value << std::endl;
|
||||
|
||||
+7
-29
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "proj_experimental.h"
|
||||
#include "proj_internal.h"
|
||||
#include "filemanager.hpp"
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_get_ctx() */
|
||||
@@ -60,9 +61,9 @@ void pj_set_ctx( projPJ pj, projCtx ctx )
|
||||
if (pj==nullptr)
|
||||
return;
|
||||
pj->ctx = ctx;
|
||||
if( pj->is_pipeline )
|
||||
if( pj->reassign_context )
|
||||
{
|
||||
pj_pipeline_assign_context_to_steps(pj, ctx);
|
||||
pj->reassign_context(pj, ctx);
|
||||
}
|
||||
for( const auto &alt: pj->alternativeCoordinateOperations )
|
||||
{
|
||||
@@ -95,7 +96,8 @@ projCtx_t projCtx_t::createDefault()
|
||||
projCtx_t ctx;
|
||||
ctx.debug_level = PJ_LOG_NONE;
|
||||
ctx.logger = pj_stderr_logger;
|
||||
ctx.fileapi = pj_get_default_fileapi();
|
||||
ctx.fileapi_legacy = pj_get_default_fileapi();
|
||||
NS_PROJ::FileManager::fillDefaultNetworkInterface(&ctx);
|
||||
|
||||
if( getenv("PROJ_DEBUG") != nullptr )
|
||||
{
|
||||
@@ -133,12 +135,13 @@ projCtx_t::projCtx_t(const projCtx_t& other)
|
||||
debug_level = other.debug_level;
|
||||
logger = other.logger;
|
||||
logger_app_data = other.logger_app_data;
|
||||
fileapi = other.fileapi;
|
||||
fileapi_legacy = other.fileapi_legacy;
|
||||
epsg_file_exists = other.epsg_file_exists;
|
||||
set_search_paths(other.search_paths);
|
||||
file_finder = other.file_finder;
|
||||
file_finder_legacy = other.file_finder_legacy;
|
||||
file_finder_user_data = other.file_finder_user_data;
|
||||
networking = other.networking;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -258,28 +261,3 @@ void *pj_ctx_get_app_data( projCtx ctx )
|
||||
return nullptr;
|
||||
return ctx->logger_app_data;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_ctx_set_fileapi() */
|
||||
/************************************************************************/
|
||||
|
||||
void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
|
||||
|
||||
{
|
||||
if (nullptr==ctx)
|
||||
return;
|
||||
ctx->fileapi = fileapi;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_ctx_get_fileapi() */
|
||||
/************************************************************************/
|
||||
|
||||
projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
|
||||
|
||||
{
|
||||
if (nullptr==ctx)
|
||||
return nullptr;
|
||||
return ctx->fileapi;
|
||||
}
|
||||
|
||||
|
||||
+1
-20
@@ -41,7 +41,7 @@
|
||||
int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
|
||||
|
||||
{
|
||||
const char *name, *towgs84, *nadgrids, *catalog;
|
||||
const char *name, *towgs84, *nadgrids;
|
||||
|
||||
projdef->datum_type = PJD_UNKNOWN;
|
||||
|
||||
@@ -117,25 +117,6 @@ int pj_datum_set(projCtx ctx, paralist *pl, PJ *projdef)
|
||||
projdef->datum_type = PJD_GRIDSHIFT;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for grid catalog parameter, and optional date. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
else if( (catalog = pj_param(ctx, pl,"scatalog").s) != nullptr )
|
||||
{
|
||||
const char *date;
|
||||
|
||||
projdef->datum_type = PJD_GRIDSHIFT;
|
||||
projdef->catalog_name = pj_strdup(catalog);
|
||||
if (!projdef->catalog_name) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 1;
|
||||
}
|
||||
|
||||
date = pj_param(ctx, pl, "sdate").s;
|
||||
if( date != nullptr)
|
||||
projdef->datum_date = pj_gc_parsedate( ctx, date);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Check for towgs84 parameter. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
+31
-5
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj_internal.h"
|
||||
#include "filemanager.hpp"
|
||||
|
||||
static PAFile stdio_fopen(projCtx ctx, const char *filename,
|
||||
const char *access);
|
||||
@@ -141,7 +142,7 @@ static void stdio_fclose(PAFile file)
|
||||
|
||||
PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access)
|
||||
{
|
||||
return ctx->fileapi->FOpen(ctx, filename, access);
|
||||
return ctx->fileapi_legacy->FOpen(ctx, filename, access);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -149,7 +150,7 @@ PAFile pj_ctx_fopen(projCtx ctx, const char *filename, const char *access)
|
||||
/************************************************************************/
|
||||
size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile file)
|
||||
{
|
||||
return ctx->fileapi->FRead(buffer, size, nmemb, file);
|
||||
return ctx->fileapi_legacy->FRead(buffer, size, nmemb, file);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -157,7 +158,7 @@ size_t pj_ctx_fread(projCtx ctx, void *buffer, size_t size, size_t nmemb, PAFile
|
||||
/************************************************************************/
|
||||
int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence)
|
||||
{
|
||||
return ctx->fileapi->FSeek(file, offset, whence);
|
||||
return ctx->fileapi_legacy->FSeek(file, offset, whence);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -165,7 +166,7 @@ int pj_ctx_fseek(projCtx ctx, PAFile file, long offset, int whence)
|
||||
/************************************************************************/
|
||||
long pj_ctx_ftell(projCtx ctx, PAFile file)
|
||||
{
|
||||
return ctx->fileapi->FTell(file);
|
||||
return ctx->fileapi_legacy->FTell(file);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -173,7 +174,7 @@ long pj_ctx_ftell(projCtx ctx, PAFile file)
|
||||
/************************************************************************/
|
||||
void pj_ctx_fclose(projCtx ctx, PAFile file)
|
||||
{
|
||||
ctx->fileapi->FClose(file);
|
||||
ctx->fileapi_legacy->FClose(file);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
@@ -212,3 +213,28 @@ char *pj_ctx_fgets(projCtx ctx, char *line, int size, PAFile file)
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_ctx_set_fileapi() */
|
||||
/************************************************************************/
|
||||
|
||||
void pj_ctx_set_fileapi( projCtx ctx, projFileAPI *fileapi )
|
||||
|
||||
{
|
||||
if (nullptr==ctx)
|
||||
return;
|
||||
ctx->fileapi_legacy = fileapi;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_ctx_get_fileapi() */
|
||||
/************************************************************************/
|
||||
|
||||
projFileAPI *pj_ctx_get_fileapi( projCtx ctx )
|
||||
|
||||
{
|
||||
if (nullptr==ctx)
|
||||
return nullptr;
|
||||
return ctx->fileapi_legacy;
|
||||
}
|
||||
|
||||
|
||||
+1733
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ
|
||||
* Purpose: File manager
|
||||
* Author: Even Rouault, <even.rouault at spatialys.com>
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2019, Even Rouault, <even.rouault at spatialys.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef FILEMANAGER_HPP_INCLUDED
|
||||
#define FILEMANAGER_HPP_INCLUDED
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj/util.hpp"
|
||||
|
||||
//! @cond Doxygen_Suppress
|
||||
|
||||
NS_PROJ_START
|
||||
|
||||
class File;
|
||||
|
||||
enum class FileAccess {
|
||||
READ_ONLY, // "rb"
|
||||
READ_UPDATE, // "r+b"
|
||||
CREATE, // "w+b"
|
||||
};
|
||||
|
||||
class FileManager {
|
||||
private:
|
||||
FileManager() = delete;
|
||||
|
||||
public:
|
||||
// "Low-level" interface.
|
||||
static std::unique_ptr<File> open(PJ_CONTEXT *ctx, const char *filename,
|
||||
FileAccess access);
|
||||
static bool exists(PJ_CONTEXT *ctx, const char *filename);
|
||||
static bool mkdir(PJ_CONTEXT *ctx, const char *filename);
|
||||
static bool unlink(PJ_CONTEXT *ctx, const char *filename);
|
||||
static bool rename(PJ_CONTEXT *ctx, const char *oldPath,
|
||||
const char *newPath);
|
||||
static std::string getProjLibEnvVar(PJ_CONTEXT *ctx);
|
||||
|
||||
// "High-level" interface, honoring PROJ_LIB and the like.
|
||||
static std::unique_ptr<File> open_resource_file(PJ_CONTEXT *ctx,
|
||||
const char *name);
|
||||
|
||||
static void fillDefaultNetworkInterface(PJ_CONTEXT *ctx);
|
||||
|
||||
static void clearMemoryCache();
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class File {
|
||||
protected:
|
||||
std::string name_;
|
||||
explicit File(const std::string &name);
|
||||
|
||||
public:
|
||||
virtual ~File();
|
||||
virtual size_t read(void *buffer, size_t sizeBytes) = 0;
|
||||
virtual size_t write(const void *buffer, size_t sizeBytes) = 0;
|
||||
virtual bool seek(unsigned long long offset, int whence = SEEK_SET) = 0;
|
||||
virtual unsigned long long tell() = 0;
|
||||
virtual void reassign_context(PJ_CONTEXT *ctx) = 0;
|
||||
virtual bool hasChanged() const = 0;
|
||||
|
||||
const std::string &name() const { return name_; }
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
std::unique_ptr<File> pj_network_file_open(PJ_CONTEXT *ctx,
|
||||
const char *filename);
|
||||
|
||||
NS_PROJ_END
|
||||
|
||||
//! @endcond Doxygen_Suppress
|
||||
|
||||
#endif // FILEMANAGER_HPP_INCLUDED
|
||||
@@ -1,248 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Code to read a grid catalog from a .cvs file.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj_internal.h"
|
||||
|
||||
static int gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry);
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gc_readcatalog() */
|
||||
/* */
|
||||
/* Read a grid catalog from a .csv file. */
|
||||
/************************************************************************/
|
||||
|
||||
PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name )
|
||||
{
|
||||
PAFile fid;
|
||||
PJ_GridCatalog *catalog;
|
||||
int entry_max;
|
||||
char line[302];
|
||||
|
||||
fid = pj_open_lib( ctx, catalog_name, "r" );
|
||||
if (fid == nullptr)
|
||||
return nullptr;
|
||||
|
||||
/* discard title line */
|
||||
pj_ctx_fgets(ctx, line, sizeof(line)-1, fid);
|
||||
|
||||
catalog = (PJ_GridCatalog *) calloc(1,sizeof(PJ_GridCatalog));
|
||||
if( !catalog )
|
||||
{
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
pj_ctx_fclose(ctx, fid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
catalog->catalog_name = pj_strdup(catalog_name);
|
||||
if (!catalog->catalog_name) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
free(catalog);
|
||||
pj_ctx_fclose(ctx, fid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
entry_max = 10;
|
||||
catalog->entries = (PJ_GridCatalogEntry *)
|
||||
malloc(entry_max * sizeof(PJ_GridCatalogEntry));
|
||||
if (!catalog->entries) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
free(catalog->catalog_name);
|
||||
free(catalog);
|
||||
pj_ctx_fclose(ctx, fid);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
while( gc_readentry( ctx, fid,
|
||||
catalog->entries+catalog->entry_count) == 0)
|
||||
{
|
||||
catalog->entry_count++;
|
||||
|
||||
if( catalog->entry_count == entry_max )
|
||||
{
|
||||
PJ_GridCatalogEntry* new_entries;
|
||||
entry_max = entry_max * 2;
|
||||
new_entries = (PJ_GridCatalogEntry *)
|
||||
realloc(catalog->entries,
|
||||
entry_max * sizeof(PJ_GridCatalogEntry));
|
||||
if (new_entries == nullptr )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < catalog->entry_count; i++ )
|
||||
free( catalog->entries[i].definition );
|
||||
free( catalog->entries );
|
||||
free( catalog->catalog_name );
|
||||
free( catalog );
|
||||
pj_ctx_fclose(ctx, fid);
|
||||
return nullptr;
|
||||
}
|
||||
catalog->entries = new_entries;
|
||||
}
|
||||
}
|
||||
|
||||
pj_ctx_fclose(ctx, fid);
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* gc_read_csv_line() */
|
||||
/* */
|
||||
/* Simple csv line splitter with fixed maximum line size and */
|
||||
/* token count. */
|
||||
/************************************************************************/
|
||||
|
||||
static int gc_read_csv_line( projCtx ctx, PAFile fid,
|
||||
char **tokens, int max_tokens )
|
||||
{
|
||||
char line[302];
|
||||
|
||||
while( pj_ctx_fgets(ctx, line, sizeof(line)-1, fid) != nullptr )
|
||||
{
|
||||
char *next = line;
|
||||
int token_count = 0;
|
||||
|
||||
while( isspace(*next) )
|
||||
next++;
|
||||
|
||||
/* skip blank and comment lines */
|
||||
if( next[0] == '#' || next[0] == '\0' )
|
||||
continue;
|
||||
|
||||
while( token_count < max_tokens && *next != '\0' )
|
||||
{
|
||||
const char *start = next;
|
||||
char* token;
|
||||
|
||||
while( *next != '\0' && *next != ',' )
|
||||
next++;
|
||||
|
||||
if( *next == ',' )
|
||||
{
|
||||
*next = '\0';
|
||||
next++;
|
||||
}
|
||||
|
||||
token = pj_strdup(start);
|
||||
if (!token) {
|
||||
while (token_count > 0)
|
||||
free(tokens[--token_count]);
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
tokens[token_count++] = token;
|
||||
}
|
||||
|
||||
return token_count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gc_parsedate() */
|
||||
/* */
|
||||
/* Parse a date into a floating point year value. Acceptable */
|
||||
/* values are "yyyy.fraction" and "yyyy-mm-dd". Anything else */
|
||||
/* returns 0.0. */
|
||||
/************************************************************************/
|
||||
|
||||
double pj_gc_parsedate( projCtx ctx, const char *date_string )
|
||||
{
|
||||
(void) ctx;
|
||||
|
||||
if( strlen(date_string) == 10
|
||||
&& date_string[4] == '-' && date_string[7] == '-' )
|
||||
{
|
||||
int year = atoi(date_string);
|
||||
int month = atoi(date_string+5);
|
||||
int day = atoi(date_string+8);
|
||||
|
||||
/* simplified calculation so we don't need to know all about months */
|
||||
return year + ((month-1) * 31 + (day-1)) / 372.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pj_atof(date_string);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* gc_readentry() */
|
||||
/* */
|
||||
/* Read one catalog entry from the file */
|
||||
/* */
|
||||
/* Format: */
|
||||
/* gridname,ll_long,ll_lat,ur_long,ur_lat,priority,date */
|
||||
/************************************************************************/
|
||||
|
||||
static int gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry)
|
||||
{
|
||||
#define MAX_TOKENS 30
|
||||
char *tokens[MAX_TOKENS];
|
||||
int token_count, i;
|
||||
int error = 0;
|
||||
|
||||
memset( entry, 0, sizeof(PJ_GridCatalogEntry) );
|
||||
|
||||
token_count = gc_read_csv_line( ctx, fid, tokens, MAX_TOKENS );
|
||||
if( token_count < 5 )
|
||||
{
|
||||
error = 1; /* TODO: need real error codes */
|
||||
if( token_count != 0 )
|
||||
pj_log( ctx, PJ_LOG_ERROR, "Short line in grid catalog." );
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->definition = tokens[0];
|
||||
tokens[0] = nullptr; /* We take ownership of tokens[0] */
|
||||
entry->region.ll_long = dmstor_ctx( ctx, tokens[1], nullptr );
|
||||
entry->region.ll_lat = dmstor_ctx( ctx, tokens[2], nullptr );
|
||||
entry->region.ur_long = dmstor_ctx( ctx, tokens[3], nullptr );
|
||||
entry->region.ur_lat = dmstor_ctx( ctx, tokens[4], nullptr );
|
||||
if( token_count > 5 )
|
||||
entry->priority = atoi( tokens[5] ); /* defaults to zero */
|
||||
if( token_count > 6 )
|
||||
entry->date = pj_gc_parsedate( ctx, tokens[6] );
|
||||
}
|
||||
|
||||
for( i = 0; i < token_count; i++ )
|
||||
free( tokens[i] );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Code in support of grid catalogs
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj_internal.h"
|
||||
|
||||
static PJ_GridCatalog *grid_catalog_list = nullptr;
|
||||
|
||||
static
|
||||
PJ_GRIDINFO *pj_gc_findgrid( projCtx_t *ctx,
|
||||
PJ_GridCatalog *catalog, int after,
|
||||
PJ_LP location, double date,
|
||||
PJ_Region *optional_region,
|
||||
double *grid_date );
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gc_unloadall() */
|
||||
/* */
|
||||
/* Deallocate all the grid catalogs (but not the referenced */
|
||||
/* grids). */
|
||||
/************************************************************************/
|
||||
|
||||
void pj_gc_unloadall( projCtx ctx )
|
||||
{
|
||||
(void) ctx;
|
||||
|
||||
while( grid_catalog_list != nullptr )
|
||||
{
|
||||
int i;
|
||||
PJ_GridCatalog *catalog = grid_catalog_list;
|
||||
grid_catalog_list = grid_catalog_list->next;
|
||||
|
||||
for( i = 0; i < catalog->entry_count; i++ )
|
||||
{
|
||||
/* we don't own gridinfo - do not free here */
|
||||
free( catalog->entries[i].definition );
|
||||
}
|
||||
free( catalog->entries );
|
||||
free( catalog->catalog_name );
|
||||
free( catalog );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gc_findcatalog() */
|
||||
/************************************************************************/
|
||||
|
||||
PJ_GridCatalog *pj_gc_findcatalog( projCtx ctx, const char *name )
|
||||
|
||||
{
|
||||
PJ_GridCatalog *catalog;
|
||||
|
||||
pj_acquire_lock();
|
||||
|
||||
for( catalog=grid_catalog_list; catalog != nullptr; catalog = catalog->next )
|
||||
{
|
||||
if( strcmp(catalog->catalog_name, name) == 0 )
|
||||
{
|
||||
pj_release_lock();
|
||||
return catalog;
|
||||
}
|
||||
}
|
||||
|
||||
pj_release_lock();
|
||||
|
||||
catalog = pj_gc_readcatalog( ctx, name );
|
||||
if( catalog == nullptr )
|
||||
return nullptr;
|
||||
|
||||
pj_acquire_lock();
|
||||
catalog->next = grid_catalog_list;
|
||||
grid_catalog_list = catalog;
|
||||
pj_release_lock();
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gc_apply_gridshift() */
|
||||
/************************************************************************/
|
||||
|
||||
int pj_gc_apply_gridshift( PJ *defn, int inverse,
|
||||
long point_count, int point_offset,
|
||||
double *x, double *y, double *z )
|
||||
|
||||
{
|
||||
int i;
|
||||
(void) z;
|
||||
|
||||
if( defn->catalog == nullptr )
|
||||
{
|
||||
defn->catalog = pj_gc_findcatalog( defn->ctx, defn->catalog_name );
|
||||
if( defn->catalog == nullptr )
|
||||
return defn->ctx->last_errno;
|
||||
}
|
||||
|
||||
defn->ctx->last_errno = 0;
|
||||
|
||||
for( i = 0; i < point_count; i++ )
|
||||
{
|
||||
long io = i * point_offset;
|
||||
PJ_LP input, output_after, output_before;
|
||||
double mix_ratio;
|
||||
PJ_GRIDINFO *gi;
|
||||
|
||||
input.phi = y[io];
|
||||
input.lam = x[io];
|
||||
|
||||
/* make sure we have appropriate "after" shift file available */
|
||||
if( defn->last_after_grid == nullptr
|
||||
|| input.lam < defn->last_after_region.ll_long
|
||||
|| input.lam > defn->last_after_region.ur_long
|
||||
|| input.phi < defn->last_after_region.ll_lat
|
||||
|| input.phi > defn->last_after_region.ll_lat ) {
|
||||
defn->last_after_grid =
|
||||
pj_gc_findgrid( defn->ctx, defn->catalog,
|
||||
1, input, defn->datum_date,
|
||||
&(defn->last_after_region),
|
||||
&(defn->last_after_date));
|
||||
if( defn->last_after_grid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
}
|
||||
gi = defn->last_after_grid;
|
||||
assert( gi->child == nullptr );
|
||||
|
||||
/* load the grid shift info if we don't have it. */
|
||||
if( gi->ct->cvs == nullptr && !pj_gridinfo_load( defn->ctx, gi ) )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
|
||||
output_after = nad_cvt( defn->ctx, input, inverse, gi->ct, 0, nullptr );
|
||||
if( output_after.lam == HUGE_VAL )
|
||||
{
|
||||
if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
|
||||
{
|
||||
pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"pj_apply_gridshift(): failed to find a grid shift table for\n"
|
||||
" location (%.7fdW,%.7fdN)",
|
||||
x[io] * RAD_TO_DEG,
|
||||
y[io] * RAD_TO_DEG );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( defn->datum_date == 0.0 )
|
||||
{
|
||||
y[io] = output_after.phi;
|
||||
x[io] = output_after.lam;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* make sure we have appropriate "before" shift file available */
|
||||
if( defn->last_before_grid == nullptr
|
||||
|| input.lam < defn->last_before_region.ll_long
|
||||
|| input.lam > defn->last_before_region.ur_long
|
||||
|| input.phi < defn->last_before_region.ll_lat
|
||||
|| input.phi > defn->last_before_region.ll_lat ) {
|
||||
defn->last_before_grid =
|
||||
pj_gc_findgrid( defn->ctx, defn->catalog,
|
||||
0, input, defn->datum_date,
|
||||
&(defn->last_before_region),
|
||||
&(defn->last_before_date));
|
||||
if( defn->last_before_grid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
}
|
||||
|
||||
gi = defn->last_before_grid;
|
||||
assert( gi->child == nullptr );
|
||||
|
||||
/* load the grid shift info if we don't have it. */
|
||||
if( gi->ct->cvs == nullptr && !pj_gridinfo_load( defn->ctx, gi ) )
|
||||
{
|
||||
pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return PJD_ERR_FAILED_TO_LOAD_GRID;
|
||||
}
|
||||
|
||||
output_before = nad_cvt( defn->ctx, input, inverse, gi->ct, 0, nullptr );
|
||||
if( output_before.lam == HUGE_VAL )
|
||||
{
|
||||
if( defn->ctx->debug_level >= PJ_LOG_DEBUG_MAJOR )
|
||||
{
|
||||
pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"pj_apply_gridshift(): failed to find a grid shift table for\n"
|
||||
" location (%.7fdW,%.7fdN)",
|
||||
x[io] * RAD_TO_DEG,
|
||||
y[io] * RAD_TO_DEG );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
mix_ratio = (defn->datum_date - defn->last_before_date)
|
||||
/ (defn->last_after_date - defn->last_before_date);
|
||||
|
||||
y[io] = mix_ratio * output_after.phi
|
||||
+ (1.0-mix_ratio) * output_before.phi;
|
||||
x[io] = mix_ratio * output_after.lam
|
||||
+ (1.0-mix_ratio) * output_before.lam;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_c_findgrid() */
|
||||
/************************************************************************/
|
||||
|
||||
static
|
||||
PJ_GRIDINFO *pj_gc_findgrid( projCtx ctx, PJ_GridCatalog *catalog, int after,
|
||||
PJ_LP location, double date,
|
||||
PJ_Region *optional_region,
|
||||
double *grid_date )
|
||||
{
|
||||
int iEntry;
|
||||
PJ_GridCatalogEntry *entry = nullptr;
|
||||
|
||||
for( iEntry = 0; iEntry < catalog->entry_count; iEntry++ )
|
||||
{
|
||||
entry = catalog->entries + iEntry;
|
||||
|
||||
if( (after && entry->date < date)
|
||||
|| (!after && entry->date > date) )
|
||||
continue;
|
||||
|
||||
if( location.lam < entry->region.ll_long
|
||||
|| location.lam > entry->region.ur_long
|
||||
|| location.phi < entry->region.ll_lat
|
||||
|| location.phi > entry->region.ur_lat )
|
||||
continue;
|
||||
|
||||
if( entry->available == -1 )
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if( entry == nullptr )
|
||||
{
|
||||
if( grid_date )
|
||||
*grid_date = 0.0;
|
||||
if( optional_region != nullptr )
|
||||
memset( optional_region, 0, sizeof(PJ_Region));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if( grid_date )
|
||||
*grid_date = entry->date;
|
||||
|
||||
if( optional_region )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if( entry->gridinfo == nullptr )
|
||||
{
|
||||
PJ_GRIDINFO **gridlist = nullptr;
|
||||
int grid_count = 0;
|
||||
gridlist = pj_gridlist_from_nadgrids( ctx, entry->definition,
|
||||
&grid_count);
|
||||
// FIXME: this leaks gridlist itself, and memory ownership of
|
||||
// entry->gridinfo is also confusing. Coverity CID 193539
|
||||
if( grid_count == 1 )
|
||||
entry->gridinfo = gridlist[0];
|
||||
}
|
||||
|
||||
return entry->gridinfo;
|
||||
}
|
||||
|
||||
@@ -1,988 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Functions for handling individual PJ_GRIDINFO's. Includes
|
||||
* loaders for all formats but CTABLE (in nad_init.c).
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "proj_internal.h"
|
||||
|
||||
/************************************************************************/
|
||||
/* swap_words() */
|
||||
/* */
|
||||
/* Convert the byte order of the given word(s) in place. */
|
||||
/************************************************************************/
|
||||
|
||||
static const int byte_order_test = 1;
|
||||
#define IS_LSB (1 == ((const unsigned char *) (&byte_order_test))[0])
|
||||
|
||||
static void swap_words( unsigned char *data, int word_size, int word_count )
|
||||
|
||||
{
|
||||
int word;
|
||||
|
||||
for( word = 0; word < word_count; word++ )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < word_size/2; i++ )
|
||||
{
|
||||
unsigned char t;
|
||||
|
||||
t = data[i];
|
||||
data[i] = data[word_size-i-1];
|
||||
data[word_size-i-1] = t;
|
||||
}
|
||||
|
||||
data += word_size;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* to_double() */
|
||||
/* */
|
||||
/* Returns a double from the pointed data. */
|
||||
/************************************************************************/
|
||||
|
||||
static double to_double( unsigned char* data )
|
||||
{
|
||||
double d;
|
||||
memcpy(&d, data, sizeof(d));
|
||||
return d;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_free() */
|
||||
/************************************************************************/
|
||||
|
||||
void pj_gridinfo_free( projCtx ctx, PJ_GRIDINFO *gi )
|
||||
|
||||
{
|
||||
if( gi == nullptr )
|
||||
return;
|
||||
|
||||
if( gi->child != nullptr )
|
||||
{
|
||||
PJ_GRIDINFO *child, *next;
|
||||
|
||||
for( child = gi->child; child != nullptr; child=next)
|
||||
{
|
||||
next=child->next;
|
||||
pj_gridinfo_free( ctx, child );
|
||||
}
|
||||
}
|
||||
|
||||
if( gi->ct != nullptr )
|
||||
nad_free( gi->ct );
|
||||
|
||||
free( gi->gridname );
|
||||
if( gi->filename != nullptr )
|
||||
free( gi->filename );
|
||||
|
||||
pj_dalloc( gi );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_load() */
|
||||
/* */
|
||||
/* This function is intended to implement delayed loading of */
|
||||
/* the data contents of a grid file. The header and related */
|
||||
/* stuff are loaded by pj_gridinfo_init(). */
|
||||
/************************************************************************/
|
||||
|
||||
int pj_gridinfo_load( projCtx_t* ctx, PJ_GRIDINFO *gi )
|
||||
|
||||
{
|
||||
struct CTABLE ct_tmp;
|
||||
|
||||
if( gi == nullptr || gi->ct == nullptr )
|
||||
return 0;
|
||||
|
||||
pj_acquire_lock();
|
||||
if( gi->ct->cvs != nullptr )
|
||||
{
|
||||
pj_release_lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(&ct_tmp, gi->ct, sizeof(struct CTABLE));
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Original platform specific CTable format. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( strcmp(gi->format,"ctable") == 0 )
|
||||
{
|
||||
PAFile fid;
|
||||
int result;
|
||||
|
||||
fid = pj_open_lib( ctx, gi->filename, "rb" );
|
||||
|
||||
if( fid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = nad_ctable_load( ctx, &ct_tmp, (struct projFileAPI_t*)fid );
|
||||
|
||||
pj_ctx_fclose( ctx, fid );
|
||||
|
||||
gi->ct->cvs = ct_tmp.cvs;
|
||||
pj_release_lock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* CTable2 format. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
else if( strcmp(gi->format,"ctable2") == 0 )
|
||||
{
|
||||
PAFile fid;
|
||||
int result;
|
||||
|
||||
fid = pj_open_lib( ctx, gi->filename, "rb" );
|
||||
|
||||
if( fid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = nad_ctable2_load( ctx, &ct_tmp, (struct projFileAPI_t*)fid );
|
||||
|
||||
pj_ctx_fclose( ctx, fid );
|
||||
|
||||
gi->ct->cvs = ct_tmp.cvs;
|
||||
|
||||
pj_release_lock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* NTv1 format. */
|
||||
/* We process one line at a time. Note that the array storage */
|
||||
/* direction (e-w) is different in the NTv1 file and what */
|
||||
/* the CTABLE is supposed to have. The phi/lam are also */
|
||||
/* reversed, and we have to be aware of byte swapping. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
else if( strcmp(gi->format,"ntv1") == 0 )
|
||||
{
|
||||
double *row_buf;
|
||||
int row;
|
||||
PAFile fid;
|
||||
|
||||
fid = pj_open_lib( ctx, gi->filename, "rb" );
|
||||
|
||||
if( fid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
pj_ctx_fseek( ctx, fid, gi->grid_offset, SEEK_SET );
|
||||
|
||||
row_buf = (double *) pj_malloc(gi->ct->lim.lam * sizeof(double) * 2);
|
||||
ct_tmp.cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
|
||||
if( row_buf == nullptr || ct_tmp.cvs == nullptr )
|
||||
{
|
||||
pj_dalloc( row_buf );
|
||||
pj_dalloc( ct_tmp.cvs );
|
||||
pj_ctx_set_errno( ctx, ENOMEM );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( row = 0; row < gi->ct->lim.phi; row++ )
|
||||
{
|
||||
int i;
|
||||
FLP *cvs;
|
||||
double *diff_seconds;
|
||||
|
||||
if( pj_ctx_fread( ctx, row_buf,
|
||||
sizeof(double), gi->ct->lim.lam * 2, fid )
|
||||
!= (size_t)( 2 * gi->ct->lim.lam ) )
|
||||
{
|
||||
pj_dalloc( row_buf );
|
||||
pj_dalloc( ct_tmp.cvs );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( IS_LSB )
|
||||
swap_words( (unsigned char *) row_buf, 8, gi->ct->lim.lam*2 );
|
||||
|
||||
/* convert seconds to radians */
|
||||
diff_seconds = row_buf;
|
||||
|
||||
for( i = 0; i < gi->ct->lim.lam; i++ )
|
||||
{
|
||||
cvs = ct_tmp.cvs + (row) * gi->ct->lim.lam
|
||||
+ (gi->ct->lim.lam - i - 1);
|
||||
|
||||
cvs->phi = (float) (*(diff_seconds++) * ((M_PI/180.0) / 3600.0));
|
||||
cvs->lam = (float) (*(diff_seconds++) * ((M_PI/180.0) / 3600.0));
|
||||
}
|
||||
}
|
||||
|
||||
pj_dalloc( row_buf );
|
||||
|
||||
pj_ctx_fclose( ctx, fid );
|
||||
|
||||
gi->ct->cvs = ct_tmp.cvs;
|
||||
pj_release_lock();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* NTv2 format. */
|
||||
/* We process one line at a time. Note that the array storage */
|
||||
/* direction (e-w) is different in the NTv2 file and what */
|
||||
/* the CTABLE is supposed to have. The phi/lam are also */
|
||||
/* reversed, and we have to be aware of byte swapping. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
else if( strcmp(gi->format,"ntv2") == 0 )
|
||||
{
|
||||
float *row_buf;
|
||||
int row;
|
||||
PAFile fid;
|
||||
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MINOR,
|
||||
"NTv2 - loading grid %s", gi->ct->id );
|
||||
|
||||
fid = pj_open_lib( ctx, gi->filename, "rb" );
|
||||
|
||||
if( fid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
pj_ctx_fseek( ctx, fid, gi->grid_offset, SEEK_SET );
|
||||
|
||||
row_buf = (float *) pj_malloc(gi->ct->lim.lam * sizeof(float) * 4);
|
||||
ct_tmp.cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
|
||||
if( row_buf == nullptr || ct_tmp.cvs == nullptr )
|
||||
{
|
||||
pj_dalloc( row_buf );
|
||||
pj_dalloc( ct_tmp.cvs );
|
||||
pj_ctx_set_errno( ctx, ENOMEM );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for( row = 0; row < gi->ct->lim.phi; row++ )
|
||||
{
|
||||
int i;
|
||||
FLP *cvs;
|
||||
float *diff_seconds;
|
||||
|
||||
if( pj_ctx_fread( ctx, row_buf, sizeof(float),
|
||||
gi->ct->lim.lam*4, fid )
|
||||
!= (size_t)( 4 * gi->ct->lim.lam ) )
|
||||
{
|
||||
pj_dalloc( row_buf );
|
||||
pj_dalloc( ct_tmp.cvs );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( gi->must_swap )
|
||||
swap_words( (unsigned char *) row_buf, 4,
|
||||
gi->ct->lim.lam*4 );
|
||||
|
||||
/* convert seconds to radians */
|
||||
diff_seconds = row_buf;
|
||||
|
||||
for( i = 0; i < gi->ct->lim.lam; i++ )
|
||||
{
|
||||
cvs = ct_tmp.cvs + (row) * gi->ct->lim.lam
|
||||
+ (gi->ct->lim.lam - i - 1);
|
||||
|
||||
cvs->phi = (float) (*(diff_seconds++) * ((M_PI/180.0) / 3600.0));
|
||||
cvs->lam = (float) (*(diff_seconds++) * ((M_PI/180.0) / 3600.0));
|
||||
diff_seconds += 2; /* skip accuracy values */
|
||||
}
|
||||
}
|
||||
|
||||
pj_dalloc( row_buf );
|
||||
|
||||
pj_ctx_fclose( ctx, fid );
|
||||
|
||||
gi->ct->cvs = ct_tmp.cvs;
|
||||
|
||||
pj_release_lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* GTX format. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
else if( strcmp(gi->format,"gtx") == 0 )
|
||||
{
|
||||
int words = gi->ct->lim.lam * gi->ct->lim.phi;
|
||||
PAFile fid;
|
||||
|
||||
fid = pj_open_lib( ctx, gi->filename, "rb" );
|
||||
|
||||
if( fid == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
pj_ctx_fseek( ctx, fid, gi->grid_offset, SEEK_SET );
|
||||
|
||||
ct_tmp.cvs = (FLP *) pj_malloc(words*sizeof(float));
|
||||
if( ct_tmp.cvs == nullptr )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, ENOMEM );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( pj_ctx_fread( ctx, ct_tmp.cvs, sizeof(float), words, fid )
|
||||
!= (size_t)words )
|
||||
{
|
||||
pj_dalloc( ct_tmp.cvs );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( IS_LSB )
|
||||
swap_words( (unsigned char *) ct_tmp.cvs, 4, words );
|
||||
|
||||
pj_ctx_fclose( ctx, fid );
|
||||
gi->ct->cvs = ct_tmp.cvs;
|
||||
pj_release_lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
pj_release_lock();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* gridinfo_parent() */
|
||||
/* */
|
||||
/* Seek a parent grid file by name from a grid list */
|
||||
/************************************************************************/
|
||||
|
||||
static PJ_GRIDINFO* gridinfo_parent( PJ_GRIDINFO *gilist,
|
||||
const char *name, int length )
|
||||
{
|
||||
while( gilist )
|
||||
{
|
||||
if( strncmp(gilist->ct->id,name,length) == 0 ) return gilist;
|
||||
if( gilist->child )
|
||||
{
|
||||
PJ_GRIDINFO *parent=gridinfo_parent( gilist->child, name, length );
|
||||
if( parent ) return parent;
|
||||
}
|
||||
gilist=gilist->next;
|
||||
}
|
||||
return gilist;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_init_ntv2() */
|
||||
/* */
|
||||
/* Load a ntv2 (.gsb) file. */
|
||||
/************************************************************************/
|
||||
|
||||
static int pj_gridinfo_init_ntv2( projCtx ctx, PAFile fid, PJ_GRIDINFO *gilist )
|
||||
{
|
||||
unsigned char header[11*16];
|
||||
int num_subfiles, subfile;
|
||||
int must_swap;
|
||||
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(pj_int32) == 4 );
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(double) == 8 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the overview header. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pj_ctx_fread( ctx, header, sizeof(header), 1, fid ) != 1 )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( header[8] == 11 )
|
||||
must_swap = !IS_LSB;
|
||||
else
|
||||
must_swap = IS_LSB;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Byte swap interesting fields if needed. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( must_swap )
|
||||
{
|
||||
swap_words( header+8, 4, 1 );
|
||||
swap_words( header+8+16, 4, 1 );
|
||||
swap_words( header+8+32, 4, 1 );
|
||||
swap_words( header+8+7*16, 8, 1 );
|
||||
swap_words( header+8+8*16, 8, 1 );
|
||||
swap_words( header+8+9*16, 8, 1 );
|
||||
swap_words( header+8+10*16, 8, 1 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Get the subfile count out ... all we really use for now. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
memcpy( &num_subfiles, header+8+32, 4 );
|
||||
|
||||
/* ==================================================================== */
|
||||
/* Step through the subfiles, creating a PJ_GRIDINFO for each. */
|
||||
/* ==================================================================== */
|
||||
for( subfile = 0; subfile < num_subfiles; subfile++ )
|
||||
{
|
||||
struct CTABLE *ct;
|
||||
PJ_LP ur;
|
||||
int gs_count;
|
||||
PJ_GRIDINFO *gi;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read header. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pj_ctx_fread( ctx, header, sizeof(header), 1, fid ) != 1 )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( strncmp((const char *) header,"SUB_NAME",8) != 0 )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Byte swap interesting fields if needed. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( must_swap )
|
||||
{
|
||||
swap_words( header+8+16*4, 8, 1 );
|
||||
swap_words( header+8+16*5, 8, 1 );
|
||||
swap_words( header+8+16*6, 8, 1 );
|
||||
swap_words( header+8+16*7, 8, 1 );
|
||||
swap_words( header+8+16*8, 8, 1 );
|
||||
swap_words( header+8+16*9, 8, 1 );
|
||||
swap_words( header+8+16*10, 4, 1 );
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize a corresponding "ct" structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
|
||||
if (!ct) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
strncpy( ct->id, (const char *) header + 8, 8 );
|
||||
ct->id[8] = '\0';
|
||||
|
||||
ct->ll.lam = - to_double(header+7*16+8); /* W_LONG */
|
||||
ct->ll.phi = to_double(header+4*16+8); /* S_LAT */
|
||||
|
||||
ur.lam = - to_double(header+6*16+8); /* E_LONG */
|
||||
ur.phi = to_double(header+5*16+8); /* N_LAT */
|
||||
|
||||
ct->del.lam = to_double(header+9*16+8);
|
||||
ct->del.phi = to_double(header+8*16+8);
|
||||
|
||||
ct->lim.lam = (pj_int32) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
|
||||
ct->lim.phi = (pj_int32) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
|
||||
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MINOR,
|
||||
"NTv2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
|
||||
ct->id,
|
||||
ct->lim.lam, ct->lim.phi,
|
||||
ct->ll.lam/3600.0, ct->ll.phi/3600.0,
|
||||
ur.lam/3600.0, ur.phi/3600.0 );
|
||||
|
||||
ct->ll.lam *= DEG_TO_RAD/3600.0;
|
||||
ct->ll.phi *= DEG_TO_RAD/3600.0;
|
||||
ct->del.lam *= DEG_TO_RAD/3600.0;
|
||||
ct->del.phi *= DEG_TO_RAD/3600.0;
|
||||
|
||||
memcpy( &gs_count, header + 8 + 16*10, 4 );
|
||||
if( gs_count != ct->lim.lam * ct->lim.phi )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_ERROR,
|
||||
"GS_COUNT(%d) does not match expected cells (%dx%d=%d)",
|
||||
gs_count, ct->lim.lam, ct->lim.phi,
|
||||
ct->lim.lam * ct->lim.phi );
|
||||
pj_dalloc(ct);
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ct->cvs = nullptr;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Create a new gridinfo for this if we aren't processing the */
|
||||
/* 1st subfile, and initialize our grid info. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( subfile == 0 )
|
||||
gi = gilist;
|
||||
else
|
||||
{
|
||||
gi = (PJ_GRIDINFO *) pj_calloc(1, sizeof(PJ_GRIDINFO));
|
||||
if (!gi) {
|
||||
pj_dalloc(ct);
|
||||
pj_gridinfo_free(ctx, gilist);
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gi->gridname = pj_strdup( gilist->gridname );
|
||||
gi->filename = pj_strdup( gilist->filename );
|
||||
if (!gi->gridname || !gi->filename) {
|
||||
pj_gridinfo_free(ctx, gi);
|
||||
pj_dalloc(ct);
|
||||
pj_gridinfo_free(ctx, gilist);
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
gi->next = nullptr;
|
||||
}
|
||||
|
||||
gi->must_swap = must_swap;
|
||||
gi->ct = ct;
|
||||
gi->format = "ntv2";
|
||||
gi->grid_offset = pj_ctx_ftell( ctx, fid );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Attach to the correct list or sublist. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( strncmp((const char *)header+24,"NONE",4) == 0 )
|
||||
{
|
||||
if( gi != gilist )
|
||||
{
|
||||
PJ_GRIDINFO *lnk;
|
||||
|
||||
for( lnk = gilist; lnk->next != nullptr; lnk = lnk->next ) {}
|
||||
lnk->next = gi;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PJ_GRIDINFO *lnk;
|
||||
PJ_GRIDINFO *gp = gridinfo_parent(gilist,
|
||||
(const char*)header+24,8);
|
||||
|
||||
if( gp == nullptr )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_ERROR,
|
||||
"pj_gridinfo_init_ntv2(): "
|
||||
"failed to find parent %8.8s for %s.",
|
||||
(const char *) header+24, gi->ct->id );
|
||||
|
||||
for( lnk = gilist; lnk->next != nullptr; lnk = lnk->next ) {}
|
||||
lnk->next = gi;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( gp->child == nullptr )
|
||||
{
|
||||
gp->child = gi;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( lnk = gp->child; lnk->next != nullptr; lnk = lnk->next ) {}
|
||||
lnk->next = gi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Seek past the data. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
pj_ctx_fseek( ctx, fid, gs_count * 16, SEEK_CUR );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_init_ntv1() */
|
||||
/* */
|
||||
/* Load an NTv1 style Canadian grid shift file. */
|
||||
/************************************************************************/
|
||||
|
||||
static int pj_gridinfo_init_ntv1( projCtx ctx, PAFile fid, PJ_GRIDINFO *gi )
|
||||
|
||||
{
|
||||
unsigned char header[192]; /* 12 records of 16 bytes */
|
||||
struct CTABLE *ct;
|
||||
PJ_LP ur;
|
||||
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(pj_int32) == 4 );
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(double) == 8 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the header. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pj_ctx_fread( ctx, header, sizeof(header), 1, fid ) != 1 )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Regularize fields of interest. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( IS_LSB )
|
||||
{
|
||||
swap_words( header+8, 4, 1 );
|
||||
swap_words( header+24, 8, 1 );
|
||||
swap_words( header+40, 8, 1 );
|
||||
swap_words( header+56, 8, 1 );
|
||||
swap_words( header+72, 8, 1 );
|
||||
swap_words( header+88, 8, 1 );
|
||||
swap_words( header+104, 8, 1 );
|
||||
}
|
||||
|
||||
if( *((int *) (header+8)) != 12 )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_ERROR,
|
||||
"NTv1 grid shift file has wrong record count, corrupt?" );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Fill in CTABLE structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
|
||||
if (!ct) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
strcpy( ct->id, "NTv1 Grid Shift File" );
|
||||
|
||||
ct->ll.lam = - to_double(header+72);
|
||||
ct->ll.phi = to_double(header+24);
|
||||
ur.lam = - to_double(header+56);
|
||||
ur.phi = to_double(header+40);
|
||||
ct->del.lam = to_double(header+104);
|
||||
ct->del.phi = to_double(header+88);
|
||||
ct->lim.lam = (pj_int32) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
|
||||
ct->lim.phi = (pj_int32) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
|
||||
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MINOR,
|
||||
"NTv1 %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
|
||||
ct->lim.lam, ct->lim.phi,
|
||||
ct->ll.lam, ct->ll.phi, ur.lam, ur.phi );
|
||||
|
||||
ct->ll.lam *= DEG_TO_RAD;
|
||||
ct->ll.phi *= DEG_TO_RAD;
|
||||
ct->del.lam *= DEG_TO_RAD;
|
||||
ct->del.phi *= DEG_TO_RAD;
|
||||
ct->cvs = nullptr;
|
||||
|
||||
gi->ct = ct;
|
||||
gi->grid_offset = (long) sizeof(header);
|
||||
gi->format = "ntv1";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_init_gtx() */
|
||||
/* */
|
||||
/* Load a NOAA .gtx vertical datum shift file. */
|
||||
/************************************************************************/
|
||||
|
||||
static int pj_gridinfo_init_gtx( projCtx ctx, PAFile fid, PJ_GRIDINFO *gi )
|
||||
|
||||
{
|
||||
unsigned char header[40];
|
||||
struct CTABLE *ct;
|
||||
double xorigin,yorigin,xstep,ystep;
|
||||
int rows, columns;
|
||||
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(pj_int32) == 4 );
|
||||
/* cppcheck-suppress sizeofCalculation */
|
||||
STATIC_ASSERT( sizeof(double) == 8 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Read the header. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( pj_ctx_fread( ctx, header, sizeof(header), 1, fid ) != 1 )
|
||||
{
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Regularize fields of interest and extract. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( IS_LSB )
|
||||
{
|
||||
swap_words( header+0, 8, 4 );
|
||||
swap_words( header+32, 4, 2 );
|
||||
}
|
||||
|
||||
memcpy( &yorigin, header+0, 8 );
|
||||
memcpy( &xorigin, header+8, 8 );
|
||||
memcpy( &ystep, header+16, 8 );
|
||||
memcpy( &xstep, header+24, 8 );
|
||||
|
||||
memcpy( &rows, header+32, 4 );
|
||||
memcpy( &columns, header+36, 4 );
|
||||
|
||||
if( xorigin < -360 || xorigin > 360
|
||||
|| yorigin < -90 || yorigin > 90 )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_ERROR,
|
||||
"gtx file header has invalid extents, corrupt?");
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Fill in CTABLE structure. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
|
||||
if (!ct) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
strcpy( ct->id, "GTX Vertical Grid Shift File" );
|
||||
|
||||
ct->ll.lam = xorigin;
|
||||
ct->ll.phi = yorigin;
|
||||
ct->del.lam = xstep;
|
||||
ct->del.phi = ystep;
|
||||
ct->lim.lam = columns;
|
||||
ct->lim.phi = rows;
|
||||
|
||||
/* some GTX files come in 0-360 and we shift them back into the
|
||||
expected -180 to 180 range if possible. This does not solve
|
||||
problems with grids spanning the dateline. */
|
||||
if( ct->ll.lam >= 180.0 )
|
||||
ct->ll.lam -= 360.0;
|
||||
|
||||
if( ct->ll.lam >= 0.0 && ct->ll.lam + ct->del.lam * ct->lim.lam > 180.0 )
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"This GTX spans the dateline! This will cause problems." );
|
||||
}
|
||||
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MINOR,
|
||||
"GTX %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
|
||||
ct->lim.lam, ct->lim.phi,
|
||||
ct->ll.lam, ct->ll.phi,
|
||||
ct->ll.lam + (columns-1)*xstep, ct->ll.phi + (rows-1)*ystep);
|
||||
|
||||
ct->ll.lam *= DEG_TO_RAD;
|
||||
ct->ll.phi *= DEG_TO_RAD;
|
||||
ct->del.lam *= DEG_TO_RAD;
|
||||
ct->del.phi *= DEG_TO_RAD;
|
||||
ct->cvs = nullptr;
|
||||
|
||||
gi->ct = ct;
|
||||
gi->grid_offset = 40;
|
||||
gi->format = "gtx";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridinfo_init() */
|
||||
/* */
|
||||
/* Open and parse header details from a datum gridshift file */
|
||||
/* returning a list of PJ_GRIDINFOs for the grids in that */
|
||||
/* file. This superceeds use of nad_init() for modern */
|
||||
/* applications. */
|
||||
/************************************************************************/
|
||||
|
||||
PJ_GRIDINFO *pj_gridinfo_init( projCtx ctx, const char *gridname )
|
||||
|
||||
{
|
||||
PJ_GRIDINFO *gilist;
|
||||
PAFile fp;
|
||||
char header[160];
|
||||
size_t header_size = 0;
|
||||
|
||||
errno = pj_errno = 0;
|
||||
ctx->last_errno = 0;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Initialize a GRIDINFO with stub info we would use if it */
|
||||
/* cannot be loaded. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
gilist = (PJ_GRIDINFO *) pj_calloc(1, sizeof(PJ_GRIDINFO));
|
||||
if (!gilist) {
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gilist->gridname = pj_strdup( gridname );
|
||||
if (!gilist->gridname) {
|
||||
pj_dalloc(gilist);
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return nullptr;
|
||||
}
|
||||
gilist->filename = nullptr;
|
||||
gilist->format = "missing";
|
||||
gilist->grid_offset = 0;
|
||||
gilist->ct = nullptr;
|
||||
gilist->next = nullptr;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Open the file using the usual search rules. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if (!(fp = pj_open_lib(ctx, gridname, "rb"))) {
|
||||
ctx->last_errno = 0; /* don't treat as a persistent error */
|
||||
return gilist;
|
||||
}
|
||||
|
||||
gilist->filename = pj_strdup(gridname);
|
||||
if (!gilist->filename) {
|
||||
pj_dalloc(gilist->gridname);
|
||||
pj_dalloc(gilist);
|
||||
pj_ctx_set_errno(ctx, ENOMEM);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Load a header, to determine the file type. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( (header_size = pj_ctx_fread( ctx, header, 1,
|
||||
sizeof(header), fp ) ) != sizeof(header) )
|
||||
{
|
||||
/* some files may be smaller that sizeof(header), eg 160, so */
|
||||
ctx->last_errno = 0; /* don't treat as a persistent error */
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"pj_gridinfo_init: short header read of %d bytes",
|
||||
(int)header_size );
|
||||
}
|
||||
|
||||
pj_ctx_fseek( ctx, fp, SEEK_SET, 0 );
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Determine file type. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
if( header_size >= 144 + 16
|
||||
&& strncmp(header + 0, "HEADER", 6) == 0
|
||||
&& strncmp(header + 96, "W GRID", 6) == 0
|
||||
&& strncmp(header + 144, "TO NAD83 ", 16) == 0 )
|
||||
{
|
||||
pj_gridinfo_init_ntv1( ctx, fp, gilist );
|
||||
}
|
||||
|
||||
else if( header_size >= 48 + 7
|
||||
&& strncmp(header + 0, "NUM_OREC", 8) == 0
|
||||
&& strncmp(header + 48, "GS_TYPE", 7) == 0 )
|
||||
{
|
||||
pj_gridinfo_init_ntv2( ctx, fp, gilist );
|
||||
}
|
||||
|
||||
else if( strlen(gridname) > 4
|
||||
&& (strcmp(gridname+strlen(gridname)-3,"gtx") == 0
|
||||
|| strcmp(gridname+strlen(gridname)-3,"GTX") == 0) )
|
||||
{
|
||||
pj_gridinfo_init_gtx( ctx, fp, gilist );
|
||||
}
|
||||
|
||||
else if( header_size >= 9 && strncmp(header + 0,"CTABLE V2",9) == 0 )
|
||||
{
|
||||
struct CTABLE *ct = nad_ctable2_init( ctx, (struct projFileAPI_t*)fp );
|
||||
|
||||
gilist->format = "ctable2";
|
||||
gilist->ct = ct;
|
||||
|
||||
if (ct == nullptr)
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"CTABLE V2 ct is NULL.");
|
||||
}
|
||||
else
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"Ctable2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
|
||||
ct->id,
|
||||
ct->lim.lam, ct->lim.phi,
|
||||
ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
|
||||
(ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG,
|
||||
(ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
struct CTABLE *ct = nad_ctable_init( ctx, (struct projFileAPI_t*)fp );
|
||||
if (ct == nullptr)
|
||||
{
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"CTABLE ct is NULL.");
|
||||
} else
|
||||
{
|
||||
gilist->format = "ctable";
|
||||
gilist->ct = ct;
|
||||
|
||||
pj_log( ctx, PJ_LOG_DEBUG_MAJOR,
|
||||
"Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
|
||||
ct->id,
|
||||
ct->lim.lam, ct->lim.phi,
|
||||
ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
|
||||
(ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG,
|
||||
(ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
|
||||
}
|
||||
}
|
||||
|
||||
pj_ctx_fclose(ctx, fp);
|
||||
|
||||
return gilist;
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Project: PROJ.4
|
||||
* Purpose: Code to manage the list of currently loaded (cached) PJ_GRIDINFOs
|
||||
* See pj_gridinfo.c for details of loading individual grids.
|
||||
* Author: Frank Warmerdam, warmerdam@pobox.com
|
||||
*
|
||||
******************************************************************************
|
||||
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#define PJ_LIB__
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "proj.h"
|
||||
#include "proj_internal.h"
|
||||
|
||||
static PJ_GRIDINFO *grid_list = nullptr;
|
||||
#define PJ_MAX_PATH_LENGTH 1024
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_deallocate_grids() */
|
||||
/* */
|
||||
/* Deallocate all loaded grids. */
|
||||
/************************************************************************/
|
||||
|
||||
void pj_deallocate_grids()
|
||||
|
||||
{
|
||||
while( grid_list != nullptr )
|
||||
{
|
||||
PJ_GRIDINFO *item = grid_list;
|
||||
grid_list = grid_list->next;
|
||||
item->next = nullptr;
|
||||
|
||||
pj_gridinfo_free( pj_get_default_ctx(), item );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridlist_merge_grid() */
|
||||
/* */
|
||||
/* Find/load the named gridfile and merge it into the */
|
||||
/* last_nadgrids_list. */
|
||||
/************************************************************************/
|
||||
|
||||
static int pj_gridlist_merge_gridfile( projCtx ctx,
|
||||
const char *gridname,
|
||||
PJ_GRIDINFO ***p_gridlist,
|
||||
int *p_gridcount,
|
||||
int *p_gridmax )
|
||||
|
||||
{
|
||||
int got_match=0;
|
||||
PJ_GRIDINFO *this_grid, *tail = nullptr;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to find in the existing list of loaded grids. Add all */
|
||||
/* matching grids as with NTv2 we can get many grids from one */
|
||||
/* file (one shared gridname). */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( this_grid = grid_list; this_grid != nullptr; this_grid = this_grid->next)
|
||||
{
|
||||
if( strcmp(this_grid->gridname,gridname) == 0 )
|
||||
{
|
||||
got_match = 1;
|
||||
|
||||
/* don't add to the list if it is invalid. */
|
||||
if( this_grid->ct == nullptr )
|
||||
return 0;
|
||||
|
||||
/* do we need to grow the list? */
|
||||
if( *p_gridcount >= *p_gridmax - 2 )
|
||||
{
|
||||
PJ_GRIDINFO **new_list;
|
||||
int new_max = *p_gridmax + 20;
|
||||
|
||||
new_list = (PJ_GRIDINFO **) pj_calloc(new_max, sizeof(void *));
|
||||
if (!new_list) {
|
||||
pj_ctx_set_errno( ctx, ENOMEM );
|
||||
return 0;
|
||||
}
|
||||
if( *p_gridlist != nullptr )
|
||||
{
|
||||
memcpy( new_list, *p_gridlist,
|
||||
sizeof(void *) * (*p_gridmax) );
|
||||
pj_dalloc( *p_gridlist );
|
||||
}
|
||||
|
||||
*p_gridlist = new_list;
|
||||
*p_gridmax = new_max;
|
||||
}
|
||||
|
||||
/* add to the list */
|
||||
(*p_gridlist)[(*p_gridcount)++] = this_grid;
|
||||
(*p_gridlist)[*p_gridcount] = nullptr;
|
||||
}
|
||||
|
||||
tail = this_grid;
|
||||
}
|
||||
|
||||
if( got_match )
|
||||
return 1;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Try to load the named grid. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
this_grid = pj_gridinfo_init( ctx, gridname );
|
||||
|
||||
if( this_grid == nullptr )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( tail != nullptr )
|
||||
tail->next = this_grid;
|
||||
else
|
||||
grid_list = this_grid;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Recurse to add the grid now that it is loaded. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
return pj_gridlist_merge_gridfile( ctx, gridname, p_gridlist,
|
||||
p_gridcount, p_gridmax );
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* pj_gridlist_from_nadgrids() */
|
||||
/* */
|
||||
/* This functions loads the list of grids corresponding to a */
|
||||
/* particular nadgrids string into a list, and returns it. The */
|
||||
/* list is kept around till a request is made with a different */
|
||||
/* string in order to cut down on the string parsing cost, and */
|
||||
/* the cost of building the list of tables each time. */
|
||||
/************************************************************************/
|
||||
|
||||
PJ_GRIDINFO **pj_gridlist_from_nadgrids( projCtx ctx, const char *nadgrids,
|
||||
int *grid_count)
|
||||
|
||||
{
|
||||
const char *s;
|
||||
PJ_GRIDINFO **gridlist = nullptr;
|
||||
int grid_max = 0;
|
||||
|
||||
pj_errno = 0;
|
||||
*grid_count = 0;
|
||||
|
||||
pj_acquire_lock();
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/* Loop processing names out of nadgrids one at a time. */
|
||||
/* -------------------------------------------------------------------- */
|
||||
for( s = nadgrids; *s != '\0'; )
|
||||
{
|
||||
size_t end_char;
|
||||
int required = 1;
|
||||
char name[PJ_MAX_PATH_LENGTH];
|
||||
|
||||
if( *s == '@' )
|
||||
{
|
||||
required = 0;
|
||||
s++;
|
||||
}
|
||||
|
||||
for( end_char = 0;
|
||||
s[end_char] != '\0' && s[end_char] != ',';
|
||||
end_char++ ) {}
|
||||
|
||||
if( end_char >= sizeof(name) )
|
||||
{
|
||||
pj_dalloc( gridlist );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
strncpy( name, s, end_char );
|
||||
name[end_char] = '\0';
|
||||
|
||||
s += end_char;
|
||||
if( *s == ',' )
|
||||
s++;
|
||||
|
||||
if( !pj_gridlist_merge_gridfile( ctx, name, &gridlist, grid_count,
|
||||
&grid_max)
|
||||
&& required )
|
||||
{
|
||||
pj_dalloc( gridlist );
|
||||
pj_ctx_set_errno( ctx, PJD_ERR_FAILED_TO_LOAD_GRID );
|
||||
pj_release_lock();
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
pj_errno = 0;
|
||||
}
|
||||
|
||||
pj_release_lock();
|
||||
|
||||
return gridlist;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user