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