Rewrite ear-clipping triangulation to output dcel
This commit is contained in:
parent
34d9e67960
commit
51e6f8ad9c
2 changed files with 75 additions and 61 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include <psemek/cg/bbox.hpp>
|
||||
#include <psemek/cg/triangulation/ear_clipping.hpp>
|
||||
#include <psemek/cg/triangulation/monotone.hpp>
|
||||
#include <psemek/cg/triangulation/delaunay.hpp>
|
||||
#include <psemek/log/log.hpp>
|
||||
#include <psemek/prof/profiler.hpp>
|
||||
#include <psemek/util/clock.hpp>
|
||||
|
|
@ -62,12 +63,15 @@ struct triangulation_app
|
|||
|
||||
{
|
||||
prof::profiler prof("triangulate");
|
||||
indices_ = cg::ear_clipping<std::uint16_t>(points_.begin(), points_.end());
|
||||
|
||||
auto dcel = cg::ear_clipping<std::uint16_t>(geom::fast, points_.begin(), points_.end());
|
||||
edges_ = cg::edge_mesh(dcel);
|
||||
triangles_ = cg::triangle_mesh(dcel);
|
||||
}
|
||||
|
||||
prof::dump();
|
||||
|
||||
log::info() << (indices_.size() / 3) << " triangles";
|
||||
log::info() << (triangles_.size() / 3) << " triangles";
|
||||
}
|
||||
|
||||
void on_left_button_down() override
|
||||
|
|
@ -117,23 +121,21 @@ struct triangulation_app
|
|||
|
||||
auto edge = [this, line_width](auto i0, auto i1, gfx::color_rgba const & color)
|
||||
{
|
||||
painter_.line(points_[i0], points_[i1], line_width, color, false);
|
||||
painter_.line(points_[i0], points_[i1], line_width, color, true);
|
||||
};
|
||||
|
||||
random::generator rng;
|
||||
for (std::size_t i = 0; i < indices_.size(); i += 3)
|
||||
for (auto const & e : edges_)
|
||||
edge(e[0], e[1], gfx::black);
|
||||
for (auto const & t : triangles_)
|
||||
{
|
||||
// edge(indices_[i + 0], indices_[i + 1], gfx::blue);
|
||||
// edge(indices_[i + 1], indices_[i + 2], gfx::blue);
|
||||
// edge(indices_[i + 2], indices_[i + 0], gfx::blue);
|
||||
|
||||
gfx::color_rgba c;
|
||||
c[0] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||
c[1] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||
c[2] = random::uniform<std::uint8_t>(rng, {0, 255});
|
||||
c[3] = 255;
|
||||
|
||||
painter_.triangle(points_[indices_[i + 0]], points_[indices_[i + 1]], points_[indices_[i + 2]], c);
|
||||
painter_.triangle(points_[t[0]], points_[t[1]], points_[t[2]], c);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < points_.size(); ++i)
|
||||
|
|
@ -144,28 +146,12 @@ struct triangulation_app
|
|||
auto camera_transform = geom::orthographic_camera{view_bbox}.transform();
|
||||
|
||||
painter_.render(camera_transform);
|
||||
|
||||
if(false)
|
||||
for (std::size_t i = 0; i < points_.size(); ++i)
|
||||
// for (std::size_t i : {2993, 2087, 2089, 2088})
|
||||
{
|
||||
gfx::painter::text_options opts;
|
||||
opts.c = {0, 0, 0, 255};
|
||||
opts.x = gfx::painter::x_align::left;
|
||||
opts.y = gfx::painter::y_align::bottom;
|
||||
opts.scale = 2.f;
|
||||
auto p = geom::swizzle<0, 1>(geom::as_point(camera_transform * geom::homogeneous(geom::swizzle<0, 1, -1>(points_[i]))));
|
||||
p[0] = std::round((p[0] * 0.5f + 0.5f) * width());
|
||||
p[1] = std::round((0.5f - p[1] * 0.5f) * height());
|
||||
painter_.text(p, util::to_string(i), opts);
|
||||
}
|
||||
|
||||
painter_.render(geom::window_camera{width(), height()}.transform());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<geom::point<float, 2>> points_;
|
||||
std::vector<std::uint16_t> indices_;
|
||||
std::vector<geom::segment<std::uint16_t>> edges_;
|
||||
std::vector<geom::triangle<std::uint16_t>> triangles_;
|
||||
geom::box<float, 2> bbox_;
|
||||
geom::point<float, 2> camera_center_;
|
||||
float camera_size_;
|
||||
|
|
|
|||
|
|
@ -3,44 +3,68 @@
|
|||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/orientation.hpp>
|
||||
#include <psemek/geom/contains.hpp>
|
||||
#include <psemek/cg/dcel.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace psemek::cg
|
||||
{
|
||||
|
||||
template <typename IndexType = std::size_t, typename RobustTag, typename Iterator, typename OutputIterator>
|
||||
OutputIterator ear_clipping(RobustTag robust_tag, Iterator begin, Iterator end, OutputIterator out)
|
||||
template <typename IndexType = std::size_t, typename RobustTag, typename Iterator>
|
||||
auto ear_clipping(RobustTag robust_tag, Iterator begin, Iterator end)
|
||||
{
|
||||
IndexType const count = std::distance(begin, end);
|
||||
|
||||
std::vector<IndexType> next(count, 0);
|
||||
auto at = [begin](IndexType i){ return *(begin + i); };
|
||||
|
||||
using dcel_type = dcel<util::empty, util::empty, util::empty, IndexType>;
|
||||
|
||||
dcel_type result;
|
||||
|
||||
auto outer_face = result.push_face();
|
||||
auto inner_face = result.push_face();
|
||||
|
||||
result.faces[inner_face.index()].edge = 0;
|
||||
result.faces[outer_face.index()].edge = count;
|
||||
|
||||
result.points.resize(count);
|
||||
result.edges.resize(2 * count);
|
||||
|
||||
for (IndexType i = 0; i < count; ++i)
|
||||
{
|
||||
next[i] = (i + 1) % count;
|
||||
result.points[i].edge = i;
|
||||
|
||||
result.edges[i].face = 1;
|
||||
result.edges[i].origin = i;
|
||||
result.edges[i].prev = (i + count - 1) % count;
|
||||
result.edges[i].next = (i + 1) % count;
|
||||
result.edges[i].twin = i + count;
|
||||
|
||||
result.edges[i + count].face = 0;
|
||||
result.edges[i + count].origin = (i + 1) % count;
|
||||
result.edges[i + count].prev = count + (i + 1) % count;
|
||||
result.edges[i + count].next = count + (i + count - 1) % count;
|
||||
result.edges[i + count].twin = i;
|
||||
}
|
||||
|
||||
IndexType j = 0;
|
||||
for (IndexType i = 0; i + 2 < count; ++i)
|
||||
auto edge = result.edge(0);
|
||||
for (IndexType i = 0; i + 3 < count; ++i)
|
||||
{
|
||||
for (;; j = (j + 1) % count)
|
||||
for (;; edge = edge.next())
|
||||
{
|
||||
if (next[j] == j) continue;
|
||||
|
||||
bool ear = true;
|
||||
|
||||
auto l = next[j];
|
||||
auto h = next[l];
|
||||
auto next = edge.next();
|
||||
auto nnext = next.next();
|
||||
|
||||
geom::simplex triangle{*(begin + j), *(begin + l), *(begin + h)};
|
||||
geom::simplex triangle{at(edge.origin().index()), at(next.origin().index()), at(nnext.origin().index())};
|
||||
|
||||
if (geom::orientation(robust_tag, triangle[0], triangle[1], triangle[2]) == geom::sign_t::negative)
|
||||
continue;
|
||||
|
||||
for (IndexType k = next[h]; k != j; k = next[k])
|
||||
for (auto k = nnext.next(); k != edge; k = k.next())
|
||||
{
|
||||
if (geom::contains(triangle, *(begin + k)))
|
||||
if (geom::contains(triangle, at(k.origin().index())))
|
||||
{
|
||||
ear = false;
|
||||
break;
|
||||
|
|
@ -50,36 +74,40 @@ namespace psemek::cg
|
|||
if (!ear)
|
||||
continue;
|
||||
|
||||
*out++ = j;
|
||||
*out++ = l;
|
||||
*out++ = h;
|
||||
auto ein = result.push_edge();
|
||||
auto eout = result.push_edge();
|
||||
auto prev = edge.prev();
|
||||
|
||||
next[l] = l;
|
||||
auto face = result.push_face();
|
||||
|
||||
next[j] = h;
|
||||
face.edge(ein);
|
||||
ein.face(face);
|
||||
edge.face(face);
|
||||
next.face(face);
|
||||
|
||||
ein.origin(nnext.origin());
|
||||
ein.prev(next); next.next(ein);
|
||||
ein.next(edge); edge.prev(ein);
|
||||
ein.twin(eout);
|
||||
|
||||
eout.origin(edge.origin());
|
||||
eout.prev(prev); prev.next(eout);
|
||||
eout.next(nnext); nnext.prev(eout);
|
||||
eout.twin(ein);
|
||||
|
||||
inner_face.edge(eout);
|
||||
eout.face(inner_face);
|
||||
|
||||
edge = eout;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename IndexType = std::size_t, typename Iterator, typename OutputIterator>
|
||||
OutputIterator ear_clipping(Iterator begin, Iterator end, OutputIterator out)
|
||||
{
|
||||
return ear_clipping<IndexType>(geom::default_robust_tag, begin, end, out);
|
||||
}
|
||||
|
||||
template <typename IndexType, typename RobustTag, typename Iterator>
|
||||
std::vector<IndexType> ear_clipping(RobustTag robust_tag, Iterator begin, Iterator end)
|
||||
{
|
||||
std::vector<IndexType> result;
|
||||
ear_clipping<IndexType>(robust_tag, begin, end, std::back_inserter(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename IndexType, typename Iterator>
|
||||
template <typename IndexType = std::size_t, typename Iterator>
|
||||
auto ear_clipping(Iterator begin, Iterator end)
|
||||
{
|
||||
return ear_clipping<IndexType>(geom::default_robust_tag, begin, end);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue