From b4576e3a40d0416dea4e82042905598680fba3ee Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 15 Dec 2024 15:00:08 +0000 Subject: Reuse close edges when adding new vertices for surface --- game/geoData.cpp | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'game/geoData.cpp') diff --git a/game/geoData.cpp b/game/geoData.cpp index a5fc4ef..d3b5485 100644 --- a/game/geoData.cpp +++ b/game/geoData.cpp @@ -430,6 +430,19 @@ GeoData::setHeights(const std::span triangleStrip, const return std::make_pair(v, glm::length(::difference(p, this->point(v).xy()))); }; }; + const auto vertexDistFromE = [this](GlobalPosition2D p) { + return [p, this](const HalfedgeHandle e) { + const auto fromPoint = point(from_vertex_handle(e)).xy(); + const auto toPoint = point(to_vertex_handle(e)).xy(); + return std::make_pair(e, Triangle<2> {fromPoint, toPoint, p}.height()); + }; + }; + const auto notBoundary = std::views::filter([this](auto handleItr) { + return !is_boundary(*handleItr); + }); + const auto notEdgeBoundary = std::views::filter([this](auto handleItr) { + return !is_boundary(edge_handle(*handleItr)); + }); std::set newOrChangedVerts; auto addVertexForNormalUpdate = [this, &newOrChangedVerts](const VertexHandle vertex) { @@ -437,21 +450,32 @@ GeoData::setHeights(const std::span triangleStrip, const std::ranges::copy(vv_range(vertex), std::inserter(newOrChangedVerts, newOrChangedVerts.end())); }; - // New vertices for each vertex in triangleStrip std::vector newVerts; + auto newVertexOnFace = [this, &vertexDistFrom, &opts, &vertexDistFromE, &newVerts, ¬Boundary, ¬EdgeBoundary]( + GlobalPosition3D tsPoint) { + const auto face = findPoint(tsPoint); + // Check vertices + if (const auto nearest = std::ranges::min(std::views::iota(fv_begin(face), fv_end(face)) | notBoundary + | std::views::transform(vertexDistFrom(tsPoint)), + {}, &std::pair::second); + nearest.second < opts.nearNodeTolerance && !std::ranges::contains(newVerts, nearest.first)) { + point(nearest.first) = tsPoint; + return nearest.first; + } + // Check edges + if (const auto nearest = std::ranges::min(std::views::iota(fh_begin(face), fh_end(face)) | notEdgeBoundary + | std::views::transform(vertexDistFromE(tsPoint)), + {}, &std::pair::second); + nearest.second < opts.nearNodeTolerance) { + return split(edge_handle(nearest.first), tsPoint); + } + // Nothing close, split face + return split(face, tsPoint); + }; + + // New vertices for each vertex in triangleStrip newVerts.reserve(newVerts.size()); - std::transform(triangleStrip.begin(), triangleStrip.end(), std::back_inserter(newVerts), - [this, &newVerts, &vertexDistFrom, &opts](const auto tsPoint) { - const auto face = findPoint(tsPoint); - if (const auto nearest = std::ranges::min(std::views::iota(fv_begin(face), fv_end(face)) - | std::views::transform(vertexDistFrom(tsPoint)), - {}, &std::pair::second); - nearest.second < opts.nearNodeTolerance && !std::ranges::contains(newVerts, nearest.first)) { - point(nearest.first) = tsPoint; - return nearest.first; - } - return split(face, tsPoint); - }); + std::transform(triangleStrip.begin(), triangleStrip.end(), std::back_inserter(newVerts), newVertexOnFace); std::ranges::for_each(newVerts, addVertexForNormalUpdate); // Create temporary triangles from triangleStrip -- cgit v1.2.3