From 04078dbb3fe4acd09d150e016c2b2e0d5d036950 Mon Sep 17 00:00:00 2001
From: Dan Goodliffe <dan@randomdan.homeip.net>
Date: Sun, 5 Nov 2023 13:07:32 +0000
Subject: Add methods to walk the boundary of the terrain mesh

---
 game/geoData.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++
 game/geoData.h   |  6 ++++++
 2 files changed, 51 insertions(+)

(limited to 'game')

diff --git a/game/geoData.cpp b/game/geoData.cpp
index c58658a..f9c11bf 100644
--- a/game/geoData.cpp
+++ b/game/geoData.cpp
@@ -218,6 +218,43 @@ GeoData::walkUntil(const PointFace & from, const glm::vec2 to, const std::functi
 	}
 }
 
+void
+GeoData::boundaryWalk(const std::function<void(HalfedgeHandle)> & op) const
+{
+	boundaryWalk(op, findBoundaryStart());
+}
+
+void
+GeoData::boundaryWalk(const std::function<void(HalfedgeHandle)> & op, HalfedgeHandle start) const
+{
+	assert(is_boundary(start));
+	boundaryWalkUntil(
+			[&op](auto heh) {
+		op(heh);
+				return false;
+			},
+			start);
+}
+
+void
+GeoData::boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> & op) const
+{
+	boundaryWalkUntil(op, findBoundaryStart());
+}
+
+void
+GeoData::boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> & op, HalfedgeHandle start) const
+{
+	assert(is_boundary(start));
+	if (!op(start)) {
+		for (auto heh = next_halfedge_handle(start); heh != start; heh = next_halfedge_handle(heh)) {
+			if (op(heh)) {
+				break;
+			}
+		}
+	}
+}
+
 bool
 GeoData::triangleContainsPoint(const glm::vec2 p, const Triangle<2> & t)
 {
@@ -230,3 +267,11 @@ GeoData::triangleContainsPoint(const glm::vec2 p, FaceHandle face) const
 {
 	return triangleContainsPoint(p, triangle<2>(face));
 }
+
+GeoData::HalfedgeHandle
+GeoData::findBoundaryStart() const
+{
+	return *std::find_if(halfedges_begin(), halfedges_end(), [this](const auto heh) {
+		return is_boundary(heh);
+	});
+}
diff --git a/game/geoData.h b/game/geoData.h
index b8561d0..15d7e24 100644
--- a/game/geoData.h
+++ b/game/geoData.h
@@ -78,6 +78,11 @@ public:
 	void walk(const PointFace & from, const glm::vec2 to, const std::function<void(FaceHandle)> & op) const;
 	void walkUntil(const PointFace & from, const glm::vec2 to, const std::function<bool(FaceHandle)> & op) const;
 
+	void boundaryWalk(const std::function<void(HalfedgeHandle)> &) const;
+	void boundaryWalk(const std::function<void(HalfedgeHandle)> &, HalfedgeHandle start) const;
+	void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &) const;
+	void boundaryWalkUntil(const std::function<bool(HalfedgeHandle)> &, HalfedgeHandle start) const;
+
 	[[nodiscard]] auto
 	getExtents() const
 	{
@@ -94,6 +99,7 @@ protected:
 
 	[[nodiscard]] static bool triangleContainsPoint(const glm::vec2, const Triangle<2> &);
 	[[nodiscard]] bool triangleContainsPoint(const glm::vec2, FaceHandle) const;
+	[[nodiscard]] HalfedgeHandle findBoundaryStart() const;
 
 private:
 	glm::vec3 lowerExtent {}, upperExtent {};
-- 
cgit v1.2.3