Skip to content

Commit

Permalink
proposal 2: multilinesting
Browse files Browse the repository at this point in the history
Improve consistency of GEOSVoronoiDiagram
**change**

the getDiagramEdges now only returns a MultiLineString, whether there is
one or many lines. Which reduces to two the number of possible kind of
geometries given by `GEOSVoronoiDiagram`

**reason**

I've been working on adding `voronoi_diagram` to RGeo. And looking at
the [Shapely PR for voronoi diagram][1] and [mine in RGeo][2], it seems
like the `GEOSVoronoiDiagram` CAPI method causes confusion by returning
three possible kind of geometries:

- `GeometryCollection` (when `onlyEdges` is false)
- `MultiLineString` (`onlyEdges` is true and there are at least two lines)
- `LineString` (`onlyEdges` is true and there is only one line)

The parameter `onlyEdges` changes the outcome, which is ok to reason
about. However, the fact that we could have either a LineString or a
MultiLineString is way harder to work around in my opinion.

[1]: shapely/shapely#881 (comment)
[2]: rgeo/rgeo#334 (comment)
  • Loading branch information
BuonOmo committed Nov 10, 2022
1 parent e315692 commit a943545
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 23 deletions.
4 changes: 2 additions & 2 deletions include/geos/triangulate/VoronoiDiagramBuilder.h
Expand Up @@ -107,13 +107,13 @@ class GEOS_DLL VoronoiDiagramBuilder {
std::unique_ptr<geom::GeometryCollection> getDiagram(const geom::GeometryFactory& geomFact);

/** \brief
* Gets the faces of the computed diagram as a {@link geom::GeometryCollection}
* Gets the faces of the computed diagram as a {@link geom::MultiLineString}
* of {@link geom::LineString}s, clipped as specified.
*
* @param geomFact the geometry factory to use to create the output
* @return the faces of the diagram
*/
std::unique_ptr<geom::GeometryCollection> getDiagramEdges(const geom::GeometryFactory& geomFact);
std::unique_ptr<geom::MultiLineString> getDiagramEdges(const geom::GeometryFactory& geomFact);

private:

Expand Down
17 changes: 7 additions & 10 deletions src/triangulate/VoronoiDiagramBuilder.cpp
Expand Up @@ -123,33 +123,30 @@ VoronoiDiagramBuilder::getDiagram(const geom::GeometryFactory& geomFact)
return ret;
}

std::unique_ptr<GeometryCollection>
std::unique_ptr<MultiLineString>
VoronoiDiagramBuilder::getDiagramEdges(const geom::GeometryFactory& geomFact)
{
create();

if (!subdiv) {
return geomFact.createGeometryCollection();
return geomFact.createMultiLineString();
}

std::unique_ptr<geom::MultiLineString> edges = subdiv->getVoronoiDiagramEdges(geomFact);
if(edges->isEmpty()) {
return geomFact.createGeometryCollection();
return edges.release();
}
std::unique_ptr<geom::Geometry> clipPoly(geomFact.toGeometry(&diagramEnv));
std::unique_ptr<Geometry> clipped(clipPoly->intersection(edges.get()));

switch (clipped->getGeometryTypeId()) {
case GEOS_LINESTRING: {
std::vector<std::unique_ptr<Geometry>> vec;
vec.reserve(1);
vec.emplace_back(clipped.release());
return geomFact.createGeometryCollection(std::move(vec));
std::vector<std::unique_ptr<LineString>> lines;
lines.emplace_back(static_cast<LineString*>(clipped.release()));
return geomFact.createMultiLineString(std::move(lines));
}
case GEOS_MULTILINESTRING: {
return geomFact.createGeometryCollection(
static_cast<MultiLineString*>(clipped.get())->releaseGeometries()
);
return clipped
}
default: {
throw util::GEOSException("Unknown state");
Expand Down
16 changes: 5 additions & 11 deletions tests/unit/triangulate/VoronoiTest.cpp
Expand Up @@ -237,25 +237,19 @@ void object::test<10>
runVoronoi(wkt, expected, 0);
}

// Consistency in the return value.
// Consistency in the return value for edges
template<>
template<>
void object::test<11>
()
{
const char* wkt0 = "MULTIPOINT ((150 200))";
const char* expected0 = "GEOMETRYCOLLECTION EMPTY";
const char* wkt1 = "LINESTRING (10 10, 20 20)";
const char* expected1 = "GEOMETRYCOLLECTION (POLYGON ((0 30, 30 30, 30 0, 0 30)), POLYGON ((0 0, 0 30, 30 0, 0 0)))";
const char* expected2 = "GEOMETRYCOLLECTION (LINESTRING (0 30, 30 0))";
const char* expected1 = "MULTILINESTRING ((0 30, 30 0))";
const char* wkt2 = "LINESTRING (10 10, 20 20, 30 30)";
const char* expected3 = "GEOMETRYCOLLECTION (LINESTRING (0 50, 50 0), LINESTRING (-10 40, 40 -10))";
const char* expected2 = "MULTILINESTRING ((0 50, 50 0), (-10 40, 40 -10))";

runVoronoi(wkt0, expected0, 0, false);
runVoronoi(wkt0, expected0, 0, true);
runVoronoi(wkt1, expected1, 0, false);
runVoronoi(wkt1, expected2, 0, true);
runVoronoi(wkt2, expected3, 0, true);
runVoronoi(wkt1, expected1, 0, true);
runVoronoi(wkt2, expected2, 0, true);
}

} // namespace tut

0 comments on commit a943545

Please sign in to comment.