Add ear clipping simple polygon triangulation

This commit is contained in:
Nikita Lisitsa 2022-09-15 14:42:05 +03:00
parent 208a6f0e8b
commit 2e44978ff3

View 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;
}
}