Skip to content

Commit

Permalink
BoundaryOp: Preserve M values in (Multi)LineString inputs
Browse files Browse the repository at this point in the history
Fixes #1195
  • Loading branch information
dbaston committed Nov 18, 2024
1 parent 32a3bf4 commit fc95e4b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
24 changes: 16 additions & 8 deletions src/operation/BoundaryOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ BoundaryOp::boundaryMultiLineString(const geom::MultiLineString& mLine)

// return Point or MultiPoint
if (bdyPts->size() == 1) {
return std::unique_ptr<Geometry>(m_geomFact.createPoint(bdyPts->getAt(0)));
return bdyPts->applyAt(0, [this](const auto& c) {
return m_geomFact.createPoint(c);
});
}
// this handles 0 points case as well
return std::unique_ptr<Geometry>(m_geomFact.createMultiPoint(*bdyPts));
Expand All @@ -148,8 +150,8 @@ BoundaryOp::boundaryMultiLineString(const geom::MultiLineString& mLine)
std::unique_ptr<CoordinateSequence>
BoundaryOp::computeBoundaryCoordinates(const geom::MultiLineString& mLine)
{
auto bdyPts = detail::make_unique<CoordinateSequence>();
std::map<Coordinate, int> endpointMap;
auto bdyPts = detail::make_unique<CoordinateSequence>(0, mLine.hasZ(), mLine.hasM());
std::map<geom::CoordinateXYZM, int> endpointMap;

for (std::size_t i = 0; i < mLine.getNumGeometries(); i++) {
const LineString* line = mLine.getGeometryN(i);
Expand All @@ -158,14 +160,20 @@ BoundaryOp::computeBoundaryCoordinates(const geom::MultiLineString& mLine)
continue;
}

endpointMap[line->getCoordinateN(0)]++;
endpointMap[line->getCoordinateN(line->getNumPoints() - 1)]++;
const CoordinateSequence& pts = *line->getCoordinatesRO();

geom::CoordinateXYZM start;
geom::CoordinateXYZM end;
pts.getAt(0, start);
pts.getAt(pts.size() - 1, end);

endpointMap[start]++;
endpointMap[end]++;
}

for (const auto& entry: endpointMap) {
auto valence = entry.second;
for (const auto& [coord, valence] : endpointMap) {
if (m_bnRule.isInBoundary(valence)) {
bdyPts->add(entry.first);
bdyPts->add(coord);
}
}

Expand Down
22 changes: 22 additions & 0 deletions tests/unit/capi/GEOSBoundaryTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,27 @@ void object::test<2>()
ensure(result_ == nullptr);
}

template<>
template<>
void object::test<3>()
{
input_ = fromWKT("MULTILINESTRING M ((10 11 3, 20 21 4), (20 21 4, 32 21 3))");
result_ = GEOSBoundary(input_);
expected_ = fromWKT("MULTIPOINT M ((10 11 3), (32 21 3))");

ensure_geometry_equals_identical(result_, expected_);
}

template<>
template<>
void object::test<4>()
{
input_ = fromWKT("POLYGON M ((0 0 0, 1 0 1, 1 1 2, 0 1 3, 0 0 4))");
result_ = GEOSBoundary(input_);
expected_ = fromWKT("LINESTRING M (0 0 0, 1 0 1, 1 1 2, 0 1 3, 0 0 4)");

ensure_geometry_equals_identical(result_, expected_);
}

} // namespace tut

5 changes: 4 additions & 1 deletion tests/unit/capi/capi_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ namespace capitest {
fromWKT(const char* wkt)
{
GEOSGeometry* g = GEOSGeomFromWKT(wkt);
tut::ensure(g != nullptr);
if (g == nullptr) {
std::string message = "WKT is invalid: " + std::string(wkt);
tut::ensure(message, g != nullptr);
}
return g;
}

Expand Down

0 comments on commit fc95e4b

Please sign in to comment.