[Git][debian-gis-team/geos][upstream] New upstream version 3.14.1
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Mon Oct 27 16:51:48 GMT 2025
Bas Couwenberg pushed to branch upstream at Debian GIS Project / geos
Commits:
5a46899f by Bas Couwenberg at 2025-10-27T17:04:46+01:00
New upstream version 3.14.1
- - - - -
15 changed files:
- CMakeLists.txt
- NEWS.md
- Version.txt
- include/geos/geom/Quadrant.h
- release.md
- src/algorithm/CircularArcs.cpp
- src/coverage/CoverageRingEdges.cpp
- src/geom/CoordinateSequence.cpp
- src/operation/grid/Grid.cpp
- tests/unit/CMakeLists.txt
- tests/unit/algorithm/CircularArcsTest.cpp
- + tests/unit/geom/QuadrantTest.cpp
- tests/unit/utility.h
- util/geosop/GeometryOp.cpp
- util/geosop/GeosOp.cpp
Changes:
=====================================
CMakeLists.txt
=====================================
@@ -558,3 +558,10 @@ if(PROJECT_IS_TOP_LEVEL)
unset(_is_multi_config_generator)
endif() # PROJECT_IS_TOP_LEVEL
+
+include(CheckIncludeFile)
+check_include_file(fenv.h HAVE_FENV_H)
+
+if(HAVE_FENV_H)
+ target_compile_definitions(geos_cxx_flags INTERFACE HAVE_FENV)
+endif()
=====================================
NEWS.md
=====================================
@@ -1,3 +1,14 @@
+
+## Changes in 3.14.1
+2025-10-27
+
+- Fixes/Improvements:
+ - Make floating-point exceptions optional for geosop (GH-1305, Maxim Kochetkov)
+ - Fix undefined behaviour in CoordinateSequence::closeRing (GH-1309, Paul Ramsey)
+ - GridIntersection: Fix crash for certain polygons outside grid extent (Dan Baston)
+ - Fix incorrect envelope calculation for arcs (GH-1314, Dan Baston)
+
+
## Changes in 3.14.0
2025-08-21
=====================================
Version.txt
=====================================
@@ -2,7 +2,7 @@
# GEOS Versions
GEOS_VERSION_MAJOR=3
GEOS_VERSION_MINOR=14
-GEOS_VERSION_PATCH=0
+GEOS_VERSION_PATCH=1
# OPTIONS: "", "dev", "rc1" etc.
GEOS_PATCH_WORD=
@@ -16,7 +16,7 @@ GEOS_PATCH_WORD=
# ( THIS MUST BE CAREFULLY AVOIDED )
#
CAPI_INTERFACE_CURRENT=21
-CAPI_INTERFACE_REVISION=4
+CAPI_INTERFACE_REVISION=5
CAPI_INTERFACE_AGE=20
# JTS Port
=====================================
include/geos/geom/Quadrant.h
=====================================
@@ -119,6 +119,24 @@ public:
}
};
+ /** Return a measure that increases monotonically with counterclockwise
+ * angle and avoids trigonometric calculations. Values are consistent
+ * with the numeric quadrant codes
+ *
+ * @param p0 circle center coordinate
+ * @param p1 coordinate for which pseudoangle should be calculated
+ */
+ static double pseudoAngle(const CoordinateXY& p0, const CoordinateXY& p1)
+ {
+ const double dx = p1.x - p0.x;
+ const double dy = p1.y - p0.y;
+
+ const double k = dx / (std::abs(dx) + std::abs(dy));
+ const double w = 2 + (dy > 0 ? 3 - k : 1 + k);
+
+ return w >= 4 ? w - 4 : w;
+ }
+
/**
* Returns true if the quadrants are 1 and 3, or 2 and 4
*/
=====================================
release.md
=====================================
@@ -1,38 +1,10 @@
-2025-08-21
-- New things:
- - Add clustering functions to C API (GH-1154, Dan Baston)
- - Ported LineDissolver (Paul Ramsey)
- - Ported CoverageCleaner (Paul Ramsey)
- - Add GEOSGridIntersectionFractions to C API (GH-1295, Dan Baston)
- - Add functions to interrupt processing in a specific thread/context (GH-803, Dan Baston)
- - Add "geos-targets.cmake" to build tree to allow building other software against
- GEOS build without installing first (GH-1269, Dan Baston)
- - Add GEOSCoordSeq_hasZ, GEOSCoordSeq_hasM (GH-1256, Aurele Ferotin)
- - Add GEOSCoordSeq_createWithDimensions, GEOSCoordSeq_setM, GEOSCoordSeq_getM (GH-1246, Dan Baston)
- - Add GEOSGeoJSONWriter_setOutputDimension (GH-1260, Aurele Ferotin)
- - Add GEOSGeom_transformXYZ (GH-1157, Aurele Ferotin)
- - Add GEOSisSimpleDetail (GH-1296, Dan Baston)
-
-- Breaking Changes:
- - C++17 is now required (GH-1144)
- - Stricter WKT parsing (GH-1241, @freemine)
- - GEOSCoordSeq_setOrdinate returns an error if the sequence does not have the specified ordinate (GH-1245, Dan Baston)
+2025-10-27
- Fixes/Improvements:
- - Fix ConcaveHullOfPolygons nested shell handling (GH-1169, Martin Davis)
- - Fix RelateNG for computing IM for empty-nonempty cases (Martin Davis)
- - Fix TopologyPreservingSimplifier/TaggedLineString to avoid jumping components (JTS-1096, Martin Davis)
- - Fix WKTWriter for small precisions and with trim enabled (GH-1199, Mike Taves)
- - Fix BufferOp to increase length of segments removed by heuristic (GH-1200, Martin Davis)
- - Improve RelateNG performance for A/L cases in prepared predicates (GH-1201, Martin Davis)
- - Improve OffsetCurve to handle mitre joins for polygons (Martin Davis)
- - Fix inscribed circle initialization (GH-1225, Benoit Maurin)
- - Fix overlay heuristic for GeometryCollections with empty elements (GH-1229, Martin Davis)
- - Add ring buffer hole removal heuristic (GH-1233, Martin Davis)
- - Fix buffer element erosion for negative distance and remove overlay deps (GH-1239, Martin Davis)
- - Fix OverlayNG coordinate dimension handling for EMPTY geometries (GH-1258, Martin Davis)
- - Fix DepthSegment comparison logic (really this time) (GH-1266, Martin Davis)
- - Change CoverageGapFinder to return polygons (Martin Davis)
- - Update DiscreteFrechetDistance to new algorithm (GH-1274, Paul Ramsey)
+ - Make floating-point exceptions optional for geosop (GH-1305, Maxim Kochetkov)
+ - Fix undefined behaviour in CoordinateSequence::closeRing (GH-1309, Paul Ramsey)
+ - GridIntersection: Fix crash for certain polygons outside grid extent (Dan Baston)
+ - Fix incorrect envelope calculation for arcs (GH-1314, Dan Baston)
+
=====================================
src/algorithm/CircularArcs.cpp
=====================================
@@ -57,6 +57,8 @@ void
CircularArcs::expandEnvelope(geom::Envelope& e, const geom::CoordinateXY& p0, const geom::CoordinateXY& p1,
const geom::CoordinateXY& p2)
{
+ using geom::Quadrant;
+
e.expandToInclude(p0);
e.expandToInclude(p1);
e.expandToInclude(p2);
@@ -73,22 +75,24 @@ CircularArcs::expandEnvelope(geom::Envelope& e, const geom::CoordinateXY& p0, co
return;
}
- auto orientation = Orientation::index(center, p0, p1);
-
//* 1 | 0
//* --+--
//* 2 | 3
+ const auto pa0 = Quadrant::pseudoAngle(center, p0);
+ const auto pa1 = Quadrant::pseudoAngle(center, p1);
+ const auto pa2 = Quadrant::pseudoAngle(center, p2);
- using geom::Quadrant;
-
- auto q0 = geom::Quadrant::quadrant(center, p0);
- auto q2 = geom::Quadrant::quadrant(center, p2);
+ auto q0 = static_cast<int>(pa0);
+ auto q2 = static_cast<int>(pa2);
double R = center.distance(p1);
if (q0 == q2) {
- // Start and end quadrants are the same. Either the arc crosses all of
+ // Start and end quadrants are the same. Either the arc crosses all
// the axes, or none of the axes.
- if (Orientation::index(center, p1, p2) != orientation) {
+
+ const bool isBetween = pa1 > std::min(pa0, pa2) && pa1 < std::max(pa0, pa2);
+
+ if (!isBetween) {
e.expandToInclude({center.x, center.y + R});
e.expandToInclude({center.x - R, center.y});
e.expandToInclude({center.x, center.y - R});
@@ -98,6 +102,8 @@ CircularArcs::expandEnvelope(geom::Envelope& e, const geom::CoordinateXY& p0, co
return;
}
+ auto orientation = Orientation::index(p0, p1, p2);
+
if (orientation == Orientation::CLOCKWISE) {
std::swap(q0, q2);
}
=====================================
src/coverage/CoverageRingEdges.cpp
=====================================
@@ -13,7 +13,7 @@
*
**********************************************************************/
-#include <map>
+#include <unordered_map>
#include <geos/coverage/CoverageBoundarySegmentFinder.h>
#include <geos/coverage/CoverageEdge.h>
=====================================
src/geom/CoordinateSequence.cpp
=====================================
@@ -261,9 +261,10 @@ void
CoordinateSequence::closeRing(bool allowRepeated)
{
if(!isEmpty() && (allowRepeated || front<CoordinateXY>() != back<CoordinateXY>())) {
- m_vect.insert(m_vect.end(),
- m_vect.begin(),
- std::next(m_vect.begin(), stride()));
+ const std::size_t n = stride();
+ const std::size_t old = m_vect.size();
+ m_vect.resize(old + n);
+ std::copy_n(m_vect.data(), n, m_vect.data() + old);
}
}
=====================================
src/operation/grid/Grid.cpp
=====================================
@@ -63,7 +63,7 @@ Grid<infinite_extent>::getCellEnvelope(size_t row, size_t col) const
}
if (row == 0) {
- cell_ymax = std::max(xmax() + PADDED_CELL_SIZE, m_domain.getMaxX());
+ cell_ymax = std::max(ymax() + PADDED_CELL_SIZE, m_domain.getMaxY());
} else if (row == getNumRows() - 1) {
cell_ymax = ymin(); // because bottom row of regular may have different height from others
} else {
=====================================
tests/unit/CMakeLists.txt
=====================================
@@ -14,6 +14,35 @@ file(GLOB_RECURSE _sources ${CMAKE_CURRENT_LIST_DIR}/*.cpp CONFIGURE_DEPEND)
add_executable(test_geos_unit ${_sources})
unset(_sources)
+# test that std::filesystem header actually is there and works
+if(NOT CMAKE_REQUIRED_QUIET)
+ # CMake 3.17+ use CHECK_START/CHECK_PASS/CHECK_FAIL
+ message(STATUS "Checking if compiler supports std::filesystem")
+endif()
+set(_filename "${CMAKE_CURRENT_BINARY_DIR}/has_filesystem.cpp")
+write_file(${_filename} "\
+#include <filesystem>
+int main() {
+ std::filesystem::path pth {\"../\"};
+ return 0;
+}")
+try_compile(HAVE_STD_FILESYSTEM "${CMAKE_BINARY_DIR}/temp" "${_filename}")
+file(REMOVE "${_filename}")
+unset(_filename)
+if(HAVE_STD_FILESYSTEM)
+ if(NOT CMAKE_REQUIRED_QUIET)
+ # CMake 3.17+ use CHECK_START/CHECK_PASS/CHECK_FAIL
+ message(STATUS "Checking if compiler supports std::filesystem - yes")
+ endif()
+ target_compile_definitions(test_geos_unit PRIVATE HAVE_STD_FILESYSTEM)
+else()
+ if(NOT CMAKE_REQUIRED_QUIET)
+ # CMake 3.17+ use CHECK_START/CHECK_PASS/CHECK_FAIL
+ message(STATUS "Checking if compiler supports std::filesystem - no")
+ endif()
+ target_compile_definitions(test_geos_unit PRIVATE HAVE_STD_FILESYSTEM=0)
+endif()
+
find_package(Threads)
target_link_libraries(test_geos_unit PRIVATE geos geos_c Threads::Threads)
=====================================
tests/unit/algorithm/CircularArcsTest.cpp
=====================================
@@ -215,5 +215,19 @@ void object::test<13>()
3, 4, 3, 4);
}
+template<>
+template<>
+void object::test<14>()
+{
+ set_test_name("envelope: GH #1313");
+
+ CoordinateXY p0{2, 0};
+ CoordinateXY p1{4, 2};
+ CoordinateXY p2{2, 1};
+
+ checkEnvelope(p0, p1, p2,
+ 2, -1.0811388300841898, 5.08113883008419,2.08113883008419);
+}
+
}
=====================================
tests/unit/geom/QuadrantTest.cpp
=====================================
@@ -0,0 +1,83 @@
+#include <tut/tut.hpp>
+
+#include <geos/geom/Quadrant.h>
+
+using geos::geom::Quadrant;
+
+namespace tut {
+
+struct test_quadrant_data {
+
+ static std::string quadrantName(int quadrant) {
+ switch (quadrant) {
+ case Quadrant::NE: return "NE";
+ case Quadrant::NW: return "NW";
+ case Quadrant::SE: return "SE";
+ case Quadrant::SW: return "SW";
+ }
+ return "unknown";
+ }
+
+ static void checkQuadrant(double dx, double dy, int expected) {
+ int quadrant = Quadrant::quadrant({0, 0}, {dx, dy});
+ ensure_equals(quadrant, expected);
+ }
+
+ static void checkPseudoAngleMatchesQuadrant(double dx, double dy) {
+ int quadrant = Quadrant::quadrant({0, 0}, {dx, dy});
+ double pa = Quadrant::pseudoAngle({0, 0}, {dx, dy});
+
+ if (quadrant != static_cast<int>(pa)) {
+ std::stringstream ss;
+ ss << "relative coordinate (" << dx << ", " << dy << ") expected to be in quadrant " << quadrantName(quadrant) << " but pseudoAngle " << pa << " corresponds to quadrant " << quadrantName(static_cast<int>(pa));
+ fail(ss.str());
+ }
+
+ ensure_equals(quadrant, static_cast<int>(pa));
+ }
+};
+
+typedef test_group<test_quadrant_data> group;
+typedef group::object object;
+
+group test_quadrant_group("geos::geom::Quadrant");
+
+template<>
+template<>
+void object::test<1>()
+{
+ checkQuadrant(1, 1, Quadrant::NE);
+ checkQuadrant(1, -1, Quadrant::SE);
+ checkQuadrant(-1, -1, Quadrant::SW);
+ checkQuadrant(-1, 1, Quadrant::NW);
+}
+
+template<>
+template<>
+void object::test<2>()
+{
+ static constexpr double eps = 1e-8;
+
+ // center of each quadrant
+ checkPseudoAngleMatchesQuadrant(1, 1);
+ checkPseudoAngleMatchesQuadrant(1, -1);
+ checkPseudoAngleMatchesQuadrant(-1, -1);
+ checkPseudoAngleMatchesQuadrant(-1, 1);
+
+ // near axes
+ checkPseudoAngleMatchesQuadrant(1, eps); // +X
+ checkPseudoAngleMatchesQuadrant(1, -eps); // +X
+ checkPseudoAngleMatchesQuadrant(eps, 1); // +Y
+ checkPseudoAngleMatchesQuadrant(-eps, 1); // +Y
+ checkPseudoAngleMatchesQuadrant(-1, eps); // +X
+ checkPseudoAngleMatchesQuadrant(-1, -eps); // +X
+ checkPseudoAngleMatchesQuadrant(eps, -1); // -Y
+ checkPseudoAngleMatchesQuadrant(-eps, -1); // -Y
+
+ // axes
+ checkPseudoAngleMatchesQuadrant(1, 0); // +X
+ //checkPseudoAngleMatchesQuadrant(0, 1); // +Y
+ //checkPseudoAngleMatchesQuadrant(-1, 0); // +X
+ //checkPseudoAngleMatchesQuadrant(0, -1); // -Y
+}
+}
=====================================
tests/unit/utility.h
=====================================
@@ -33,11 +33,13 @@
#include <fstream>
#include <sstream>
+#ifndef HAVE_STD_FILESYSTEM
#if defined(__GNUC__) && !defined(__clang__)
#define HAVE_STD_FILESYSTEM (__GNUC__ > 8)
#else
#define HAVE_STD_FILESYSTEM 1
#endif
+#endif /* ifndef HAVE_STD_FILESYSTEM */
#if HAVE_STD_FILESYSTEM
#include <filesystem>
#endif
=====================================
util/geosop/GeometryOp.cpp
=====================================
@@ -238,7 +238,7 @@ std::vector<GeometryOpCreator> opRegistry {
catMetric, "area of geometry",
Result::typeDouble,
[](const Geometry& geom) {
- return new Result( geom.convexHull() );
+ return new Result( geom.getArea() );
});
}},
{"length", [](std::string name) { return GeometryOp::create(name,
=====================================
util/geosop/GeosOp.cpp
=====================================
@@ -26,7 +26,9 @@
#include <geos/io/WKBStreamReader.h>
#include <geos/io/WKBWriter.h>
+#if defined(HAVE_FENV)
#include <cfenv>
+#endif
#include <fstream>
#include <iostream>
#include <sstream>
@@ -394,10 +396,13 @@ void GeosOp::run(OpArguments& opArgs) {
//------------------------
try {
+#if defined(HAVE_FENV)
std::feclearexcept(FE_ALL_EXCEPT); // clear floating-point status flags
+#endif
execute(op, opArgs);
+#if defined(HAVE_FENV)
// Catch everything except for FE_INEXACT, which is usually harmless
const int fpexp = std::fetestexcept(FE_ALL_EXCEPT ^ FE_INEXACT);
if (args.isVerbose && (fpexp != 0)) {
@@ -414,6 +419,7 @@ void GeosOp::run(OpArguments& opArgs) {
std::cerr << " FE_UNDERFLOW";
std::cerr << std::endl;
}
+#endif
}
catch (std::exception &e) {
std::cerr << "Run-time exception: " << e.what() << std::endl;
View it on GitLab: https://salsa.debian.org/debian-gis-team/geos/-/commit/5a46899f7c09f4b7aa2a11fff12a31fa3e9d3a75
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/geos/-/commit/5a46899f7c09f4b7aa2a11fff12a31fa3e9d3a75
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20251027/c585827d/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list