Make cg::triangulation & cg::delaunay return dcel with nothing but connectivity data and using the input vertex order

This commit is contained in:
Nikita Lisitsa 2022-09-16 19:40:27 +03:00
parent 0fe4477097
commit 83f1ac4202
2 changed files with 30 additions and 28 deletions

View file

@ -13,6 +13,8 @@ namespace psemek::cg
{
std::vector<Index> edge_queue;
auto at = [&](Index i){ return *(begin + i); };
auto callback = [&](auto & dcel, auto p)
{
auto outer_face = dcel.face(0);
@ -58,7 +60,7 @@ namespace psemek::cg
auto p3 = e.twin().next().next().origin();
// decide if a flip is needed
if (in_circle(robust_tag, *p0.data(), *p1.data(), *p2.data(), *p3.data()) != 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;
auto f0 = e.face();
auto f1 = twin.face();

View file

@ -19,16 +19,20 @@ namespace psemek::cg
using point_type = std::decay_t<decltype(*begin)>;
static_assert(point_type::static_dimension == 2);
using dcel_type = dcel<Iterator, util::empty, util::empty, Index>;
Index const count = std::distance(begin, end);
auto at = [begin](Index i){ return *(begin + i); };
std::vector<Index> sweepline_events;
sweepline_events.resize(count);
std::iota(sweepline_events.begin(), sweepline_events.end(), Index{0});
std::sort(sweepline_events.begin(), sweepline_events.end(), [&](auto i, auto j){ return at(i) < at(j); });
using dcel_type = dcel<util::empty, util::empty, util::empty, Index>;
dcel_type result;
std::vector<Iterator> sweepline_events;
sweepline_events.resize(std::distance(begin, end));
std::iota(sweepline_events.begin(), sweepline_events.end(), begin);
std::sort(sweepline_events.begin(), sweepline_events.end(), [](auto it, auto jt){ return *it < *jt; });
auto it = sweepline_events.begin();
for (auto it = begin; it != end; ++it)
result.push_point();
auto outer_face = result.push_face();
@ -36,23 +40,19 @@ namespace psemek::cg
if (sweepline_events.empty()) return result;
if (sweepline_events.size() == 1)
{
result.push_point(*it++);
return result;
}
{
auto const N = sweepline_events.size();
result.points.reserve(N);
result.edges.reserve(3*(N-1));
result.faces.reserve(2*(N-1));
}
result.points.reserve(count);
result.edges.reserve(3 * (count - 1));
result.faces.reserve(2 * (count - 1));
auto it = sweepline_events.begin();
typename dcel_type::edge_handle hull_start;
{
auto p0 = result.push_point(*it++);
auto p1 = result.push_point(*it++);
auto p0 = result.point(*it++);
auto p1 = result.point(*it++);
auto e01 = result.push_edge();
auto e10 = result.push_edge();
@ -93,7 +93,7 @@ namespace psemek::cg
bool degenerate = false;
// find first hull edge visible from new point
while (orientation(robust_tag, **it, *hp0.data(), *hp1.data()) != geom::sign_t::positive)
while (orientation(robust_tag, at(*it), at(hp0.index()), at(hp1.index())) != geom::sign_t::positive)
{
move_hull_edge();
if (cur_hull_edge == hull_start)
@ -115,8 +115,8 @@ namespace psemek::cg
// find rightmost point
for (Index i = 1; i < result.points.size(); ++i)
{
auto const x = (*result.points[i].data())[0];
auto const qx = (*q.data())[0];
auto const x = at(i)[0];
auto const qx = at(q.index())[0];
if (x == qx)
{
@ -137,8 +137,8 @@ namespace psemek::cg
for (Index i = 1; i < result.points.size(); ++i)
{
auto const y = (*result.points[i].data())[1];
auto const qy = (*q.data())[1];
auto const y = at(i)[1];
auto const qy = at(q.index())[1];
if (y > qy)
{
@ -147,7 +147,7 @@ namespace psemek::cg
}
}
auto p = result.push_point(*it);
auto p = result.point(*it);
auto qnext = q.edge();
auto qprev = qnext.twin();
@ -172,7 +172,7 @@ namespace psemek::cg
continue;
}
auto p = result.push_point(*it);
auto p = result.point(*it);
auto mid_edge = result.push_edge();
mid_edge.origin(hp0);
@ -192,7 +192,7 @@ namespace psemek::cg
}
// until current edge is visible
while (orientation(robust_tag, **it, *hp0.data(), *hp1.data()) == geom::sign_t::positive)
while (orientation(robust_tag, at(*it), at(hp0.index()), at(hp1.index())) == geom::sign_t::positive)
{
// fill new triangle