aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/install.rst24
-rw-r--r--src/CMakeLists.txt20
-rw-r--r--src/Makefile.am6
-rw-r--r--src/bin_gie.cmake6
-rw-r--r--src/check_md5sum.cmake7
-rw-r--r--src/generate_wkt_parser.cmake18
-rw-r--r--src/iso19111/c_api.cpp7
-rw-r--r--src/iso19111/io.cpp47
-rw-r--r--src/iso19111/operation/parammappings.cpp5
-rw-r--r--src/lib_proj.cmake54
-rwxr-xr-xtest/fuzzers/build.sh16
-rw-r--r--test/unit/test_io.cpp31
12 files changed, 201 insertions, 40 deletions
diff --git a/docs/source/install.rst b/docs/source/install.rst
index 73cc6e00..208b55d4 100644
--- a/docs/source/install.rst
+++ b/docs/source/install.rst
@@ -322,33 +322,43 @@ CMake configure options
Options to configure a CMake are provided using ``-D<var>=<value>``.
All cached entries can be viewed using ``cmake -LAH`` from a build directory.
+.. option:: BUILD_APPS=ON
+
+ Build PROJ applications. Default is ON. Control the default value for
+ BUILD_CCT, BUILD_CS2CS, BUILD_GEOD, BUILD_GIE, BUILD_PROJ, BUILD_PROJINFO
+ and BUILD_PROJSYNC.
+ Note that changing its value after having configured once will not change
+ the value of the individual BUILD_CCT, ... options.
+
+ .. versionchanged:: 8.2
+
.. option:: BUILD_CCT=ON
- Build :ref:`cct`, default ON.
+ Build :ref:`cct`, default is the value of BUILD_APPS.
.. option:: BUILD_CS2CS=ON
- Build :ref:`cs2cs`, default ON.
+ Build :ref:`cs2cs`,default is the value of BUILD_APPS.
.. option:: BUILD_GEOD=ON
- Build :ref:`geod`, default ON.
+ Build :ref:`geod`, default is the value of BUILD_APPS.
.. option:: BUILD_GIE=ON
- Build :ref:`gie`, default ON.
+ Build :ref:`gie`, default is the value of BUILD_APPS.
.. option:: BUILD_PROJ=ON
- Build :ref:`proj`, default ON.
+ Build :ref:`proj`, default is the value of BUILD_APPS.
.. option:: BUILD_PROJINFO=ON
- Build :ref:`projinfo`, default ON.
+ Build :ref:`projinfo`, default is the value of BUILD_APPS.
.. option:: BUILD_PROJSYNC=ON
- Build :ref:`projsync`, default ON.
+ Build :ref:`projsync`, default is the value of BUILD_APPS.
.. option:: BUILD_SHARED_LIBS
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 534bc311..311cdbac 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,20 +3,23 @@
include(lib_proj.cmake)
# configure executable build
+option(BUILD_APPS
+ "Build PROJ applications (default value for BUILD_CCT, BUILD_CS2CS, etc.)" ON)
+
option(BUILD_CCT
- "Build cct (coordinate conversion and transformation tool)" ON)
+ "Build cct (coordinate conversion and transformation tool)" "${BUILD_APPS}")
option(BUILD_CS2CS
- "Build cs2cs (coordinate systems to coordinate systems translation tool)" ON)
+ "Build cs2cs (coordinate systems to coordinate systems translation tool)" "${BUILD_APPS}")
option(BUILD_GEOD
- "Build geod (computation of geodesic lines)" ON)
+ "Build geod (computation of geodesic lines)" "${BUILD_APPS}")
option(BUILD_GIE
- "Build gie (geospatial integrity investigation environment)" ON)
+ "Build gie (geospatial integrity investigation environment)" "${BUILD_APPS}")
option(BUILD_PROJ
- "Build proj (cartographic projection tool)" ON)
+ "Build proj (cartographic projection tool)" "${BUILD_APPS}")
option(BUILD_PROJINFO
- "Build projinfo (SRS and coordinate operation metadata/query tool)" ON)
+ "Build projinfo (SRS and coordinate operation metadata/query tool)" "${BUILD_APPS}")
option(BUILD_PROJSYNC
- "Build projsync (synchronize transformation support data)" ON)
+ "Build projsync (synchronize transformation support data)" "${BUILD_APPS}")
if(NOT MSVC)
@@ -69,7 +72,8 @@ if(BUILD_PROJINFO)
set(BIN_TARGETS ${BIN_TARGETS} binprojinfo)
endif()
-if(BUILD_GIE)
+# Always build gie if testing is requested
+if(BUILD_GIE OR BUILD_TESTING)
include(bin_gie.cmake)
set(BIN_TARGETS ${BIN_TARGETS} gie)
endif()
diff --git a/src/Makefile.am b/src/Makefile.am
index f58e7602..1e847080 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,7 +14,11 @@ include_HEADERS = proj.h proj_experimental.h proj_constants.h geodesic.h \
EXTRA_DIST = bin_cct.cmake bin_gie.cmake bin_cs2cs.cmake \
bin_geod.cmake bin_proj.cmake bin_projinfo.cmake \
- lib_proj.cmake CMakeLists.txt bin_geodtest.cmake \
+ lib_proj.cmake \
+ check_md5sum.cmake \
+ generate_wkt_parser.cmake \
+ CMakeLists.txt \
+ bin_geodtest.cmake \
bin_projsync.cmake \
tests/geodtest.cpp \
wkt1_grammar.y wkt2_grammar.y apps/emess.h apps/utils.h \
diff --git a/src/bin_gie.cmake b/src/bin_gie.cmake
index a26ead3e..6ad7d4ab 100644
--- a/src/bin_gie.cmake
+++ b/src/bin_gie.cmake
@@ -11,8 +11,10 @@ add_executable(gie ${GIE_SRC} ${GIE_INCLUDE})
target_link_libraries(gie PRIVATE ${PROJ_LIBRARIES})
target_compile_options(gie PRIVATE ${PROJ_CXX_WARN_FLAGS})
-install(TARGETS gie
- DESTINATION ${BINDIR})
+if(BUILD_GIE)
+ install(TARGETS gie
+ DESTINATION ${BINDIR})
+endif()
if(MSVC AND BUILD_SHARED_LIBS)
target_compile_definitions(gie PRIVATE PROJ_MSVC_DLL_IMPORT=1)
diff --git a/src/check_md5sum.cmake b/src/check_md5sum.cmake
new file mode 100644
index 00000000..bab6fc6f
--- /dev/null
+++ b/src/check_md5sum.cmake
@@ -0,0 +1,7 @@
+file(READ "${IN_FILE}" CONTENTS)
+
+string(MD5 MD5SUM "${CONTENTS}")
+
+if(NOT("${MD5SUM}" STREQUAL "${EXPECTED_MD5SUM}"))
+ message(FATAL_ERROR "File ${IN_FILE} has been modified. target ${TARGET} should be manually run. And lib_proj.cmake should be updated with \"${MD5SUM}\"")
+endif()
diff --git a/src/generate_wkt_parser.cmake b/src/generate_wkt_parser.cmake
new file mode 100644
index 00000000..bcfc09be
--- /dev/null
+++ b/src/generate_wkt_parser.cmake
@@ -0,0 +1,18 @@
+message("Generating ${OUT_FILE}")
+
+execute_process(COMMAND "bison" "--no-lines" "-d" "-p" "${PREFIX}" "-o${OUT_FILE}" "${IN_FILE}"
+ RESULT_VARIABLE STATUS)
+
+if(STATUS AND NOT STATUS EQUAL 0)
+ message(FATAL_ERROR "bison failed")
+endif()
+
+# Post processing of the generated file
+# All those replacements are to please MSVC
+file(READ ${OUT_FILE} CONTENTS)
+string(REPLACE "yyerrorlab:" "#if 0\nyyerrorlab:" CONTENTS "${CONTENTS}")
+string(REPLACE "yyerrlab1:" "#endif\nyyerrlab1:" CONTENTS "${CONTENTS}")
+string(REPLACE "for (yylen = 0; yystr[yylen]; yylen++)" "for (yylen = 0; yystr && yystr[yylen]; yylen++)" CONTENTS "${CONTENTS}")
+string(REPLACE "return yystpcpy (yyres, yystr) - yyres;" "return (YYPTRDIFF_T)(yystpcpy (yyres, yystr) - yyres);" CONTENTS "${CONTENTS}")
+string(REPLACE "YYPTRDIFF_T yysize = yyssp - yyss + 1;" "YYPTRDIFF_T yysize = (YYPTRDIFF_T)(yyssp - yyss + 1);" CONTENTS "${CONTENTS}")
+file(WRITE "${OUT_FILE}" "${CONTENTS}")
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 9493452c..acf36402 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -8479,7 +8479,12 @@ PJ *proj_crs_get_datum_forced(PJ_CONTEXT *ctx, const PJ *crs) {
const auto &datumEnsemble = l_crs->datumEnsemble();
assert(datumEnsemble);
auto dbContext = getDBcontextNoException(ctx, __FUNCTION__);
- return pj_obj_create(ctx, datumEnsemble->asDatum(dbContext));
+ try {
+ return pj_obj_create(ctx, datumEnsemble->asDatum(dbContext));
+ } catch (const std::exception &e) {
+ proj_log_debug(ctx, __FUNCTION__, e.what());
+ return nullptr;
+ }
}
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 24201ee1..9ce642e7 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -3800,6 +3800,39 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
tryToIdentifyWKT1Method ? getMappingFromWKT1(projectionName) : nullptr;
if (mapping) {
mapping = selectSphericalOrEllipsoidal(mapping, baseGeodCRS);
+ } else if (metadata::Identifier::isEquivalentName(
+ projectionName.c_str(), "Lambert Conformal Conic")) {
+ // Lambert Conformal Conic or Lambert_Conformal_Conic are respectively
+ // used by Oracle WKT and Trimble for either LCC 1SP or 2SP, so we
+ // have to look at parameters to figure out the variant.
+ bool found2ndStdParallel = false;
+ bool foundScaleFactor = false;
+ for (const auto &childNode : projCRSNode->GP()->children()) {
+ if (ci_equal(childNode->GP()->value(), WKTConstants::PARAMETER)) {
+ const auto &childNodeChildren = childNode->GP()->children();
+ if (childNodeChildren.size() < 2) {
+ ThrowNotEnoughChildren(WKTConstants::PARAMETER);
+ }
+ const std::string wkt1ParameterName(
+ stripQuotes(childNodeChildren[0]));
+ if (metadata::Identifier::isEquivalentName(
+ wkt1ParameterName.c_str(), WKT1_STANDARD_PARALLEL_2)) {
+ found2ndStdParallel = true;
+ } else if (metadata::Identifier::isEquivalentName(
+ wkt1ParameterName.c_str(), WKT1_SCALE_FACTOR)) {
+ foundScaleFactor = true;
+ }
+ }
+ }
+ if (found2ndStdParallel && !foundScaleFactor) {
+ mapping = getMapping(EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP);
+ } else if (!found2ndStdParallel && foundScaleFactor) {
+ mapping = getMapping(EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_1SP);
+ } else if (found2ndStdParallel && foundScaleFactor) {
+ // Not sure if that happens
+ mapping = getMapping(
+ EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN);
+ }
}
// For Krovak, we need to look at axis to decide between the Krovak and
@@ -3833,7 +3866,7 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
}
foundParameters.resize(countParams);
}
- bool found2ndStdParallel = false;
+
for (const auto &childNode : projCRSNode->GP()->children()) {
if (ci_equal(childNode->GP()->value(), WKTConstants::PARAMETER)) {
const auto &childNodeChildren = childNode->GP()->children();
@@ -3886,10 +3919,6 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
propertiesParameter.set(Identifier::CODESPACE_KEY,
Identifier::EPSG);
}
- if (paramMapping->epsg_code ==
- EPSG_CODE_PARAMETER_LATITUDE_2ND_STD_PARALLEL) {
- found2ndStdParallel = true;
- }
}
propertiesParameter.set(IdentifiedObject::NAME_KEY, parameterName);
parameters.push_back(
@@ -3906,14 +3935,6 @@ ConversionNNPtr WKTParser::Private::buildProjectionStandard(
}
}
- // Oracle WKT: make sure that the 2nd std parallel parameter is found to
- // select the LCC_2SP mapping
- if (metadata::Identifier::isEquivalentName(wkt1ProjectionName.c_str(),
- "Lambert Conformal Conic") &&
- !found2ndStdParallel) {
- propertiesMethod.set(IdentifiedObject::NAME_KEY, wkt1ProjectionName);
- }
-
// Add back important parameters that should normally be present, but
// are sometimes missing. Currently we only deal with Scale factor at
// natural origin. This is to avoid a default value of 0 to slip in later.
diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp
index df5ae7c5..240a2b50 100644
--- a/src/iso19111/operation/parammappings.cpp
+++ b/src/iso19111/operation/parammappings.cpp
@@ -598,11 +598,6 @@ static const MethodMapping projectionMethodMappings[] = {
EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP,
"Lambert_Conformal_Conic_2SP", "lcc", nullptr, paramsLCC2SP},
- // Oracle WKT
- {EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP,
- EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP, "Lambert Conformal Conic",
- "lcc", nullptr, paramsLCC2SP},
-
{EPSG_NAME_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN,
EPSG_CODE_METHOD_LAMBERT_CONIC_CONFORMAL_2SP_MICHIGAN,
nullptr, // no mapping to WKT1_GDAL
diff --git a/src/lib_proj.cmake b/src/lib_proj.cmake
index 785ec6f0..4ece9094 100644
--- a/src/lib_proj.cmake
+++ b/src/lib_proj.cmake
@@ -298,6 +298,60 @@ source_group("CMake Files" FILES CMakeLists.txt)
# Embed PROJ_LIB data files location
add_definitions(-DPROJ_LIB="${CMAKE_INSTALL_PREFIX}/${DATADIR}")
+
+###########################################################
+# targets to refresh wkt1_parser.cpp and wkt2_parser.cpp
+###########################################################
+
+# Those targets need to be run manually each time wkt1_grammar.y / wkt2_grammar.y
+# is modified.
+# We could of course run them automatically, but that would make building
+# PROJ harder.
+
+# This target checks that wkt1_grammar.y md5sum has not changed
+# If it has, then it should be updated and the generate_wkt1_parser target
+# should be manually run
+add_custom_target(check_wkt1_grammar_md5 ALL
+ COMMAND ${CMAKE_COMMAND}
+ "-DIN_FILE=wkt1_grammar.y"
+ "-DTARGET=generate_wkt1_parser"
+ "-DEXPECTED_MD5SUM=3a1720c3fa1b759719e33dd558603efb"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check_md5sum.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/wkt1_grammar.y"
+ VERBATIM)
+
+add_custom_target(generate_wkt1_parser
+ COMMAND ${CMAKE_COMMAND}
+ "-DPREFIX=pj_wkt1_"
+ "-DIN_FILE=wkt1_grammar.y"
+ "-DOUT_FILE=wkt1_generated_parser.c"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_wkt_parser.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM)
+
+# This target checks that wkt2_grammar.y md5sum has not changed
+# If it has, then it should be updated and the generate_wkt2_parser target
+# should be manually run
+add_custom_target(check_wkt2_grammar_md5 ALL
+ COMMAND ${CMAKE_COMMAND}
+ "-DIN_FILE=wkt2_grammar.y"
+ "-DTARGET=generate_wkt2_parser"
+ "-DEXPECTED_MD5SUM=1691b7d213073d5a1b49db2e080bc96e"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check_md5sum.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/wkt2_grammar.y"
+ VERBATIM)
+
+add_custom_target(generate_wkt2_parser
+ COMMAND ${CMAKE_COMMAND}
+ "-DPREFIX=pj_wkt2_"
+ "-DIN_FILE=wkt2_grammar.y"
+ "-DOUT_FILE=wkt2_generated_parser.c"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/generate_wkt_parser.cmake"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+ VERBATIM)
+
#################################################
## targets: libproj and proj_config.h
#################################################
diff --git a/test/fuzzers/build.sh b/test/fuzzers/build.sh
index 54909fea..25c43fa2 100755
--- a/test/fuzzers/build.sh
+++ b/test/fuzzers/build.sh
@@ -50,10 +50,20 @@ make -j$(nproc)
make install
cd ..
-./autogen.sh
-SQLITE3_CFLAGS=-I/usr/include SQLITE3_LIBS=-lsqlite3 TIFF_CFLAGS=-I$SRC/install/include TIFF_LIBS="-L$SRC/install/lib -ltiff" ./configure --disable-shared --with-curl=$SRC/install/bin/curl-config
+mkdir build
+cd build
+cmake .. -DBUILD_SHARED_LIBS:BOOL=OFF \
+ -DCURL_INCLUDE_DIR:PATH="$SRC/install/include" \
+ -DCURL_LIBRARY_RELEASE:FILEPATH="$SRC/install/lib/libcurl.a" \
+ -DTIFF_INCLUDE_DIR:PATH="$SRC/install/include" \
+ -DTIFF_LIBRARY_RELEASE:FILEPATH="$SRC/install/lib/libtiff.a" \
+ -DCMAKE_INSTALL_PREFIX=$SRC/install \
+ -DBUILD_APPS:BOOL=OFF \
+ -DBUILD_TESTING:BOOL=OFF
make clean -s
make -j$(nproc) -s
+make install
+cd ..
EXTRA_LIBS="-lpthread -Wl,-Bstatic -lsqlite3 -L$SRC/install/lib -ltiff -lcurl -lssl -lcrypto -lz -Wl,-Bdynamic"
@@ -66,7 +76,7 @@ build_fuzzer()
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
+ $LIB_FUZZING_ENGINE "$SRC/install/lib/libproj.a" $EXTRA_LIBS
}
build_fuzzer proj_crs_to_crs_fuzzer test/fuzzers/proj_crs_to_crs_fuzzer.cpp
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 4e888f2c..196552d4 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -6394,6 +6394,37 @@ TEST(wkt_parse, wkt1_oracle) {
// ---------------------------------------------------------------------------
+TEST(wkt_parse, wkt1_lcc_1sp_without_1sp_suffix) {
+ // WKT from Trimble
+ auto wkt = "PROJCS[\"TWM-Madison Co LDP\","
+ "GEOGCS[\"WGS 1984\","
+ "DATUM[\"WGS 1984\","
+ "SPHEROID[\"World Geodetic System 1984\","
+ "6378137,298.257223563]],"
+ "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+ "UNIT[\"Degree\",0.01745329251994,"
+ "AUTHORITY[\"EPSG\",\"9102\"]],"
+ "AXIS[\"Long\",EAST],AXIS[\"Lat\",NORTH]],"
+ "PROJECTION[\"Lambert_Conformal_Conic\"],"
+ "PARAMETER[\"False_Easting\",103000.0000035],"
+ "PARAMETER[\"False_Northing\",79000.00007055],"
+ "PARAMETER[\"Latitude_Of_Origin\",38.83333333333],"
+ "PARAMETER[\"Central_Meridian\",-89.93333333333],"
+ "PARAMETER[\"Scale_Factor\",1.000019129],"
+ "UNIT[\"Foot_US\",0.3048006096012,AUTHORITY[\"EPSG\",\"9003\"]],"
+ "AXIS[\"East\",EAST],AXIS[\"North\",NORTH]]";
+
+ auto dbContext = DatabaseContext::create();
+ auto obj = WKTParser().attachDatabaseContext(dbContext).createFromWKT(wkt);
+ auto crs = nn_dynamic_pointer_cast<ProjectedCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+
+ EXPECT_EQ(crs->derivingConversion()->method()->nameStr(),
+ "Lambert Conic Conformal (1SP)");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(wkt_parse, invalid) {
EXPECT_THROW(WKTParser().createFromWKT(""), ParsingException);
EXPECT_THROW(WKTParser().createFromWKT("A"), ParsingException);