aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--cmake/CMakeLists.txt5
-rw-r--r--cmake/project-config.cmake.in1
-rw-r--r--configure.ac7
-rw-r--r--data/Makefile.am1
-rw-r--r--data/tests/us_noaa_geoid06_ak_subset_at_antimeridian.tifbin0 -> 6617 bytes
-rw-r--r--docs/images/foss4g2020.pngbin0 -> 14375 bytes
-rw-r--r--docs/source/apps/projinfo.rst18
-rw-r--r--docs/source/community/index.rst14
-rw-r--r--docs/source/community/rfc/index.rst1
-rw-r--r--docs/source/community/rfc/rfc-5.rst135
-rw-r--r--docs/source/development/bindings.rst5
-rw-r--r--docs/source/operations/projections/cea.rst6
-rw-r--r--scripts/reference_exported_symbols.txt1
-rw-r--r--src/4D_api.cpp19
-rw-r--r--src/apps/projinfo.cpp33
-rw-r--r--src/filemanager.cpp66
-rw-r--r--src/filemanager.hpp5
-rw-r--r--src/grids.cpp104
-rw-r--r--src/init.cpp22
-rw-r--r--src/iso19111/coordinateoperation.cpp2
-rw-r--r--src/iso19111/io.cpp55
-rw-r--r--src/proj_internal.h3
-rwxr-xr-xtest/cli/testprojinfo26
-rwxr-xr-xtest/fuzzers/build.sh75
-rwxr-xr-xtest/fuzzers/build_google_oss_fuzzers.sh41
-rwxr-xr-xtest/fuzzers/build_seed_corpus.sh12
-rw-r--r--test/fuzzers/proj_crs_to_crs_fuzzer.cpp6
-rw-r--r--test/gie/geotiff_grids.gie33
-rw-r--r--test/unit/test_io.cpp18
30 files changed, 559 insertions, 156 deletions
diff --git a/.travis.yml b/.travis.yml
index 42924cd2..4f15edd4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -92,4 +92,5 @@ notifications:
irc:
channels:
- "irc.freenode.org#gdal"
+ - "irc.freenode.org#proj"
use_notice: true
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index b9cff123..23be1f23 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -39,9 +39,6 @@ install(FILES
# Make information about the cmake targets (the library and the tools)
# available.
install(EXPORT targets
- FILE ${PROJECT_NAME_LOWER}-targets.cmake
- DESTINATION "${CMAKECONFIGDIR}")
-install(EXPORT targets
NAMESPACE ${PROJECT_NAME}::
- FILE ${PROJECT_NAME_LOWER}-namespace-targets.cmake
+ FILE ${PROJECT_NAME_LOWER}-targets.cmake
DESTINATION "${CMAKECONFIGDIR}")
diff --git a/cmake/project-config.cmake.in b/cmake/project-config.cmake.in
index c62ecb47..fcb0698f 100644
--- a/cmake/project-config.cmake.in
+++ b/cmake/project-config.cmake.in
@@ -23,7 +23,6 @@ set (@PROJECT_NAME@_BINARY_DIRS "${_ROOT}/@BINDIR@")
set (@PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::proj)
# Read in the exported definition of the library
include ("${_DIR}/@PROJECT_NAME_LOWER@-targets.cmake")
-include ("${_DIR}/@PROJECT_NAME_LOWER@-namespace-targets.cmake")
unset (_ROOT)
unset (_DIR)
diff --git a/configure.ac b/configure.ac
index 2abf5684..28e9067d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,7 +89,6 @@ dnl C++ specific stuff
AC_LANG_PUSH([C++])
AX_CHECK_COMPILE_FLAG([-Wunused-private-field], [CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"],,[$ERROR_ON_UNKNOWN_OPTIONS])
-AX_CHECK_COMPILE_FLAG([-Wmissing-prototypes], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"],,[$ERROR_ON_UNKNOWN_OPTIONS])
AX_CHECK_COMPILE_FLAG([-Wmissing-declarations], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"],,[$ERROR_ON_UNKNOWN_OPTIONS])
AX_CHECK_COMPILE_FLAG([-Wnon-virtual-dtor], [CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"],,[$ERROR_ON_UNKNOWN_OPTIONS])
AX_CHECK_COMPILE_FLAG([-Wold-style-cast], [WARN_OLD_STYLE_CAST="-Wold-style-cast"],,[$ERROR_ON_UNKNOWN_OPTIONS])
@@ -255,8 +254,8 @@ dnl ---------------------------------------------------------------------------
dnl Check for libtiff
dnl ---------------------------------------------------------------------------
-AC_ARG_ENABLE([tiff-is-strongly-discouraged],
- AS_HELP_STRING([--disable-tiff-is-strongly-discouraged],
+AC_ARG_ENABLE([tiff],
+ AS_HELP_STRING([--disable-tiff],
[Disable TIFF support. Strongly discouraged !]),
[enable_tiff=no],
[enable_tiff=yes])
@@ -284,7 +283,7 @@ CURL_CFLAGS=
CURL_LIB=
AC_ARG_WITH(curl,
- [ --with-curl[=ARG] Enable curl support (ARG=path to curl-config.)],,,)
+ [ --with-curl[=ARG] Enable curl support (ARG=path to curl-config.)],,,)
dnl Clear some cache variables
unset ac_cv_path_LIBCURL
diff --git a/data/Makefile.am b/data/Makefile.am
index 564bbeed..ede26453 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -86,6 +86,7 @@ EXTRA_DIST = proj.ini GL27 nad.lst nad27 nad83 \
tests/nkgrf03vel_realigned_xy_extract.ct2 \
tests/nkgrf03vel_realigned_z_extract.gtx \
tests/test_hgrid_with_two_level_of_subgrids_no_grid_name.tif \
+ tests/us_noaa_geoid06_ak_subset_at_antimeridian.tif \
null \
generate_all_sql_in.cmake sql_filelist.cmake \
$(SQL_ORDERED_LIST)
diff --git a/data/tests/us_noaa_geoid06_ak_subset_at_antimeridian.tif b/data/tests/us_noaa_geoid06_ak_subset_at_antimeridian.tif
new file mode 100644
index 00000000..2c01759c
--- /dev/null
+++ b/data/tests/us_noaa_geoid06_ak_subset_at_antimeridian.tif
Binary files differ
diff --git a/docs/images/foss4g2020.png b/docs/images/foss4g2020.png
new file mode 100644
index 00000000..3371bebe
--- /dev/null
+++ b/docs/images/foss4g2020.png
Binary files differ
diff --git a/docs/source/apps/projinfo.rst b/docs/source/apps/projinfo.rst
index 47deaaeb..0b65b8a0 100644
--- a/docs/source/apps/projinfo.rst
+++ b/docs/source/apps/projinfo.rst
@@ -26,7 +26,8 @@ Synopsis
| [--main-db-path path] [--aux-db-path path]*
| [--identify] [--3d]
| [--c-ify] [--single-line]
- | {object_definition} | {object_reference} | (-s {srs_def} -t {srs_def})
+ | --searchpaths | --remote-data | {object_definition} |
+ | {object_reference} | (-s {srs_def} -t {srs_def})
|
where {object_definition} or {srs_def} is
@@ -248,6 +249,21 @@ The following control parameters can appear in any order:
Output WKT or PROJJSON strings on a single line, instead of multiple intended lines by
default.
+.. option:: --searchpaths
+
+ .. versionadded:: 7.0
+
+ Output the directories into which PROJ resources will be looked for
+ (if not using C API such as :cpp:func:`proj_context_set_search_paths`
+ that will override them.
+
+.. option:: --remote-data
+
+ .. versionadded:: 7.0
+
+ Display information regarding if :ref:`network` is enabled, and the
+ related URL.
+
Examples
********
diff --git a/docs/source/community/index.rst b/docs/source/community/index.rst
index b0d1ce3a..0ae69d7e 100644
--- a/docs/source/community/index.rst
+++ b/docs/source/community/index.rst
@@ -16,3 +16,17 @@ contributor the community is always very welcoming.
code_contributions
code_of_conduct
rfc/index
+
+Conference
+----------
+
+.. image:: ../../images/foss4g2020.png
+ :alt: FOSS4G 2020
+ :target: https://2020.foss4g.org/
+
+`FOSS4G 2020 <https://2020.foss4g.org/>`_ is the leading annual conference for
+free and open source geospatial software. It will include presentations related
+to PROJ, and some of the PROJ development community will be attending. It is the
+event for those interested in PROJ, other FOSS geospatial technologies and the
+community around them. The conference will be held in Calgary, Canada,
+August 24th - August 29th, 2020.
diff --git a/docs/source/community/rfc/index.rst b/docs/source/community/rfc/index.rst
index a41dfe7d..ced162e2 100644
--- a/docs/source/community/rfc/index.rst
+++ b/docs/source/community/rfc/index.rst
@@ -15,3 +15,4 @@ the project.
rfc-2
rfc-3
rfc-4
+ rfc-5
diff --git a/docs/source/community/rfc/rfc-5.rst b/docs/source/community/rfc/rfc-5.rst
new file mode 100644
index 00000000..cab4687f
--- /dev/null
+++ b/docs/source/community/rfc/rfc-5.rst
@@ -0,0 +1,135 @@
+.. _rfc5:
+
+====================================================================
+PROJ RFC 5: Adopt GeoTIFF-based grids for grids delivered with PROJ
+====================================================================
+
+:Author: Even Rouault
+:Contact: even.rouault@spatialys.com
+:Status: Adopted
+:Implementation target: PROJ 7
+:Last Updated: 2020-01-28
+
+Motivation
+-------------------------------------------------------------------------------
+
+This RFC is a continuation of :ref:`rfc4`. With RFC4, PROJ can, upon request
+of the user, download grids from a CDN in a progressive way. There is also API,
+such as :cpp:func:`proj_download_file` to be able to download a GeoTIFF grid in
+the user writable directory. The content of the CDN at https://cdn.proj.org
+is https://github.com/OSGeo/PROJ-data , which has the same content
+as https://github.com/OSGeo/proj-datumgrid converted in GeoTIFF files. In the
+current state, we could have a somewhat inconsistency between users relying on
+the proj-datumgrid, proj-datumgrid-[world,northamerica,oceania,europe] packages
+of mostly NTv2 and GTX files, and what is shipped through the CDN. Maintaining
+two repositories is also a maintaince burden in the long term.
+
+It is thus desirable to have a single source of truth, and we propose it to be
+based on the GeoTIFF grids.
+
+Summary of work planned by this RFC and related decisions
+-------------------------------------------------------------------------------
+
+- https://github.com/OSGeo/PROJ-data/ will be used, starting with
+ PROJ 7.0, to create "static" grid packages.
+
+- For now, a single package of, mostly GeoTIFF grids (a few text files for
+ PROJ init style files, as well as a few edge cases for deformation models where
+ grids have not been converted), will be delivered.
+ Its size at the time of writing is 486 MB (compared to 1.5 GB of uncompressed
+ NTv2 + GTX content, compressed to ~ 700 MB currently)
+
+- The content of this archive will be flat, i.e. no subdirectories
+
+- Each file will be named according to the following pattern
+ ``${agency_name}_${filename}[.ext]``. For example fr_ign_ntf_r93.tif
+ This convention should allow packagers, if the need arise, to be able to
+ split the monolothic package in smaller ones, based on criterion related to
+ the country.
+
+ The agency name is the one you can see from the directory names at
+ https://github.com/OSGeo/PROJ-data/.
+ ``${agency_name}`` itself is structure like ``${two_letter_country_code_of_agency_nationality}_${some_abbreviation}``
+ (with the exception of eur_nkg, for the Nordic Geodetic Commission which
+ isn't affiliated to a single country but to some european countries, and
+ follows the general scheme)
+
+- https://github.com/OSGeo/proj-datumgrid and related packages will only be
+ maintained during the remaining lifetime of PROJ 6.x. After that, the
+ repository will no longer receive any update and will be put in archiving
+ state (see https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-archiving-repositories)
+
+- PROJ database ``grid_alternatives`` table will be updated to point to the new
+ TIFF filenames. It will also maintain the old names as used by current
+ proj-datumgrid packages to be able to provide backward compatibility when
+ a PROJ string refers to a grid by its previous name.
+
+- Upon adoption of this RFC, new grids referenced by PROJ database will only
+ point to GeoTIFF grid names.
+
+- Related to the above point, if a PROJ string refers to a grid name, let's
+ say foo.gsb. This grid will first be looked for in all the relevant locations
+ under this name. If no match is found, then a lookup in the
+ ``grid_alternatives`` table will be done to retrieve the potential new name
+ (GeoTIFF file), and if there's such match, a new look-up in the file system
+ will be done with the name of this GeoTIFF file.
+
+- The ``package_name`` column of grid_alternatives will no longer be filled.
+ And ``url`` will be filled with the direct URL to the grid in the CDN, for
+ example: https://cdn.proj.org/fr_ign_ntf_r93.tif
+
+- The Python scripts to convert grids (NTv2, GTX) to GeoTIFF currently available at
+ https://github.com/rouault/sample_proj_gtiff_grids/ will be moved to a
+ grid_tools/ subdirectories of https://github.com/OSGeo/PROJ-data/
+ Documentation for those utilities will be added to PROJ documentation.
+
+- Obviously, all the above assumes PROJ builds to have libtiff enabled.
+ Non-libtiff builds are not considered as nominal PROJ builds (if a PROJ master
+ build is attempted and libtiff is not detected, it fails. The user has to
+ explictly ask to disable TIFF support), and users deciding to go through that
+ route will have to deal with the consequences (that is that
+ grid-based transformations generated by PROJ will likely be non working)
+
+Backward compatibility
+-------------------------------------------------------------------------------
+
+This change is considered to be *mostly* backward compatible. There might be
+impacts for software using :cpp:func:`proj_coordoperation_get_grid_used` and
+assuming that the url returned is one of the proj-datumgrid-xxx files at
+https://download.osgeo.org. As mentionned in
+https://lists.osgeo.org/pipermail/proj/2020-January/009274.html , this
+assumption was not completely bullet-proof either.
+There will be impacts on software checking the value of PROJ pipeline strings
+resulting :cpp:func:`proj_create_crs_to_crs`. The new grid names will now
+be returned (the most impacted software will likely be PROJ's own test suite)
+
+Although discouraged, people not using the new proj-datumgrid-geotiff-XXX.zip
+archives, should still be able to use the old archives made of NTv2/GTX files,
+at least as long as the PROJ database does not only point to a GeoTIFF grid.
+So this might be a short-term partly working solution, but at time goes, it
+will become increasingly non-working. The nominal combination will be
+PROJ 7.0 + proj-datumgrid-geotiff-1.0.zip
+
+Testing
+-------------------------------------------------------------------------------
+
+PROJ test suite will have to be adapted for the new TIFF based filenames.
+
+Mechanism to auto-promote existing NTv2/GTX names to TIFF ones will be exercised.
+
+Proposed implementation
+-------------------------------------------------------------------------------
+
+https://github.com/OSGeo/PROJ/pull/1891 and https://github.com/OSGeo/PROJ-data/pull/5
+
+Adoption status
+-------------------------------------------------------------------------------
+
+The RFC was adopted on 2020-01-28 with +1's from the following PSC members
+
+* Kristian Evers
+* Even Rouault
+* Thomas Knudsen
+* Howard Butler
+* Kurt Schwehr
+
diff --git a/docs/source/development/bindings.rst b/docs/source/development/bindings.rst
index 8f3b44a3..26becb92 100644
--- a/docs/source/development/bindings.rst
+++ b/docs/source/development/bindings.rst
@@ -28,6 +28,11 @@ Go (Golang)
`go-proj <https://github.com/everystreet/go-proj>`_:
Go bindings and idiomatic wrapper for PROJ
+Julia
+=====
+`Proj4.jl <https://github.com/JuliaGeo/Proj4.jl>`_"
+Low-level bindings and a Julian API over PROJ.
+
TCL
========
`proj4tcl <http://wiki.tcl.tk/41270>`_:
diff --git a/docs/source/operations/projections/cea.rst b/docs/source/operations/projections/cea.rst
index 4542fe71..80fe1df3 100644
--- a/docs/source/operations/projections/cea.rst
+++ b/docs/source/operations/projections/cea.rst
@@ -29,3 +29,9 @@ Parameters
.. include:: ../options/x_0.rst
.. include:: ../options/y_0.rst
+
+.. note::
+
+ ``lat_ts`` and ``k_0`` are mutually exclusive. If ``lat_ts``
+ is specified, it is equivalent to setting ``k_0`` to
+ :math:`\frac{\cos \phi_{ts}}{\sqrt{1 - e^2 \sin^2 \phi_{ts}}}` \ No newline at end of file
diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt
index 07043504..ee174da9 100644
--- a/scripts/reference_exported_symbols.txt
+++ b/scripts/reference_exported_symbols.txt
@@ -739,6 +739,7 @@ pj_cleanup_lock
pj_clear_initcache
pj_compare_datums
pj_context_get_grid_cache_filename(projCtx_t*)
+pj_context_get_url_endpoint(projCtx_t*)
pj_context_get_user_writable_directory(projCtx_t*, bool)
pj_context_is_network_enabled(projCtx_t*)
pj_ctx_alloc
diff --git a/src/4D_api.cpp b/src/4D_api.cpp
index dabd44a0..91510c35 100644
--- a/src/4D_api.cpp
+++ b/src/4D_api.cpp
@@ -1484,23 +1484,10 @@ PJ_INFO proj_info (void) {
/* build search path string */
auto ctx = pj_get_default_ctx();
if (!ctx || ctx->search_paths.empty()) {
- // 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.empty()) {
- buf = path_append(buf, PROJ_LIB, &buf_size);
+ const auto searchpaths = pj_get_default_searchpaths(ctx);
+ for( const auto& path: searchpaths ) {
+ buf = path_append(buf, path.c_str(), &buf_size);
}
-#endif
} else {
for (const auto &path : ctx->search_paths) {
buf = path_append(buf, path.c_str(), &buf_size);
diff --git a/src/apps/projinfo.cpp b/src/apps/projinfo.cpp
index 27ea278a..9cd9b2ee 100644
--- a/src/apps/projinfo.cpp
+++ b/src/apps/projinfo.cpp
@@ -98,8 +98,9 @@ static void usage() {
<< std::endl
<< " [--identify] [--3d]" << std::endl
<< " [--c-ify] [--single-line]" << std::endl
- << " {object_definition} | (-s {srs_def} -t {srs_def})"
- << std::endl;
+ << " --searchpaths | --remote-data | "
+ "{object_definition} |"
+ << " (-s {srs_def} -t {srs_def})" << std::endl;
std::cerr << std::endl;
std::cerr << "-o: formats is a comma separated combination of: "
"all,default,PROJ,WKT_ALL,WKT2:2015,WKT2:2019,WKT1:GDAL,"
@@ -1057,6 +1058,34 @@ int main(int argc, char **argv) {
outputOpt.strict = false;
} else if (ci_equal(arg, "--3d")) {
promoteTo3D = true;
+ } else if (ci_equal(arg, "--searchpaths")) {
+#ifdef _WIN32
+ constexpr char delim = ';';
+#else
+ constexpr char delim = ':';
+#endif
+ const auto paths = split(proj_info().searchpath, delim);
+ for (const auto &path : paths) {
+ std::cout << path << std::endl;
+ }
+ std::exit(0);
+ } else if (ci_equal(arg, "--remote-data")) {
+#ifdef CURL_ENABLED
+ if (pj_context_is_network_enabled(nullptr)) {
+ std::cout << "Status: enabled" << std::endl;
+ std::cout << "URL: " << pj_context_get_url_endpoint(nullptr)
+ << std::endl;
+ } else {
+ std::cout << "Status: disabled" << std::endl;
+ std::cout << "Reason: not enabled in proj.ini or "
+ "PROJ_NETWORK=ON not specified"
+ << std::endl;
+ }
+#else
+ std::cout << "Status: disabled" << std::endl;
+ std::cout << "Reason: build without Curl support" << std::endl;
+#endif
+ std::exit(0);
} else if (arg == "-?" || arg == "--help") {
usage();
} else if (arg[0] == '-') {
diff --git a/src/filemanager.cpp b/src/filemanager.cpp
index 75476974..ac753012 100644
--- a/src/filemanager.cpp
+++ b/src/filemanager.cpp
@@ -1254,9 +1254,8 @@ static bool is_rel_or_absolute_filename(const char *name) {
// ---------------------------------------------------------------------------
#ifdef _WIN32
-static const char *get_path_from_win32_projlib(PJ_CONTEXT *ctx,
- const char *name,
- std::string &out) {
+
+static std::string pj_get_win32_projlib() {
/* Check if proj.db lieves in a share/proj dir parallel to bin/proj.dll */
/* Based in
* https://stackoverflow.com/questions/9112893/how-to-get-path-to-executable-in-c-running-on-windows
@@ -1272,10 +1271,10 @@ static const char *get_path_from_win32_projlib(PJ_CONTEXT *ctx,
DWORD last_error = GetLastError();
if (result == 0) {
- return nullptr;
+ return std::string();
} else if (result == path_size - 1) {
if (ERROR_INSUFFICIENT_BUFFER != last_error) {
- return nullptr;
+ return std::string();
}
path_size = path_size * 2;
} else {
@@ -1285,18 +1284,33 @@ static const char *get_path_from_win32_projlib(PJ_CONTEXT *ctx,
// Now remove the program's name. It was (example)
// "C:\programs\gmt6\bin\gdal_translate.exe"
wout.resize(wcslen(wout.c_str()));
- out = NS_PROJ::WStringToUTF8(wout);
+ std::string out = NS_PROJ::WStringToUTF8(wout);
size_t k = out.size();
while (k > 0 && out[--k] != '\\') {
}
out.resize(k);
- out += "/../share/proj/";
+ out += "/../share/proj";
+ return out;
+}
+
+// ---------------------------------------------------------------------------
+
+static const char *get_path_from_win32_projlib(PJ_CONTEXT *ctx,
+ const char *name,
+ std::string &out) {
+
+ out = pj_get_win32_projlib();
+ if (out.empty()) {
+ return nullptr;
+ }
+ out += '/';
out += name;
return NS_PROJ::FileManager::exists(ctx, out.c_str()) ? out.c_str()
: nullptr;
}
+
#endif
/************************************************************************/
@@ -1460,6 +1474,41 @@ pj_open_lib_internal(projCtx ctx, const char *name, const char *mode,
}
/************************************************************************/
+/* pj_get_default_searchpaths() */
+/************************************************************************/
+
+std::vector<std::string> pj_get_default_searchpaths(PJ_CONTEXT *ctx) {
+ std::vector<std::string> ret;
+
+ // 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') {
+ ret.push_back(pj_context_get_user_writable_directory(ctx, false));
+ }
+ const std::string envPROJ_LIB = NS_PROJ::FileManager::getProjLibEnvVar(ctx);
+ if (!envPROJ_LIB.empty()) {
+ ret.push_back(envPROJ_LIB);
+ }
+#ifdef _WIN32
+ if (envPROJ_LIB.empty()) {
+ const std::string win32Dir = pj_get_win32_projlib();
+ if (!win32Dir.empty()) {
+ ret.push_back(win32Dir);
+ }
+ }
+#endif
+#ifdef PROJ_LIB
+ if (envPROJ_LIB.empty()) {
+ ret.push_back(PROJ_LIB);
+ }
+#endif
+ return ret;
+}
+
+/************************************************************************/
/* pj_open_file_with_manager() */
/************************************************************************/
@@ -1642,6 +1691,9 @@ int pj_find_file(projCtx ctx, const char *short_filename,
/************************************************************************/
std::string pj_context_get_url_endpoint(PJ_CONTEXT *ctx) {
+ if (ctx == nullptr) {
+ ctx = pj_get_default_ctx();
+ }
if (!ctx->endpoint.empty()) {
return ctx->endpoint;
}
diff --git a/src/filemanager.hpp b/src/filemanager.hpp
index 2761b83c..bbd12b7e 100644
--- a/src/filemanager.hpp
+++ b/src/filemanager.hpp
@@ -29,6 +29,8 @@
#define FILEMANAGER_HPP_INCLUDED
#include <memory>
+#include <string>
+#include <vector>
#include "proj.h"
#include "proj/util.hpp"
@@ -95,9 +97,10 @@ class File {
std::unique_ptr<File> pj_network_file_open(PJ_CONTEXT *ctx,
const char *filename);
-
NS_PROJ_END
+std::vector<std::string> pj_get_default_searchpaths(PJ_CONTEXT *ctx);
+
//! @endcond Doxygen_Suppress
#endif // FILEMANAGER_HPP_INCLUDED
diff --git a/src/grids.cpp b/src/grids.cpp
index 68bf8600..b641f088 100644
--- a/src/grids.cpp
+++ b/src/grids.cpp
@@ -1403,13 +1403,28 @@ bool VerticalShiftGridSet::reopen(PJ_CONTEXT *ctx) {
// ---------------------------------------------------------------------------
+static bool isPointInExtent(double lon, double lat, const ExtentAndRes &extent,
+ double eps = 0) {
+ if (!(lat + eps >= extent.southLat && lat - eps <= extent.northLat))
+ return false;
+ if (extent.fullWorldLongitude())
+ return true;
+ if (lon + eps < extent.westLon)
+ lon += 2 * M_PI;
+ else if (lon - eps > extent.eastLon)
+ lon -= 2 * M_PI;
+ if (!(lon + eps >= extent.westLon && lon - eps <= extent.eastLon))
+ return false;
+ return true;
+}
+
+// ---------------------------------------------------------------------------
+
const VerticalShiftGrid *VerticalShiftGrid::gridAt(double lon,
double lat) const {
for (const auto &child : m_children) {
const auto &extentChild = child->extentAndRes();
- if ((extentChild.fullWorldLongitude() ||
- (lon >= extentChild.westLon && lon <= extentChild.eastLon)) &&
- lat >= extentChild.southLat && lat <= extentChild.northLat) {
+ if (isPointInExtent(lon, lat, extentChild)) {
return child->gridAt(lon, lat);
}
}
@@ -1424,9 +1439,7 @@ const VerticalShiftGrid *VerticalShiftGridSet::gridAt(double lon,
return grid.get();
}
const auto &extent = grid->extentAndRes();
- if ((extent.fullWorldLongitude() ||
- (lon >= extent.westLon && lon <= extent.eastLon)) &&
- lat >= extent.southLat && lat <= extent.northLat) {
+ if (isPointInExtent(lon, lat, extent)) {
return grid->gridAt(lon, lat);
}
}
@@ -2373,11 +2386,7 @@ const HorizontalShiftGrid *HorizontalShiftGrid::gridAt(double lon,
const auto &extentChild = child->extentAndRes();
const double epsilon = (extentChild.resLon + extentChild.resLat) *
REL_TOLERANCE_HGRIDSHIFT;
- if ((extentChild.fullWorldLongitude() ||
- (lon + epsilon >= extentChild.westLon &&
- lon - epsilon <= extentChild.eastLon)) &&
- lat + epsilon >= extentChild.southLat &&
- lat - epsilon <= extentChild.northLat) {
+ if (isPointInExtent(lon, lat, extentChild, epsilon)) {
return child->gridAt(lon, lat);
}
}
@@ -2394,11 +2403,7 @@ const HorizontalShiftGrid *HorizontalShiftGridSet::gridAt(double lon,
const auto &extent = grid->extentAndRes();
const double epsilon =
(extent.resLon + extent.resLat) * REL_TOLERANCE_HGRIDSHIFT;
- if ((extent.fullWorldLongitude() ||
- (lon + epsilon >= extent.westLon &&
- lon - epsilon <= extent.eastLon)) &&
- lat + epsilon >= extent.southLat &&
- lat - epsilon <= extent.northLat) {
+ if (isPointInExtent(lon, lat, extent, epsilon)) {
return grid->gridAt(lon, lat);
}
}
@@ -2712,9 +2717,7 @@ bool GenericShiftGridSet::reopen(PJ_CONTEXT *ctx) {
const GenericShiftGrid *GenericShiftGrid::gridAt(double lon, double lat) const {
for (const auto &child : m_children) {
const auto &extentChild = child->extentAndRes();
- if ((extentChild.fullWorldLongitude() ||
- (lon >= extentChild.westLon && lon <= extentChild.eastLon)) &&
- lat >= extentChild.southLat && lat <= extentChild.northLat) {
+ if (isPointInExtent(lon, lat, extentChild)) {
return child->gridAt(lon, lat);
}
}
@@ -2730,9 +2733,7 @@ const GenericShiftGrid *GenericShiftGridSet::gridAt(double lon,
return grid.get();
}
const auto &extent = grid->extentAndRes();
- if ((extent.fullWorldLongitude() ||
- (lon >= extent.westLon && lon <= extent.eastLon)) &&
- lat >= extent.southLat && lat <= extent.northLat) {
+ if (isPointInExtent(lon, lat, extent)) {
return grid->gridAt(lon, lat);
}
}
@@ -2948,7 +2949,13 @@ static PJ_LP pj_hgrid_apply_internal(projCtx ctx, PJ_LP in,
/* normalize input to ll origin */
tb = in;
const auto *extent = &(grid->extentAndRes());
+ const double epsilon =
+ (extent->resLon + extent->resLat) * REL_TOLERANCE_HGRIDSHIFT;
tb.lam -= extent->westLon;
+ if (tb.lam + epsilon < 0)
+ tb.lam += 2 * M_PI;
+ else if (tb.lam - epsilon > extent->eastLon - extent->westLon)
+ tb.lam -= 2 * M_PI;
tb.phi -= extent->southLat;
t = pj_hgrid_interpolate(tb, grid, true);
@@ -2992,6 +2999,10 @@ static PJ_LP pj_hgrid_apply_internal(projCtx ctx, PJ_LP in,
t.phi = lp.phi - extent->southLat;
tb = in;
tb.lam -= extent->westLon;
+ if (tb.lam + epsilon < 0)
+ tb.lam += 2 * M_PI;
+ else if (tb.lam - epsilon > extent->eastLon - extent->westLon)
+ tb.lam -= 2 * M_PI;
tb.phi -= extent->southLat;
dif.lam = std::numeric_limits<double>::max();
dif.phi = std::numeric_limits<double>::max();
@@ -3077,11 +3088,15 @@ PJ_LP pj_hgrid_value(PJ *P, const ListOfHGrids &grids, PJ_LP lp) {
/* normalize input to ll origin */
const auto &extent = grid->extentAndRes();
+ const double epsilon =
+ (extent.resLon + extent.resLat) * REL_TOLERANCE_HGRIDSHIFT;
lp.lam -= extent.westLon;
+ if (lp.lam + epsilon < 0)
+ lp.lam += 2 * M_PI;
+ else if (lp.lam - epsilon > extent.eastLon - extent.westLon)
+ lp.lam -= 2 * M_PI;
lp.phi -= extent.southLat;
- lp.lam = adjlon(lp.lam - M_PI) + M_PI;
-
out = pj_hgrid_interpolate(lp, grid, false);
if (grid->hasChanged()) {
if (gridset->reopen(P->ctx)) {
@@ -3119,23 +3134,43 @@ static double read_vgrid_value(PJ_CONTEXT *ctx, const ListOfVGrids &grids,
}
}
if (!grid) {
+ pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
return HUGE_VAL;
}
const auto &extent = grid->extentAndRes();
- /* Interpolation a location within the grid */
+ /* Interpolation of a location within the grid */
double grid_x = (input.lam - extent.westLon) / extent.resLon;
- if (extent.fullWorldLongitude()) {
- // 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 + grid->width(), grid->width()) + grid->width(),
- grid->width());
+ if (input.lam < extent.westLon) {
+ if (extent.fullWorldLongitude()) {
+ // 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 + grid->width(), grid->width()) +
+ grid->width(),
+ grid->width());
+ } else {
+ grid_x = (input.lam + 2 * M_PI - extent.westLon) / extent.resLon;
+ }
+ } else if (input.lam > extent.eastLon) {
+ if (extent.fullWorldLongitude()) {
+ // 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 + grid->width(), grid->width()) +
+ grid->width(),
+ grid->width());
+ } else {
+ grid_x = (input.lam - 2 * M_PI - extent.westLon) / extent.resLon;
+ }
}
double grid_y = (input.phi - extent.southLat) / extent.resLat;
int grid_ix = static_cast<int>(lround(floor(grid_x)));
- assert(grid_ix >= 0 && grid_ix < grid->width());
+ if (!(grid_ix >= 0 && grid_ix < grid->width())) {
+ // in the unlikely case we end up here...
+ pj_log(ctx, PJ_LOG_ERROR, "grid_ix not in grid");
+ pj_ctx_set_errno(ctx, PJD_ERR_GRID_AREA);
+ return HUGE_VAL;
+ }
int grid_iy = static_cast<int>(lround(floor(grid_y)));
assert(grid_iy >= 0 && grid_iy < grid->height());
grid_x -= grid_ix;
@@ -3304,6 +3339,11 @@ bool pj_bilinear_interpolation_three_samples(const GenericShiftGrid *grid,
const auto &extent = grid->extentAndRes();
double grid_x = (lp.lam - extent.westLon) / extent.resLon;
+ if (lp.lam < extent.westLon) {
+ grid_x = (lp.lam + 2 * M_PI - extent.westLon) / extent.resLon;
+ } else if (lp.lam > extent.eastLon) {
+ grid_x = (lp.lam - 2 * M_PI - extent.westLon) / extent.resLon;
+ }
double grid_y = (lp.phi - extent.southLat) / extent.resLat;
int ix = static_cast<int>(grid_x);
int iy = static_cast<int>(grid_y);
diff --git a/src/init.cpp b/src/init.cpp
index ba3d86e4..9c7b7b19 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -49,25 +49,23 @@ static paralist *string_to_paralist (PJ_CONTEXT *ctx, char *definition) {
Convert a string (presumably originating from get_init_string) to a paralist.
***************************************************************************************/
const char *c = definition;
- paralist *first = nullptr, *next = nullptr;
+ paralist *first = nullptr, *last = nullptr;
while (*c) {
/* Keep a handle to the start of the list, so we have something to return */
- if (nullptr==first)
- first = next = pj_mkparam_ws (c, &c);
- else
- next = next->next = pj_mkparam_ws (c, &c);
- if (nullptr==next) {
+ auto param = pj_mkparam_ws (c, &c);
+ if (nullptr==param) {
pj_dealloc_params (ctx, first, ENOMEM);
return nullptr;
}
+ if (nullptr==last) {
+ first = param;
+ }
+ else {
+ last->next = param;
+ }
+ last = param;
}
-
- if( next == nullptr )
- return nullptr;
-
- /* Terminate list and return */
- next->next = nullptr;
return first;
}
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 6d97adc3..8ca95223 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -6238,7 +6238,7 @@ void Conversion::_exportToPROJString(
if (!param->proj_name) {
continue;
}
- const auto value =
+ const auto &value =
parameterValueMeasure(param->wkt2_name, param->epsg_code);
double valueConverted = 0;
if (value == nullMeasure) {
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index d88581b4..e4b159bd 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -3526,7 +3526,7 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
EPSG_CODE_PARAMETER_LATITUDE_OF_NATURAL_ORIGIN);
propertiesParameter.set(Identifier::CODESPACE_KEY,
Identifier::EPSG);
- } else if (paramMapping) {
+ } else if (mapping && paramMapping) {
for (size_t idx = 0; mapping->params[idx] != nullptr; ++idx) {
if (mapping->params[idx] == paramMapping) {
foundParameters[idx] = true;
@@ -4542,7 +4542,7 @@ class JSONParser {
static Measure getMeasure(const json &j);
IdentifierNNPtr buildId(const json &j, bool removeInverseOf);
- ObjectDomainPtr buildObjectDomain(const json &j);
+ static ObjectDomainPtr buildObjectDomain(const json &j);
PropertyMap buildProperties(const json &j, bool removeInverseOf = false);
GeographicCRSNNPtr buildGeographicCRS(const json &j);
@@ -8736,22 +8736,43 @@ CRSNNPtr PROJStringParser::Private::buildProjectedCRS(
} else if (param->unit_type == UnitOfMeasure::Type::SCALE) {
value = 1;
- } else {
- // For omerc, if gamma is missing, the default value is
- // alpha
- if (step.name == "omerc" && proj_name == "gamma") {
- paramValue = &getParamValue(step, "alpha");
- if (!paramValue->empty()) {
- value = getAngularValue(*paramValue);
+ }
+ // For omerc, if gamma is missing, the default value is
+ // alpha
+ else if (step.name == "omerc" && proj_name == "gamma") {
+ paramValue = &getParamValue(step, "alpha");
+ if (!paramValue->empty()) {
+ value = getAngularValue(*paramValue);
+ }
+ } else if (step.name == "krovak") {
+ if (param->epsg_code ==
+ EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS) {
+ value = 30.28813975277777776;
+ } else if (
+ param->epsg_code ==
+ EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL) {
+ value = 78.5;
+ }
+ } else if (step.name == "cea" && proj_name == "lat_ts") {
+ paramValue = &getParamValueK(step);
+ if (!paramValue->empty()) {
+ bool hasError = false;
+ const double k = getNumericValue(*paramValue, &hasError);
+ if (hasError) {
+ throw ParsingException("invalid value for k/k_0");
}
- } else if (step.name == "krovak") {
- if (param->epsg_code ==
- EPSG_CODE_PARAMETER_COLATITUDE_CONE_AXIS) {
- value = 30.28813975277777776;
- } else if (
- param->epsg_code ==
- EPSG_CODE_PARAMETER_LATITUDE_PSEUDO_STANDARD_PARALLEL) {
- value = 78.5;
+ if (k >= 0 && k <= 1) {
+ const double es =
+ geogCRS->ellipsoid()->squaredEccentricity();
+ if (es < 0) {
+ throw ParsingException("Invalid flattening");
+ }
+ value =
+ Angle(acos(k * sqrt((1 - es) / (1 - k * k * es))),
+ UnitOfMeasure::RADIAN)
+ .convertToUnit(UnitOfMeasure::DEGREE);
+ } else {
+ throw ParsingException("k/k_0 should be in [0,1]");
}
}
}
diff --git a/src/proj_internal.h b/src/proj_internal.h
index a587c037..69d583fc 100644
--- a/src/proj_internal.h
+++ b/src/proj_internal.h
@@ -863,7 +863,8 @@ PJ *pj_create_argv_internal (PJ_CONTEXT *ctx, int argc, char **argv);
// For use by projinfo
bool PROJ_DLL pj_context_is_network_enabled(PJ_CONTEXT* ctx);
-std::string pj_context_get_url_endpoint(PJ_CONTEXT* ctx);
+// For use by projinfo
+std::string PROJ_DLL pj_context_get_url_endpoint(PJ_CONTEXT* ctx);
void pj_load_ini(PJ_CONTEXT* ctx);
diff --git a/test/cli/testprojinfo b/test/cli/testprojinfo
index b9c452fb..4ec1bdbb 100755
--- a/test/cli/testprojinfo
+++ b/test/cli/testprojinfo
@@ -175,6 +175,32 @@ echo 'Testing -k operation EPSG:8457 -o PROJ -q' >> ${OUT}
$EXE -k operation EPSG:8457 -o PROJ -q >>${OUT} 2>&1
echo "" >>${OUT}
+# Testing --searchpaths
+if ! $EXE --searchpaths > testprojinfo_out_searchpaths.txt; then
+ echo "--searchpaths failed"
+ exit 100
+fi
+# Hard to test content of testprojinfo_out_searchpaths.txt
+rm testprojinfo_out_searchpaths.txt
+
+# Testing --remote-data
+if ! $EXE --remote-data > testprojinfo_out_remotedata.txt; then
+ echo "--remote-data failed"
+ exit 100
+fi
+# Hard to test content of testprojinfo_out_remotedata.txt
+rm testprojinfo_out_remotedata.txt
+
+# Testing --remote-data
+export PROJ_NETWORK=ON
+if ! $EXE --remote-data > testprojinfo_out_remotedata.txt; then
+ echo "--remote-data failed"
+ exit 100
+fi
+# Hard to test content of testprojinfo_out_remotedata.txt
+rm testprojinfo_out_remotedata.txt
+unset PROJ_NETWORK
+
# do 'diff' with distribution results
echo "diff ${OUT} with testprojinfo_out.dist"
diff -u ${OUT} ${TEST_CLI_DIR}/testprojinfo_out.dist
diff --git a/test/fuzzers/build.sh b/test/fuzzers/build.sh
new file mode 100755
index 00000000..c971a739
--- /dev/null
+++ b/test/fuzzers/build.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+# This script is meant to be run by
+# https://github.com/google/oss-fuzz/blob/master/projects/proj.4/Dockerfile
+
+set -e
+
+if [ "$SRC" == "" ]; then
+ echo "SRC env var not defined"
+ exit 1
+fi
+
+if [ "$OUT" == "" ]; then
+ echo "OUT env var not defined"
+ exit 1
+fi
+
+if [ "$CXX" == "" ]; then
+ echo "CXX env var not defined"
+ exit 1
+fi
+
+if [ "$LIB_FUZZING_ENGINE" = "" ]; then
+ export LIB_FUZZING_ENGINE=-lFuzzingEngine
+fi
+
+I386_PACKAGES="zlib1g-dev:i386 libssl-dev:i386 libsqlite3-dev:i386 \
+ libtiff5-dev:i386"
+X64_PACKAGES="zlib1g-dev libssl-dev libsqlite3-dev \
+ libtiff5-dev"
+
+if [ "$ARCHITECTURE" = "i386" ]; then
+ apt-get install -y $I386_PACKAGES
+else
+ apt-get install -y $X64_PACKAGES
+fi
+
+# build libcurl.a (builing against Ubuntu libcurl.a doesn't work easily)
+cd curl
+./buildconf
+./configure --disable-shared --prefix=$SRC/install
+make clean -s
+make -j$(nproc) -s
+make install
+cd ..
+
+./autogen.sh
+SQLITE3_CFLAGS=-I/usr/include SQLITE3_LIBS=-lsqlite3 TIFF_CFLAGS=-I/usr/include TIFF_LIBS=-ltiff ./configure --disable-shared --with-curl=$SRC/install/bin/curl-config
+make clean -s
+make -j$(nproc) -s
+
+EXTRA_LIBS="-lpthread -lsqlite3 -ltiff -Wl,-Bstatic -L$SRC/install/lib -lcurl -lssl -lcrypto -lz -Wl,-Bdynamic"
+
+build_fuzzer()
+{
+ fuzzerName=$1
+ sourceFilename=$2
+ shift
+ shift
+ echo "Building fuzzer $fuzzerName"
+ $CXX $CXXFLAGS -std=c++11 -fvisibility=hidden -Isrc -Iinclude \
+ $sourceFilename $* -o $OUT/$fuzzerName \
+ $LIB_FUZZING_ENGINE src/.libs/libproj.a $EXTRA_LIBS
+}
+
+build_fuzzer standard_fuzzer test/fuzzers/standard_fuzzer.cpp
+build_fuzzer proj_crs_to_crs_fuzzer test/fuzzers/proj_crs_to_crs_fuzzer.cpp
+
+echo "[libfuzzer]" > $OUT/standard_fuzzer.options
+echo "max_len = 10000" >> $OUT/standard_fuzzer.options
+
+echo "[libfuzzer]" > $OUT/proj_crs_to_crs_fuzzer.options
+echo "max_len = 10000" >> $OUT/proj_crs_to_crs_fuzzer.options
+
+cp -r data/* $OUT
diff --git a/test/fuzzers/build_google_oss_fuzzers.sh b/test/fuzzers/build_google_oss_fuzzers.sh
deleted file mode 100755
index cd9fed49..00000000
--- a/test/fuzzers/build_google_oss_fuzzers.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [ "$SRC" == "" ]; then
- echo "SRC env var not defined"
- exit 1
-fi
-
-if [ "$OUT" == "" ]; then
- echo "OUT env var not defined"
- exit 1
-fi
-
-if [ "$CXX" == "" ]; then
- echo "CXX env var not defined"
- exit 1
-fi
-
-SRC_DIR=$(dirname $0)/../..
-
-build_fuzzer()
-{
- fuzzerName=$1
- sourceFilename=$2
- shift
- shift
- echo "Building fuzzer $fuzzerName"
- $CXX $CXXFLAGS -std=c++11 -fvisibility=hidden -I$SRC_DIR/src -I$SRC_DIR/include \
- $sourceFilename $* -o $OUT/$fuzzerName \
- -lFuzzingEngine $SRC_DIR/src/.libs/libproj.a -lpthread /usr/lib/x86_64-linux-gnu/libsqlite3.a $EXTRA_LIBS
-}
-
-build_fuzzer standard_fuzzer $(dirname $0)/standard_fuzzer.cpp
-build_fuzzer proj_crs_to_crs_fuzzer $(dirname $0)/proj_crs_to_crs_fuzzer.cpp
-
-echo "[libfuzzer]" > $OUT/standard_fuzzer.options
-echo "max_len = 10000" >> $OUT/standard_fuzzer.options
-
-echo "[libfuzzer]" > $OUT/proj_crs_to_crs_fuzzer.options
-echo "max_len = 10000" >> $OUT/proj_crs_to_crs_fuzzer.options
diff --git a/test/fuzzers/build_seed_corpus.sh b/test/fuzzers/build_seed_corpus.sh
deleted file mode 100755
index cdd3cfc3..00000000
--- a/test/fuzzers/build_seed_corpus.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [ "$OUT" == "" ]; then
- echo "OUT env var not defined"
- exit 1
-fi
-
-SRC_DIR=$(dirname $0)/../..
-
-cp -r $SRC_DIR/data/* $OUT
diff --git a/test/fuzzers/proj_crs_to_crs_fuzzer.cpp b/test/fuzzers/proj_crs_to_crs_fuzzer.cpp
index 9b4b1ed9..a23cc0d9 100644
--- a/test/fuzzers/proj_crs_to_crs_fuzzer.cpp
+++ b/test/fuzzers/proj_crs_to_crs_fuzzer.cpp
@@ -34,7 +34,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include "proj_internal.h" // For pj_gc_unloadall()
#include "proj.h"
/* Standalone build:
@@ -47,7 +46,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len);
int LLVMFuzzerInitialize(int* /*argc*/, char*** argv)
{
const char* argv0 = (*argv)[0];
- char* path = pj_strdup(argv0);
+ char* path = strdup(argv0);
char* lastslash = strrchr(path, '/');
if( lastslash )
{
@@ -96,8 +95,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
proj_create_crs_to_crs(nullptr, first_line, second_line, nullptr));
free(buf_dup);
- pj_gc_unloadall(pj_get_default_ctx());
- pj_deallocate_grids();
+ proj_cleanup();
return 0;
}
diff --git a/test/gie/geotiff_grids.gie b/test/gie/geotiff_grids.gie
index 62a5b16d..a0d2a05b 100644
--- a/test/gie/geotiff_grids.gie
+++ b/test/gie/geotiff_grids.gie
@@ -160,7 +160,40 @@ operation +proj=vgridshift +grids=tests/test_vgrid_unsupported_byte.tif +multi
expect failure errno failed_to_load_grid
-------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
+operation +proj=vgridshift +grids=tests/us_noaa_geoid06_ak_subset_at_antimeridian.tif +multiplier=1
+-------------------------------------------------------------------------------
+tolerance 1 mm
+
+accept 179.99 54.5 0
+expect 179.99 54.5 -2.2226
+
+accept -179.99 54.5 0
+expect -179.99 54.5 -2.3488
+
+accept 179.999999 54.5 0
+expect 179.999999 54.5 -2.2872
+
+accept -179.999999 54.5 0
+expect -179.999999 54.5 -2.2872
+
+accept 179.8 54.5 0
+expect 179.8 54.5 -0.7011
+
+accept 179.799 54.5 0
+expect failure errno grid_area
+
+accept 180.1833333 54.5 0
+expect -179.8166667 54.5 -3.1933
+
+accept -179.8166667 54.5 0
+expect -179.8166667 54.5 -3.1933
+
+accept 180.184 54.5 0
+expect failure errno grid_area
+accept -179.816 54.5 0
+expect failure errno grid_area
-------------------------------------------------------------------------------
operation +proj=hgridshift +grids=tests/test_hgrid.tif
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index fd38847c..cc780be1 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -7968,6 +7968,24 @@ TEST(io, projparse_cea_ellipsoidal) {
// ---------------------------------------------------------------------------
+TEST(io, projparse_cea_ellipsoidal_with_k_0) {
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=cea +ellps=GRS80 +k_0=0.99 +type=crs");
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ WKTFormatterNNPtr f(WKTFormatter::create());
+ f->simulCurNodeHasId();
+ f->setMultiLine(false);
+ crs->exportToWKT(f.get());
+ auto wkt = f->toString();
+ EXPECT_TRUE(
+ wkt.find("PARAMETER[\"Latitude of 1st standard parallel\",8.1365") !=
+ std::string::npos)
+ << wkt;
+}
+
+// ---------------------------------------------------------------------------
+
TEST(io, projparse_geos_sweep_x) {
auto obj = PROJStringParser().createFromPROJString(
"+proj=geos +sweep=x +h=1 +type=crs");