Fix cg::delaunay for some weird circular cases

This commit is contained in:
Nikita Lisitsa 2022-12-23 13:26:41 +03:00
parent eb33aa3b91
commit ee9847a904

View file

@ -4,6 +4,7 @@
#include <psemek/cg/triangulation/triangulation.hpp> #include <psemek/cg/triangulation/triangulation.hpp>
#include <queue> #include <queue>
#include <vector>
namespace psemek::cg namespace psemek::cg
{ {
@ -12,6 +13,7 @@ namespace psemek::cg
auto delaunay(RobustTag robust_tag, InputIterator begin, InputIterator end) auto delaunay(RobustTag robust_tag, InputIterator begin, InputIterator end)
{ {
std::vector<Index> edge_queue; std::vector<Index> edge_queue;
std::vector<Index> flipped_set;
auto at = [&](Index i){ return *(begin + i); }; auto at = [&](Index i){ return *(begin + i); };
@ -62,6 +64,8 @@ namespace psemek::cg
// decide if a flip is needed // decide if a flip is needed
if (in_circle(robust_tag, at(p0.index()), at(p1.index()), at(p2.index()), at(p3.index())) != geom::sign_t::positive) continue; if (in_circle(robust_tag, at(p0.index()), at(p1.index()), at(p2.index()), at(p3.index())) != geom::sign_t::positive) continue;
flipped_set.insert(std::lower_bound(flipped_set.begin(), flipped_set.end(), e.index()), e.index());
auto f0 = e.face(); auto f0 = e.face();
auto f1 = twin.face(); auto f1 = twin.face();
@ -81,15 +85,17 @@ namespace psemek::cg
tprev.face(f0); tprev.face(f0);
tprev.next(next); next.prev(tprev); tprev.next(next); next.prev(tprev);
p0.edge(prev);
p1.edge(tnext); p1.edge(tnext);
p2.edge(next); p2.edge(next);
p3.edge(tprev);
f0.edge(e); f0.edge(e);
f1.edge(twin); f1.edge(twin);
auto push = [&](auto e) auto push = [&](auto e)
{ {
if (e.twin().face() != outer_face) if (e.twin().face() != outer_face && !std::binary_search(flipped_set.begin(), flipped_set.end(), e.index()))
edge_queue.push_back(e.index()); edge_queue.push_back(e.index());
}; };
@ -98,6 +104,8 @@ namespace psemek::cg
push(tnext); push(tnext);
push(tprev); push(tprev);
} }
flipped_set.clear();
}; };
return detail::triangulate<Index>(robust_tag, begin, end, callback); return detail::triangulate<Index>(robust_tag, begin, end, callback);
} }