[Git][debian-gis-team/geos][upstream] New upstream version 3.10.2
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Sun Jan 16 07:52:26 GMT 2022
Bas Couwenberg pushed to branch upstream at Debian GIS Project / geos
Commits:
d4949261 by Bas Couwenberg at 2022-01-16T07:16:22+01:00
New upstream version 3.10.2
- - - - -
26 changed files:
- CMakeLists.txt
- NEWS
- README.md
- Version.txt
- include/geos/geom/CoordinateSequence.h
- include/geos/index/SpatialIndex.h
- include/geos/index/strtree/TemplateSTRtree.h
- include/geos/precision/CommonBitsRemover.h
- include/geos/triangulate/polygon/PolygonEarClipper.h
- include/geos/triangulate/polygon/PolygonHoleJoiner.h
- src/algorithm/construct/MaximumInscribedCircle.cpp
- − src/dirlist.mk
- src/geomgraph/Node.cpp
- src/index/chain/MonotoneChainBuilder.cpp
- src/io/GeoJSONWriter.cpp
- src/operation/polygonize/BuildArea.cpp
- src/operation/union/CascadedPolygonUnion.cpp
- src/triangulate/polygon/PolygonEarClipper.cpp
- tests/unit/algorithm/construct/MaximumInscribedCircleTest.cpp
- tests/unit/capi/GEOSPreparedGeometryTest.cpp
- tests/unit/capi/GEOSSTRtreeTest.cpp
- + tests/unit/geom/Geometry/differenceTest.cpp
- tests/unit/index/chain/MonotoneChainBuilderTest.cpp
- tests/unit/io/GeoJSONWriterTest.cpp
- tests/unit/triangulate/polygon/PolygonTriangulatorTest.cpp
- tests/xmltester/tests/general/TestUnaryUnion.xml
Changes:
=====================================
CMakeLists.txt
=====================================
@@ -368,6 +368,11 @@ install(DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/include/geos"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
+install(DIRECTORY
+ "${CMAKE_CURRENT_LIST_DIR}/include/geos"
+ "${CMAKE_CURRENT_BINARY_DIR}/include/geos"
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ FILES_MATCHING PATTERN "*.hpp")
if(NOT DISABLE_GEOS_INLINE)
install(DIRECTORY
"${CMAKE_CURRENT_LIST_DIR}/include/geos"
=====================================
NEWS
=====================================
@@ -1,3 +1,21 @@
+
+Changes in 3.10.2
+2022-01-15
+
+- Fixes/Improvements:
+ - Fix crash in MonotoneChain with empty CoordinateSequence (GH-539, Sandro Santilli)
+ - Fix crash in GeoJSONWriter in case of empty points (TRAC-1139, Paul Ramsey)
+ - Improve BuildArea performance (TRAC-1122, Sandro Santilli)
+ - Fix unaryUnion to avoid segfault with empty polygon (GH-501, Mike Taves)
+ - Fix memory leak on exception in prepared geometry (GH-506, Dan Baston)
+ - Iterator invalidation in rare cases (GH-508, Momtchil Momtchev)
+ - Infinite loop on collapsed input to MaximumInscribedCircle (Paul Ramsey)
+ - Write LinearRing to GeoJSON as LineString (TRAC-1140, Paul Ramsey)
+ - Fix PolygonEarClipper to handle collapsed corners (GH-526, Martin Davis)
+ - Fix GEOSSTRtree_remove for empty tree (GH-544, Dan Baston)
+ - Fix crash on query of STRtree with removed items (GH-545, Dan Baston)
+
+
Changes in 3.10.1
2021-11-2
=====================================
README.md
=====================================
@@ -1,16 +1,16 @@
GEOS -- Geometry Engine, Open Source
====================================
-GEOS is a C++11 library for performing operations on two-dimensional vector
+GEOS is a C++ library for performing operations on two-dimensional vector
geometries. It is primarily a port of the [JTS Topology
Suite](https://github.com/locationtech/jts) Java library. It provides many of
the algorithms used by [PostGIS](http://www.postgis.net/), the
[Shapely](https://pypi.org/project/Shapely/) package for Python, the
[sf](https://github.com/r-spatial/sf) package for R, and others.
-More information is available the [project homepage](https://trac.osgeo.org/geos).
+More information is available the [project homepage](https://libgeos.org).
-The official Git repository is at [OSGEO Gitea](https://git.osgeo.org/gitea/geos).
+The official Git repository is at [GitHub](https://github.com/libgeos/geos).
## Build status
=====================================
Version.txt
=====================================
@@ -2,7 +2,7 @@
# GEOS Versions
GEOS_VERSION_MAJOR=3
GEOS_VERSION_MINOR=10
-GEOS_VERSION_PATCH=1
+GEOS_VERSION_PATCH=2
# OPTIONS: "", "dev", "rc1" etc.
GEOS_PATCH_WORD=
=====================================
include/geos/geom/CoordinateSequence.h
=====================================
@@ -159,10 +159,9 @@ public:
static CoordinateSequence* atLeastNCoordinatesOrNothing(std::size_t n,
CoordinateSequence* c);
- /// Return position of a Coordinate, or -1 if not found
- ///
- /// FIXME: return std::size_t, using numeric_limits<std::size_t>::max
- /// as 'not found' value.
+ /// Return position of a Coordinate
+ //
+ /// or numeric_limits<std::size_t>::max() if not found
///
static std::size_t indexOf(const Coordinate* coordinate,
const CoordinateSequence* cl);
=====================================
include/geos/index/SpatialIndex.h
=====================================
@@ -71,9 +71,7 @@ public:
* intersect the query envelope.
*
* @param searchEnv the envelope to query for
- * @return a list of the items found by the query in a newly allocated vector
*/
- //virtual std::vector<void*>* query(const geom::Envelope *searchEnv)=0;
virtual void query(const geom::Envelope* searchEnv, std::vector<void*>&) = 0;
/** \brief
=====================================
include/geos/index/strtree/TemplateSTRtree.h
=====================================
@@ -306,6 +306,8 @@ public:
/// @{
bool remove(const BoundsType& itemEnv, const ItemType& item) {
+ build();
+
if (root == nullptr) {
return false;
}
@@ -359,12 +361,12 @@ public:
// begin and end define a range of nodes needing parents
auto begin = nodes.begin();
- auto end = nodes.end();
+ auto number = static_cast<size_t>(std::distance(begin, nodes.end()));
- while (std::distance(begin, end) > 1) {
- createParentNodes(begin, end);
- begin = end; // parents just added become children in the next round
- end = nodes.end();
+ while (number > 1) {
+ createParentNodes(begin, number);
+ std::advance(begin, static_cast<long>(number)); // parents just added become children in the next round
+ number = static_cast<size_t>(std::distance(begin, nodes.end()));
}
assert(finalSize == nodes.size());
@@ -421,22 +423,24 @@ protected:
return nodesInTree;
}
- void createParentNodes(const NodeListIterator& begin, const NodeListIterator& end) {
+ void createParentNodes(const NodeListIterator& begin, size_t number) {
// Arrange child nodes in two dimensions.
// First, divide them into vertical slices of a given size (left-to-right)
// Then create nodes within those slices (bottom-to-top)
- auto numChildren = static_cast<std::size_t>(std::distance(begin, end));
- auto numSlices = sliceCount(numChildren);
- std::size_t nodesPerSlice = sliceCapacity(numChildren, numSlices);
+ auto numSlices = sliceCount(number);
+ std::size_t nodesPerSlice = sliceCapacity(number, numSlices);
// We could sort all of the nodes here, but we don't actually need them to be
// completely sorted. They need to be sorted enough for each node to end up
// in the right vertical slice, but their relative position within the slice
// doesn't matter. So we do a partial sort for each slice below instead.
+ auto end = begin + static_cast<long>(number);
sortNodesX(begin, end);
auto startOfSlice = begin;
for (decltype(numSlices) j = 0; j < numSlices; j++) {
+ // end iterator is being invalidated at each iteration
+ end = begin + static_cast<long>(number);
auto nodesRemaining = static_cast<size_t>(std::distance(startOfSlice, end));
auto nodesInSlice = std::min(nodesRemaining, nodesPerSlice);
auto endOfSlice = std::next(startOfSlice, static_cast<long>(nodesInSlice));
@@ -544,9 +548,11 @@ protected:
for (auto *child = node.beginChildren(); child < node.endChildren(); ++child) {
if (child->boundsIntersect(queryEnv)) {
- if (child->isLeaf() && !child->isDeleted()) {
- if (!visitLeaf(visitor, *child)) {
- return;
+ if (child->isLeaf()) {
+ if (!child->isDeleted()) {
+ if (!visitLeaf(visitor, *child)) {
+ return;
+ }
}
} else {
query(queryEnv, *child, visitor);
=====================================
include/geos/precision/CommonBitsRemover.h
=====================================
@@ -75,7 +75,6 @@ public:
*
* @param geom the Geometry from which to remove the common
* coordinate bits
- * @return the shifted Geometry
*/
void removeCommonBits(geom::Geometry* geom);
=====================================
include/geos/triangulate/polygon/PolygonEarClipper.h
=====================================
@@ -164,7 +164,12 @@ private:
bool isFlat(const std::array<Coordinate, 3>& pts) const;
- bool hasRepeatedPoint(const std::array<Coordinate, 3>& pts) const;
+ /**
+ * Detects if a corner has repeated points (AAB or ABB), or is collapsed (ABA).
+ * @param pts the corner points
+ * @return true if the corner is flat or collapsed
+ */
+ bool isCornerInvalid(const std::array<Coordinate, 3>& pts) const;
public:
=====================================
include/geos/triangulate/polygon/PolygonHoleJoiner.h
=====================================
@@ -51,11 +51,15 @@ namespace polygon {
/**
- * Transforms a polygon with holes into a single self-touching ring
+ * Transforms a polygon with holes into a single self-touching (invalid) ring
* by connecting holes to the exterior shell or to another hole.
* The holes are added from the lowest upwards.
* As the resulting shell develops, a hole might be added to what was
* originally another hole.
+ *
+ * There is no attempt to optimize the quality of the join lines.
+ * In particular, a hole which already touches at a vertex may be
+ * joined at a different vertex.
*/
class GEOS_DLL PolygonHoleJoiner {
=====================================
src/algorithm/construct/MaximumInscribedCircle.cpp
=====================================
@@ -121,6 +121,10 @@ MaximumInscribedCircle::createInitialGrid(const Envelope* env, std::priority_que
double cellSize = std::min(width, height);
double hSize = cellSize / 2.0;
+ // Collapsed geometries just end up using the centroid
+ // as the answer and skip all the other machinery
+ if (cellSize == 0) return;
+
// compute initial grid of cells to cover area
for (double x = minX; x < maxX; x += cellSize) {
for (double y = minY; y < maxY; y += cellSize) {
=====================================
src/dirlist.mk deleted
=====================================
@@ -1,48 +0,0 @@
-#
-# List of directories use by makefile.vc to clean .obj files
-#
-
-GEOS_DIRLIST = \
- algorithm \
- algorithm\distance \
- algorithm\locate \
- examples \
- geom \
- geom\util \
- geom\prep \
- geomgraph \
- geomgraph\index \
- headers \
- headers\geos \
- index \
- index\bintree \
- index\chain \
- index\intervalrtree \
- index\quadtree \
- index\strtree \
- index\sweepline \
- io \
- linearref \
- noding \
- noding\snapround \
- operation \
- operation\buffer \
- operation\distance \
- operation\intersection \
- operation\linemerge \
- operation\overlay \
- operation\overlay\snap \
- operation\overlay\validate \
- operation\polygonize \
- operation\predicate \
- operation\relate \
- operation\sharedpaths \
- operation\union \
- operation\valid \
- planargraph \
- planargraph\algorithm \
- precision \
- simplify \
- triangulate \
- triangulate\quadedge \
- util
=====================================
src/geomgraph/Node.cpp
=====================================
@@ -29,6 +29,7 @@
#include <geos/util.h>
#include <cmath>
+#include <memory>
#include <string>
#include <sstream>
#include <vector>
@@ -132,8 +133,9 @@ Node::isIncidentEdgeInResult() const
}
void
-Node::add(EdgeEnd* e)
+Node::add(EdgeEnd* p_e)
{
+ std::unique_ptr<EdgeEnd> e(p_e);
assert(e);
#if GEOS_DEBUG
std::cerr << "[" << this << "] Node::add(" << e->print() << ")" << std::endl;
@@ -152,10 +154,10 @@ Node::add(EdgeEnd* e)
assert(edges);
//if (edges==NULL) return;
- edges->insert(e);
- e->setNode(this);
+ edges->insert(e.release());
+ p_e->setNode(this);
#if COMPUTE_Z
- addZ(e->getCoordinate().z);
+ addZ(p_e->getCoordinate().z);
#endif
testInvariant();
}
=====================================
src/index/chain/MonotoneChainBuilder.cpp
=====================================
@@ -64,6 +64,7 @@ public:
private:
void finishChain() {
+ if ( m_i == 0 ) return;
m_ends.push_back(m_i - 1);
}
=====================================
src/io/GeoJSONWriter.cpp
=====================================
@@ -180,6 +180,10 @@ void GeoJSONWriter::encodeGeometry(const geom::Geometry* geometry, geos_nlohmann
auto line = static_cast<const geom::LineString*>(geometry);
encodeLineString(line, j);
}
+ else if (type == GEOS_LINEARRING) {
+ auto line = static_cast<const geom::LineString*>(geometry);
+ encodeLineString(line, j);
+ }
else if (type == GEOS_POLYGON) {
auto poly = static_cast<const geom::Polygon*>(geometry);
encodePolygon(poly, j);
@@ -205,7 +209,12 @@ void GeoJSONWriter::encodeGeometry(const geom::Geometry* geometry, geos_nlohmann
void GeoJSONWriter::encodePoint(const geom::Point* point, geos_nlohmann::ordered_json& j)
{
j["type"] = "Point";
- j["coordinates"] = convertCoordinate(point->getCoordinate());
+ if (!point->isEmpty()) {
+ j["coordinates"] = convertCoordinate(point->getCoordinate());
+ }
+ else {
+ j["coordinates"] = j.array();
+ }
}
void GeoJSONWriter::encodeLineString(const geom::LineString* line, geos_nlohmann::ordered_json& j)
=====================================
src/operation/polygonize/BuildArea.cpp
=====================================
@@ -66,6 +66,74 @@ struct Face {
}
};
+static bool ringsEqualAnyDirection(const LinearRing* r1, const LinearRing* r2)
+{
+
+ const CoordinateSequence *cs1 = r1->getCoordinatesRO();
+ const CoordinateSequence *cs2 = r2->getCoordinatesRO();
+
+ /* Check same number of points */
+ size_t npoints = cs1->size();
+ if ( npoints != cs2->size() )
+ {
+ return false;
+ }
+
+ if ( npoints == 0 ) return true; /* if empty, they are equal */
+
+ /* Check same envelope (probably better avoid, as it'd need to
+ * compute the envelope doing an additional scan for each) */
+ if ( ! r1->getEnvelopeInternal()->equals(r2->getEnvelopeInternal()) )
+ {
+ return false;
+ }
+
+ /* Pretend the rings had one less point, as the last one will be
+ * equal to the first one anyway */
+ --npoints;
+
+ const Coordinate& firstPoint = cs1->getAt(0);
+ size_t offset = CoordinateSequence::indexOf(&firstPoint, cs2);
+ if ( offset == std::numeric_limits<std::size_t>::max() ) return false;
+
+ bool equal = true;
+
+ /* Check equals forward (skip first point, we checked it alread) */
+ for (size_t i=1; i<npoints; ++i)
+ {
+ size_t j = ( i + offset ) % npoints;
+ const Coordinate& c1 = cs1->getAt(i);
+ const Coordinate& c2 = cs2->getAt(j);
+ if ( ! c1.equals(c2) ) {
+ equal = false;
+ break;
+ }
+ }
+
+ if ( equal ) return true;
+
+ /* Check equals backward (skip first point, we checked it already) */
+ equal = true;
+ for (size_t i=1; i<npoints; ++i)
+ {
+ size_t j;
+ if ( i <= offset ) {
+ j = offset - i;
+ } else {
+ j = npoints - ( i - offset );
+ }
+
+ const Coordinate& c1 = cs1->getAt(i);
+ const Coordinate& c2 = cs2->getAt(j);
+ if ( ! c1.equals(c2) ) {
+ equal = false;
+ break;
+ }
+ }
+
+ return equal;
+}
+
static std::unique_ptr<Face> newFace(const geom::Polygon* p) {
auto f = std::unique_ptr<Face>(new Face());
f->poly = p;
@@ -100,13 +168,8 @@ static void findFaceHoles(std::vector<std::unique_ptr<Face>>& faces) {
if( f2->parent ) {
continue; /* hole already assigned */
}
- const auto f2er = f2->poly->getExteriorRing();
- /* TODO: can be optimized as the ring would have the
- * same vertices, possibly in different order.
- * maybe comparing number of points could already be
- * useful.
- */
- if( f2er->equals(hole) ) {
+ const auto shell = f2->poly->getExteriorRing();
+ if( ringsEqualAnyDirection(shell, hole) ) {
f2->parent = f.get();
break;
}
=====================================
src/operation/union/CascadedPolygonUnion.cpp
=====================================
@@ -102,7 +102,10 @@ std::unique_ptr<geom::Geometry>
CascadedPolygonUnion::binaryUnion(const std::vector<const geom::Geometry*> & geoms,
std::size_t start, std::size_t end)
{
- if(end - start <= 1) {
+ if(end - start == 0) {
+ return nullptr;
+ }
+ else if(end - start == 1) {
return unionSafe(geoms[start], nullptr);
}
else if(end - start == 2) {
=====================================
src/triangulate/polygon/PolygonEarClipper.cpp
=====================================
@@ -100,8 +100,8 @@ PolygonEarClipper::compute(TriList& triList)
* after enough ears are removed)
*/
if (! isConvex(corner)) {
- // remove the corner if it is flat or a repeated point
- bool isCornerRemoved = hasRepeatedPoint(corner)
+ // remove the corner if it is invalid or flat (if required)
+ bool isCornerRemoved = isCornerInvalid(corner)
|| (isFlatCornersSkipped && isFlat(corner));
if (isCornerRemoved) {
removeCorner();
@@ -337,9 +337,9 @@ PolygonEarClipper::isFlat(const std::array<Coordinate, 3>& pts) const
/* private static */
bool
-PolygonEarClipper::hasRepeatedPoint(const std::array<Coordinate, 3>& pts) const
+PolygonEarClipper::isCornerInvalid(const std::array<Coordinate, 3>& pts) const
{
- return pts[1].equals2D(pts[0]) || pts[1].equals2D(pts[2]);
+ return pts[1].equals2D(pts[0]) || pts[1].equals2D(pts[2]) || pts[0].equals2D(pts[2]);
}
=====================================
tests/unit/algorithm/construct/MaximumInscribedCircleTest.cpp
=====================================
@@ -174,6 +174,18 @@ void object::test<6>
}
+// //
+// // Invalid polygon collapsed to a line
+// //
+template<>
+template<>
+void object::test<7>
+()
+{
+ checkCircle("POLYGON((1 2, 1 2, 1 2, 1 2, 3 2, 1 2))",
+ 0.01, 2, 2, 0 );
+}
+
} // namespace tut
=====================================
tests/unit/capi/GEOSPreparedGeometryTest.cpp
=====================================
@@ -405,5 +405,23 @@ void object::test<13>
ensure_equals(ret, 0);
}
+// Verify no memory leak on exception (https://github.com/libgeos/geos/issues/505)
+template<>
+template<>
+void object::test<14>
+()
+{
+ geom1_ = GEOSGeomFromWKT("LINESTRING(0 0, 1 NaN)");
+ geom2_ = GEOSGeomFromWKT("POINT(0 0)");
+ prepGeom1_ = GEOSPrepare(geom1_);
+
+ ensure(nullptr != prepGeom1_);
+ ensure(nullptr != geom2_);
+
+ int ret = GEOSPreparedTouches(prepGeom1_, geom2_);
+ ensure_equals(ret, 2);
+}
+
+
} // namespace tut
=====================================
tests/unit/capi/GEOSSTRtreeTest.cpp
=====================================
@@ -382,6 +382,40 @@ void object::test<11>()
GEOSSTRtree_destroy(tree);
}
+template<>
+template<>
+void object::test<12>()
+{
+ GEOSSTRtree* tree = GEOSSTRtree_create(10);
+
+ GEOSGeometry* g1 = GEOSGeomFromWKT("LINESTRING (0 0, 10 10)");
+ GEOSGeometry* g2 = GEOSGeomFromWKT("LINESTRING (20 20, 30 30)");
+ GEOSGeometry* g3 = GEOSGeomFromWKT("LINESTRING (20 20, 30 30)");
+
+ GEOSSTRtree_insert(tree, g1, g1);
+ GEOSSTRtree_insert(tree, g2, g2);
+ GEOSSTRtree_insert(tree, g3, g3);
+
+ GEOSGeometry* p = GEOSGeomFromWKT("POINT (5 5)");
+
+ ensure_equals(GEOSSTRtree_remove(tree, p, g1), 1);
+
+ std::vector<GEOSGeometry*> hits;
+ GEOSSTRtree_query(tree, p, [](void* item, void* userdata) {
+ auto h = static_cast<std::vector<GEOSGeometry*>*>(userdata);
+ h->push_back(static_cast<GEOSGeometry*>(item));
+ }, &hits);
+
+ ensure(hits.empty());
+
+ GEOSGeom_destroy(g1);
+ GEOSGeom_destroy(g2);
+ GEOSGeom_destroy(g3);
+ GEOSGeom_destroy(p);
+
+ GEOSSTRtree_destroy(tree);
+}
+
} // namespace tut
=====================================
tests/unit/geom/Geometry/differenceTest.cpp
=====================================
@@ -0,0 +1,60 @@
+//
+// Test Suite for geos::geom::Geometry::difference() method.
+
+#include <tut/tut.hpp>
+#include <utility.h>
+// geos
+#include <geos/io/WKTReader.h>
+#include <geos/io/WKTWriter.h>
+#include <geos/geom/PrecisionModel.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/Point.h>
+#include <geos/geom/LineString.h>
+#include <geos/util.h>
+
+namespace tut {
+// dummy data, not used
+struct test_geometry_difference_data {
+ geos::io::WKTReader wktreader;
+ geos::io::WKTWriter wktwriter;
+
+ test_geometry_difference_data()
+ :
+ wktreader()
+ {}
+};
+
+typedef test_group<test_geometry_difference_data> group;
+typedef group::object object;
+
+group test_geometry_difference_group("geos::geom::Geometry::difference");
+
+//
+// Test Cases
+
+
+// This issue exercised a bug in MonotoneChainBuilder
+// https://github.com/libgeos/geos/issues/290
+template<>
+template<>
+void object::test<1>
+()
+{
+ std::string wkt1("POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))");
+ std::unique_ptr<geos::geom::Geometry> g1(wktreader.read(wkt1));
+
+ std::string wkt2("POLYGON((0.1 0.1, 4.0 0.1, 4.0 1.9, 0.1 1.9, 0.1 0.1))");
+ std::unique_ptr<geos::geom::Geometry> g2(wktreader.read(wkt2));
+
+ auto result = g2->difference(g1.get());
+ result->normalize();
+
+ std::string wktExpected("POLYGON ((2 0.1, 2 1.9, 4 1.9, 4 0.1, 2 0.1))");
+ std::unique_ptr<geos::geom::Geometry> expected(wktreader.read(wktExpected));
+
+ ensure_equals_geometry(expected.get(), result.get());
+}
+
+
+} // namespace tut
=====================================
tests/unit/index/chain/MonotoneChainBuilderTest.cpp
=====================================
@@ -4,14 +4,11 @@
#include <tut/tut.hpp>
#include <utility.h>
// geos
-#include <geos/io/WKTReader.h>
-#include <geos/io/WKTWriter.h>
-#include <geos/geom/PrecisionModel.h>
-#include <geos/geom/GeometryFactory.h>
-#include <geos/geom/Geometry.h>
-#include <geos/geom/Point.h>
-#include <geos/geom/LineString.h>
-#include <geos/util.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/index/chain/MonotoneChain.h>
+#include <geos/index/chain/MonotoneChainBuilder.h>
+
namespace tut {
// dummy data, not used
@@ -33,28 +30,19 @@ group test_monotonechain_group("geos::index::chain::MonotoneChainBuilder");
//
// Test Cases
-
// This issue exercised a bug in MonotoneChainBuilder
-// https://github.com/libgeos/geos/issues/290
+// https://github.com/libgeos/geos/issues/539
template<>
template<>
void object::test<1>
()
{
- std::string wkt1("POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))");
- std::unique_ptr<geos::geom::Geometry> g1(wktreader.read(wkt1));
-
- std::string wkt2("POLYGON((0.1 0.1, 4.0 0.1, 4.0 1.9, 0.1 1.9, 0.1 0.1))");
- std::unique_ptr<geos::geom::Geometry> g2(wktreader.read(wkt2));
+ std::vector<geos::index::chain::MonotoneChain> chain;
+ geos::geom::CoordinateArraySequence pts;
- auto result = g2->difference(g1.get());
- result->normalize();
+ geos::index::chain::MonotoneChainBuilder::getChains(&pts, 0, chain);
- std::string wktExpected("POLYGON ((2 0.1, 2 1.9, 4 1.9, 4 0.1, 2 0.1))");
- std::unique_ptr<geos::geom::Geometry> expected(wktreader.read(wktExpected));
-
- ensure_equals_geometry(expected.get(), result.get());
+ ensure_equals(chain.size(), 0u);
}
-
} // namespace tut
=====================================
tests/unit/io/GeoJSONWriterTest.cpp
=====================================
@@ -252,4 +252,60 @@ void object::test<14>
ensure_equals(result, "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[-117.0,33.0]},\"properties\":{\"id\":1.0,\"name\":\"One\"}},{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[-127.0,53.0]},\"properties\":{\"id\":2.0,\"name\":\"Two\"}}]}");
}
+// Write an empty point
+template<>
+template<>
+void object::test<15>
+()
+{
+ GeomPtr geom(wktreader.read("POINT EMPTY"));
+ std::string result = geojsonwriter.write(geom.get());
+ ensure_equals(result, "{\"type\":\"Point\",\"coordinates\":[]}");
+}
+
+// Write an empty linestring
+template<>
+template<>
+void object::test<16>
+()
+{
+ GeomPtr geom(wktreader.read("LINESTRING EMPTY"));
+ std::string result = geojsonwriter.write(geom.get());
+ ensure_equals(result, "{\"type\":\"LineString\",\"coordinates\":[]}");
+}
+
+// Write an empty polygon
+template<>
+template<>
+void object::test<17>
+()
+{
+ GeomPtr geom(wktreader.read("POLYGON EMPTY"));
+ std::string result = geojsonwriter.write(geom.get());
+ ensure_equals(result, "{\"type\":\"Polygon\",\"coordinates\":[[]]}");
+}
+
+// Write an empty polygon
+template<>
+template<>
+void object::test<18>
+()
+{
+ GeomPtr geom(wktreader.read("GEOMETRYCOLLECTION EMPTY"));
+ std::string result = geojsonwriter.write(geom.get());
+ ensure_equals(result, "{\"type\":\"GeometryCollection\",\"geometries\":[]}");
+}
+
+// Write a linear ring (as a linestring)
+template<>
+template<>
+void object::test<19>
+()
+{
+ GeomPtr geom(wktreader.read("LINEARRING (0 0, 1 1, 1 0, 0 0)"));
+ std::string result = geojsonwriter.write(geom.get());
+ ensure_equals(result, "{\"type\":\"LineString\",\"coordinates\":[[0.0,0.0],[1.0,1.0],[1.0,0.0],[0.0,0.0]]}");
+}
+
+
}
=====================================
tests/unit/triangulate/polygon/PolygonTriangulatorTest.cpp
=====================================
@@ -181,6 +181,19 @@ void object::test<11>()
);
}
+
+// testCollapsedCorner
+template<>
+template<>
+void object::test<12>()
+{
+ checkTri(
+ "POLYGON ((186 90, 71 17, 74 10, 65 0, 0 121, 186 90), (73 34, 67 41, 71 17, 73 34))"
+ );
+}
+
+
+
} // namespace tut
=====================================
tests/xmltester/tests/general/TestUnaryUnion.xml
=====================================
@@ -156,6 +156,68 @@
</test>
</case>
+<case>
+ <desc>P - empty point</desc>
+ <a>POINT EMPTY</a>
+ <test>
+ <op name="union" arg1="A">POINT EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>mP - empty multi point</desc>
+ <a>MULTIPOINT EMPTY</a>
+ <test>
+ <op name="union" arg1="A">MULTIPOINT EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>L - empty line</desc>
+ <a>LINESTRING EMPTY</a>
+ <test>
+ <op name="union" arg1="A">LINESTRING EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>mL - empty multi line</desc>
+ <a>MULTILINESTRING EMPTY</a>
+ <test>
+ <op name="union" arg1="A">MULTILINESTRING EMPTY</op>
+ </test>
+</case>
+<case>
+ <desc>L - empty linear ring</desc>
+ <a>LINEARRING EMPTY</a>
+ <test>
+ <op name="union" arg1="A">LINEARRING EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>P - empty polygon</desc>
+ <a>POLYGON EMPTY</a>
+ <test>
+ <op name="union" arg1="A">POLYGON EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>mP - empty multi polygon</desc>
+ <a>MULTIPOLYGON EMPTY</a>
+ <test>
+ <op name="union" arg1="A">MULTIPOLYGON EMPTY</op>
+ </test>
+</case>
+
+<case>
+ <desc>GC - empty geometry collection</desc>
+ <a>GEOMETRYCOLLECTION EMPTY</a>
+ <test>
+ <op name="union" arg1="A">GEOMETRYCOLLECTION EMPTY</op>
+ </test>
+</case>
</run>
View it on GitLab: https://salsa.debian.org/debian-gis-team/geos/-/commit/d49492612fd028a5229ed0f51b10dc79bd29e963
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/geos/-/commit/d49492612fd028a5229ed0f51b10dc79bd29e963
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/20220116/108e81a6/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list