[geos-commits] [SCM] GEOS branch main updated. 640d3758eeafc859e7484ca7ab7e6d76fc48719d
git at osgeo.org
git at osgeo.org
Mon Nov 17 05:24:06 PST 2025
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".
The branch, main has been updated
via 640d3758eeafc859e7484ca7ab7e6d76fc48719d (commit)
via 174866213c52f91d24cda3cfdb32dea6e4a4684e (commit)
via b0b52d238eee1b70388404e1401f7d3d7d90bc02 (commit)
from afe4d0595b2203605f6cdccd7742a9665caab6e3 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 640d3758eeafc859e7484ca7ab7e6d76fc48719d
Author: Daniel Baston <dbaston at gmail.com>
Date: Wed Oct 22 10:30:37 2025 -0400
Densifier: preserve and interpolate M values
diff --git a/src/geom/util/Densifier.cpp b/src/geom/util/Densifier.cpp
index 9f4e27967..a344757b4 100644
--- a/src/geom/util/Densifier.cpp
+++ b/src/geom/util/Densifier.cpp
@@ -108,16 +108,13 @@ Densifier::Densifier(const Geometry* geom):
std::unique_ptr<CoordinateSequence>
Densifier::densifyPoints(const CoordinateSequence& pts, double distanceTolerance, const PrecisionModel* precModel)
{
- geom::LineSegment seg;
- auto coordList = detail::make_unique<CoordinateSequence>();
+ auto coordList = detail::make_unique<CoordinateSequence>(0, pts.hasZ(), pts.hasM());
- auto items = pts.items<Coordinate>();
- for(auto it = items.cbegin(), itEnd = items.cend() - 1; it < itEnd; ++it) {
- seg.p0 = *it;
- seg.p1 = *(it + 1);
- coordList->add(seg.p0, false);
- const double len = seg.getLength();
- const double densifiedSegCountDbl = ceil(len / distanceTolerance);
+ pts.forEachSegment([&coordList, distanceTolerance, precModel](const auto& p0, const auto& p1) {
+ coordList->add(p0, false);
+
+ const double len = p0.distance(p1);
+ const double densifiedSegCountDbl = std::ceil(len / distanceTolerance);
if(densifiedSegCountDbl > std::numeric_limits<int>::max()) {
throw geos::util::GEOSException(
"Tolerance is too small compared to geometry length");
@@ -128,18 +125,20 @@ Densifier::densifyPoints(const CoordinateSequence& pts, double distanceTolerance
double densifiedSegLen = len / densifiedSegCount;
for(int j = 1; j < densifiedSegCount; j++) {
double segFract = (j * densifiedSegLen) / len;
- Coordinate p;
- seg.pointAlong(segFract, p);
+ auto p = LineSegment::pointAlong(segFract, p0, p1);
precModel->makePrecise(p);
coordList->add(p, false);
}
}
else {
// no densification required; insert the last coordinate and continue
- coordList->add(seg.p1, false);
+ coordList->add(p1, false);
}
- }
- coordList->add(pts[pts.size() - 1], false);
+
+ });
+ pts.applyAt(pts.size() - 1, [&coordList](const auto& pt) {
+ coordList->add(pt, false);
+ });
return coordList;
}
diff --git a/tests/unit/capi/GEOSDensifyTest.cpp b/tests/unit/capi/GEOSDensifyTest.cpp
index 721e91dc2..752441ddb 100644
--- a/tests/unit/capi/GEOSDensifyTest.cpp
+++ b/tests/unit/capi/GEOSDensifyTest.cpp
@@ -169,6 +169,7 @@ void object::test<10>()
result_ = GEOSDensify(input_, 0.1);
ensure("curved geometries not supported", result_ == nullptr);
}
+
// Densify a LINESTRING Z, check that Z gets interpolated
template <>
template <>
@@ -205,4 +206,17 @@ void object::test<13>()
);
}
+template <>
+template <>
+void object::test<14>()
+{
+ set_test_name("M values are interpolated");
+
+ testDensify(
+ "LINESTRING M (0 0 0, 0 6 2)",
+ "LINESTRING M (0 0 0, 0 3 1, 0 6 2)",
+ 3.0
+ );
+}
+
} // namespace tut
commit 174866213c52f91d24cda3cfdb32dea6e4a4684e
Author: Daniel Baston <dbaston at gmail.com>
Date: Wed Oct 22 10:30:29 2025 -0400
CoordinateSequence: add forEachSegment method
diff --git a/include/geos/geom/CoordinateSequence.h b/include/geos/geom/CoordinateSequence.h
index 2d952f137..5e0a7776b 100644
--- a/include/geos/geom/CoordinateSequence.h
+++ b/include/geos/geom/CoordinateSequence.h
@@ -710,6 +710,16 @@ public:
}
}
+ template<typename F>
+ void forEachSegment(F&& fun) const {
+ switch(getCoordinateType()) {
+ case CoordinateType::XY: forEachSegmentImpl<CoordinateXY, F>(std::move(fun)); break;
+ case CoordinateType::XYZ: forEachSegmentImpl<Coordinate, F>(std::move(fun)); break;
+ case CoordinateType::XYM: forEachSegmentImpl<CoordinateXYM, F>(std::move(fun)); break;
+ case CoordinateType::XYZM: forEachSegmentImpl<CoordinateXYZM, F>(std::move(fun)); break;
+ }
+ }
+
template<typename T, typename F>
void forEach(std::size_t from, std::size_t to, F&& fun) const
{
@@ -797,6 +807,24 @@ private:
orig = c;
}
+ template<typename CoordType, typename F>
+ void forEachSegmentImpl(F&& fun) const {
+ auto p0it = items<CoordType>().cbegin();
+ const auto end = items<CoordType>().end();
+
+ if (p0it == end) {
+ return;
+ }
+
+ auto p1it = std::next(p0it);
+
+ while (p1it != end) {
+ fun(*p0it, *p1it);
+ ++p0it;
+ ++p1it;
+ }
+ }
+
void make_space(std::size_t pos, std::size_t n) {
m_vect.insert(std::next(m_vect.begin(), static_cast<std::ptrdiff_t>(pos * stride())),
m_stride * n,
diff --git a/tests/unit/geom/CoordinateSequenceTest.cpp b/tests/unit/geom/CoordinateSequenceTest.cpp
index 4786c20c8..e2a94fb41 100644
--- a/tests/unit/geom/CoordinateSequenceTest.cpp
+++ b/tests/unit/geom/CoordinateSequenceTest.cpp
@@ -1536,4 +1536,48 @@ void object::test<56>
ensure_equals_xyz(seq1.getAt(3), Coordinate{10, 11, DoubleNotANumber});
}
+template<>
+template<>
+void object::test<57>()
+{
+ set_test_name("CoordinateSequence::forEachSegment called on empty CoordinateSequence");
+
+ CoordinateSequence empty;
+ empty.forEachSegment([](const auto&, const auto&) {
+ fail();
+ });
+}
+
+template<>
+template<>
+void object::test<58>()
+{
+ set_test_name("CoordinateSequence::forEachSegment called on single-point CoordinateSequence");
+
+ CoordinateSequence seq;
+ seq.add(CoordinateXY{3, 6});
+ seq.forEachSegment([](const auto&, const auto&) {
+ fail();
+ });
+}
+
+template<>
+template<>
+void object::test<59>()
+{
+ set_test_name("CoordinateSequence::forEachSegment basic test");
+
+ CoordinateSequence seq;
+ seq.add(CoordinateXY{0, 0});
+ seq.add(CoordinateXY{3, 0});
+ seq.add(CoordinateXY{3, 5});
+
+ double length = 0;
+ seq.forEachSegment([&length](const auto& p0, const auto& p1) {
+ length += p0.distance(p1);
+ });
+
+ ensure_equals(length, 8);
+}
+
} // namespace tut
commit b0b52d238eee1b70388404e1401f7d3d7d90bc02
Author: Daniel Baston <dbaston at gmail.com>
Date: Wed Oct 22 10:30:12 2025 -0400
LineSegment: Add static pointAlong interpolation methods
diff --git a/include/geos/geom/LineSegment.h b/include/geos/geom/LineSegment.h
index aea0fefd8..f6ef755ac 100644
--- a/include/geos/geom/LineSegment.h
+++ b/include/geos/geom/LineSegment.h
@@ -326,6 +326,34 @@ public:
p0.z + segmentLengthFraction * (p1.z - p0.z));
};
+ static CoordinateXY pointAlong(double segmentLengthFraction, const CoordinateXY& p0, const CoordinateXY& p1)
+ {
+ return { p0.x + segmentLengthFraction * (p1.x - p0.x),
+ p0.y + segmentLengthFraction * (p1.y - p0.y) };
+ }
+
+ static Coordinate pointAlong(double segmentLengthFraction, const Coordinate& p0, const Coordinate& p1)
+ {
+ return { p0.x + segmentLengthFraction * (p1.x - p0.x),
+ p0.y + segmentLengthFraction * (p1.y - p0.y),
+ p0.z + segmentLengthFraction * (p1.z - p0.z) };
+ }
+
+ static CoordinateXYM pointAlong(double segmentLengthFraction, const CoordinateXYM& p0, const CoordinateXYM& p1)
+ {
+ return { p0.x + segmentLengthFraction * (p1.x - p0.x),
+ p0.y + segmentLengthFraction * (p1.y - p0.y),
+ p0.m + segmentLengthFraction * (p1.m - p0.m) };
+ }
+
+ static CoordinateXYZM pointAlong(double segmentLengthFraction, const CoordinateXYZM& p0, const CoordinateXYZM& p1)
+ {
+ return { p0.x + segmentLengthFraction * (p1.x - p0.x),
+ p0.y + segmentLengthFraction * (p1.y - p0.y),
+ p0.z + segmentLengthFraction * (p1.z - p0.z),
+ p0.m + segmentLengthFraction * (p1.m - p0.m) };
+ }
+
/** \brief
* Computes the {@link Coordinate} that lies a given
* fraction along the line defined by this segment and offset from
-----------------------------------------------------------------------
Summary of changes:
include/geos/geom/CoordinateSequence.h | 28 +++++++++++++++++++
include/geos/geom/LineSegment.h | 28 +++++++++++++++++++
src/geom/util/Densifier.cpp | 29 ++++++++++----------
tests/unit/capi/GEOSDensifyTest.cpp | 14 ++++++++++
tests/unit/geom/CoordinateSequenceTest.cpp | 44 ++++++++++++++++++++++++++++++
5 files changed, 128 insertions(+), 15 deletions(-)
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list