Skip to content

Commit 15a7a71

Browse files
committed
GridIntersection: Avoid passing self-touching rings to Polygonizer
1 parent c70c4c4 commit 15a7a71

File tree

9 files changed

+308
-212
lines changed

9 files changed

+308
-212
lines changed

include/geos/operation/grid/Cell.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ class Cell
7676
* @param c Coordinate to process
7777
* @param prev_original The last *uninterpolated* coordinate preceding `c` in the
7878
* boundary being processed
79+
* @param parentage an optional pointer indicating the source of the coordinate.
7980
*
8081
* @return `true` if the Coordinate was inside this cell, `false` otherwise
8182
*/
82-
bool take(const geom::CoordinateXY& c, const geom::CoordinateXY* prev_original = nullptr);
83+
bool take(const geom::CoordinateXY& c, const geom::CoordinateXY* prev_original, const void* parentage);
8384

8485
private:
85-
std::vector<const std::vector<geom::CoordinateXY>*> getCoordLists() const;
86+
std::vector<const Traversal*> getTraversals() const;
8687

8788
enum class Location
8889
{

include/geos/operation/grid/Traversal.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,26 @@
1414

1515
#pragma once
1616

17-
#include <vector>
18-
17+
#include <geos/export.h>
1918
#include <geos/geom/Coordinate.h>
2019
#include <geos/operation/grid/Side.h>
2120

21+
#include <vector>
22+
2223
namespace geos::operation::grid {
2324

2425
/**
2526
* @brief The Traversal class records the coordinates of a line that are
2627
* within a grid cell, as well as the `Side` from which the line
2728
* entered and exited the cell.
2829
*/
29-
class Traversal
30+
class GEOS_DLL Traversal
3031
{
3132
public:
3233
Traversal()
3334
: m_entry{ Side::NONE }
3435
, m_exit{ Side::NONE }
36+
, m_parentage{ nullptr }
3537
{
3638
}
3739

@@ -48,7 +50,7 @@ class Traversal
4850
bool hasMultipleUniqueCoordinates() const;
4951

5052
/// Begin a Traversal on the specified `Side`
51-
void enter(const geom::CoordinateXY& c, Side s);
53+
void enter(const geom::CoordinateXY& c, Side s, const void* parentage);
5254

5355
/// Complete a Traversal on the specified `Side`
5456
void exit(const geom::CoordinateXY& c, Side s);
@@ -67,10 +69,13 @@ class Traversal
6769

6870
const std::vector<geom::CoordinateXY>& getCoordinates() const { return m_coords; }
6971

72+
const void* getParentage() const { return m_parentage; }
73+
7074
private:
7175
std::vector<geom::CoordinateXY> m_coords;
7276
Side m_entry;
7377
Side m_exit;
78+
const void* m_parentage;
7479
};
7580

7681
}

include/geos/operation/grid/TraversalAreas.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
namespace geos::operation::grid {
2121

22+
class Traversal;
23+
2224
class GEOS_DLL TraversalAreas {
2325
public:
2426
/**
@@ -32,7 +34,7 @@ class GEOS_DLL TraversalAreas {
3234
* @return total area
3335
*/
3436
static double
35-
getLeftHandArea(const geom::Envelope& box, const std::vector<const std::vector<geom::CoordinateXY>*>& coord_lists);
37+
getLeftHandArea(const geom::Envelope& box, const std::vector<const Traversal*>& coord_lists);
3638

3739
/**
3840
* @brief Return an areal geometry representing the closed rings formed by this box and the provided Coordinate sequences
@@ -46,7 +48,7 @@ class GEOS_DLL TraversalAreas {
4648
* @return a Polygon or MultiPolygon geometry
4749
*/
4850
static std::unique_ptr<geom::Geometry>
49-
getLeftHandRings(const geom::GeometryFactory& gfact, const geom::Envelope& box, const std::vector<const std::vector<geom::CoordinateXY>*>& coord_lists);
51+
getLeftHandRings(const geom::GeometryFactory& gfact, const geom::Envelope& box, const std::vector<const Traversal*>& coord_lists);
5052

5153
};
5254

src/operation/grid/Cell.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ Cell::getLastTraversal()
191191
}
192192

193193
bool
194-
Cell::take(const CoordinateXY& c, const CoordinateXY* prev_original)
194+
Cell::take(const CoordinateXY& c, const CoordinateXY* prev_original, const void* parentage)
195195
{
196196
Traversal& t = traversal_in_progress();
197197

@@ -201,7 +201,7 @@ Cell::take(const CoordinateXY& c, const CoordinateXY* prev_original)
201201
std::cout << "Entering " << m_box << " from " << getSide(c) << " at " << c << std::endl;
202202
#endif
203203

204-
t.enter(c, getSide(c));
204+
t.enter(c, getSide(c), parentage);
205205
return true;
206206
}
207207

@@ -258,32 +258,32 @@ Cell::isDetermined() const
258258
return false;
259259
}
260260

261-
std::vector<const std::vector<CoordinateXY>*>
262-
Cell::getCoordLists() const
261+
std::vector<const Traversal*>
262+
Cell::getTraversals() const
263263
{
264-
std::vector<const std::vector<CoordinateXY>*> coord_lists;
265-
coord_lists.reserve(m_traversals.size());
264+
std::vector<const Traversal*> traversals;
265+
traversals.reserve(m_traversals.size());
266266

267267
for (const auto& t : m_traversals) {
268268
if (t.isTraversed() || t.isClosedRing()) {
269-
coord_lists.push_back(&t.getCoordinates());
269+
traversals.push_back(&t);
270270
}
271271
}
272272

273-
return coord_lists;
273+
return traversals;
274274
}
275275

276276
double
277277
Cell::getCoveredFraction() const
278278
{
279-
auto coord_lists = getCoordLists();
279+
auto coord_lists = getTraversals();
280280
return TraversalAreas::getLeftHandArea(m_box, coord_lists) / getArea();
281281
}
282282

283283
std::unique_ptr<Geometry>
284284
Cell::getCoveredPolygons(const GeometryFactory& gfact) const
285285
{
286-
auto coord_lists = getCoordLists();
286+
auto coord_lists = getTraversals();
287287
return TraversalAreas::getLeftHandRings(gfact, m_box, coord_lists);
288288
}
289289

src/operation/grid/GridIntersection.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ collect_lengths(const Matrix<std::unique_ptr<Cell>>& cells)
308308
return lengths;
309309
}
310310

311-
void
312-
traverse_cells(Matrix<std::unique_ptr<Cell>>& cells, std::vector<CoordinateXY>& coords, const Grid<infinite_extent>& ring_grid, bool areal)
311+
static void
312+
traverse_cells(Matrix<std::unique_ptr<Cell>>& cells, std::vector<CoordinateXY>& coords, const Grid<infinite_extent>& ring_grid, bool areal, const void* parentage)
313313
{
314314
size_t pos = 0;
315315
size_t row = ring_grid.getRow(coords.front().y);
@@ -323,7 +323,7 @@ traverse_cells(Matrix<std::unique_ptr<Cell>>& cells, std::vector<CoordinateXY>&
323323
const CoordinateXY* next_coord = last_exit ? last_exit : &coords[pos];
324324
const CoordinateXY* prev_coord = pos > 0 ? &coords[pos - 1] : nullptr;
325325

326-
cell.take(*next_coord, prev_coord);
326+
cell.take(*next_coord, prev_coord, parentage);
327327

328328
if (cell.getLastTraversal().isExited()) {
329329
// Only push our exit coordinate if it's not same as the
@@ -437,7 +437,7 @@ GridIntersection::processLine(const LineString& ls, bool exterior_ring)
437437
}
438438

439439
Matrix<std::unique_ptr<Cell>> cells(ring_grid.getNumRows(), ring_grid.getNumCols());
440-
traverse_cells(cells, coordsVec, ring_grid, m_areal);
440+
traverse_cells(cells, coordsVec, ring_grid, m_areal, &ls);
441441

442442
// Compute the fraction covered for all cells and assign it to
443443
// the area matrix
@@ -473,8 +473,8 @@ traverse_ring(Matrix<std::unique_ptr<Cell>>& cells, const Grid<infinite_extent>&
473473

474474
if (want_ccw != algorithm::Orientation::isCCW(&seq)) {
475475
std::reverse(coords.begin(), coords.end());
476-
}
477-
traverse_cells(cells, coords, grid, true);
476+
}
477+
traverse_cells(cells, coords, grid, true, &g);
478478
}
479479

480480
void

src/operation/grid/Traversal.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ Traversal::isEmpty() const
3434
}
3535

3636
void
37-
Traversal::enter(const CoordinateXY& c, Side s)
37+
Traversal::enter(const CoordinateXY& c, Side s, const void* parentage)
3838
{
3939
if (!m_coords.empty()) {
4040
throw std::runtime_error("Traversal already started");
4141
}
4242

4343
add(c);
4444
m_entry = s;
45+
m_parentage = parentage;
4546
}
4647

4748
void

0 commit comments

Comments
 (0)