Add ear clipping simple polygon triangulation
This commit is contained in:
parent
208a6f0e8b
commit
2e44978ff3
1 changed files with 74 additions and 0 deletions
74
libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp
Normal file
74
libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/geom/point.hpp>
|
||||||
|
#include <psemek/geom/orientation.hpp>
|
||||||
|
#include <psemek/geom/contains.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace psemek::cg
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Iterator, typename OutputIterator, typename IndexType = std::size_t>
|
||||||
|
void ear_clipping(Iterator begin, Iterator end, OutputIterator out)
|
||||||
|
{
|
||||||
|
IndexType const count = std::distance(begin, end);
|
||||||
|
|
||||||
|
std::vector<IndexType> next(count, 0);
|
||||||
|
|
||||||
|
for (IndexType i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
next[i] = (i + 1) % count;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexType j = 0;
|
||||||
|
for (IndexType i = 0; i + 2 < count; ++i)
|
||||||
|
{
|
||||||
|
for (;; j = (j + 1) % count)
|
||||||
|
{
|
||||||
|
if (next[j] == j) continue;
|
||||||
|
|
||||||
|
bool ear = true;
|
||||||
|
|
||||||
|
auto l = next[j];
|
||||||
|
auto h = next[l];
|
||||||
|
|
||||||
|
geom::simplex triangle{*(begin + j), *(begin + l), *(begin + h)};
|
||||||
|
|
||||||
|
if (geom::orientation(triangle[0], triangle[1], triangle[2]) == geom::sign_t::negative)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (IndexType k = next[h]; k != j; k = next[k])
|
||||||
|
{
|
||||||
|
if (geom::contains(triangle, *(begin + k)))
|
||||||
|
{
|
||||||
|
ear = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ear)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*out++ = j;
|
||||||
|
*out++ = l;
|
||||||
|
*out++ = h;
|
||||||
|
|
||||||
|
next[l] = l;
|
||||||
|
|
||||||
|
next[j] = h;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IndexType, typename Iterator>
|
||||||
|
std::vector<IndexType> ear_clipping(Iterator begin, Iterator end)
|
||||||
|
{
|
||||||
|
std::vector<IndexType> result;
|
||||||
|
ear_clipping<Iterator, std::back_insert_iterator<std::vector<IndexType>>, IndexType>(begin, end, std::back_inserter(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue