diff options
| -rw-r--r-- | docs/source/install.rst | 24 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 20 | ||||
| -rw-r--r-- | src/Makefile.am | 6 | ||||
| -rw-r--r-- | src/bin_gie.cmake | 6 | ||||
| -rw-r--r-- | src/check_md5sum.cmake | 7 | ||||
| -rw-r--r-- | src/generate_wkt_parser.cmake | 18 | ||||
| -rw-r--r-- | src/iso19111/c_api.cpp | 7 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 47 | ||||
| -rw-r--r-- | src/iso19111/operation/parammappings.cpp | 5 | ||||
| -rw-r--r-- | src/lib_proj.cmake | 54 | ||||
| -rwxr-xr-x | test/fuzzers/build.sh | 16 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 31 |
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); |
