From 2e44978ff371b70e2143807d52a7f1e7561a248f Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 15 Sep 2022 14:42:05 +0300 Subject: [PATCH] Add ear clipping simple polygon triangulation --- .../psemek/cg/triangulation/ear_clipping.hpp | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp diff --git a/libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp b/libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp new file mode 100644 index 00000000..afde9669 --- /dev/null +++ b/libs/cg/include/psemek/cg/triangulation/ear_clipping.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include + +#include + +namespace psemek::cg +{ + + template + void ear_clipping(Iterator begin, Iterator end, OutputIterator out) + { + IndexType const count = std::distance(begin, end); + + std::vector 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 + std::vector ear_clipping(Iterator begin, Iterator end) + { + std::vector result; + ear_clipping>, IndexType>(begin, end, std::back_inserter(result)); + return result; + } + +}