86 lines
2.2 KiB
C++
86 lines
2.2 KiB
C++
#pragma once
|
|
|
|
#include <psemek/geom/point.hpp>
|
|
#include <psemek/geom/vector.hpp>
|
|
|
|
namespace psemek::cg
|
|
{
|
|
|
|
template <typename Iterator>
|
|
auto polygon_area(Iterator begin, Iterator end)
|
|
{
|
|
using scalar_type = std::remove_cvref_t<decltype((*begin)[0])>;
|
|
scalar_type result{};
|
|
|
|
using point_type = std::remove_cvref_t<decltype(*begin)>;
|
|
auto origin = point_type::zero();
|
|
|
|
for (auto it = begin, prev = std::prev(end); it != end; prev = it++)
|
|
{
|
|
result += geom::volume(origin, *prev, *it);
|
|
}
|
|
|
|
return result / scalar_type{2};
|
|
}
|
|
|
|
template <typename Iterator, typename Point>
|
|
auto polygon_inertia(Iterator begin, Iterator end, Point const & origin)
|
|
{
|
|
using scalar_type = std::remove_cvref_t<decltype((*begin)[0])>;
|
|
scalar_type result{};
|
|
|
|
for (auto it = begin, prev = std::prev(end); it != end; prev = it++)
|
|
{
|
|
auto const v0 = *prev - origin;
|
|
auto const v1 = *it - origin;
|
|
result += (v1[1] - v0[1]) * (v0[0] * v0[0] * v0[0] + v0[0] * v0[0] * v1[0] + v0[0] * v1[0] * v1[0] + v1[0] * v1[0] * v1[0]);
|
|
result -= (v1[0] - v0[0]) * (v0[1] * v0[1] * v0[1] + v0[1] * v0[1] * v1[1] + v0[1] * v1[1] * v1[1] + v1[1] * v1[1] * v1[1]);
|
|
}
|
|
|
|
return result / scalar_type{12};
|
|
}
|
|
|
|
template <typename Iterator>
|
|
auto polygon_center(Iterator begin, Iterator end)
|
|
{
|
|
auto const first = *begin;
|
|
|
|
auto offset = decltype(*begin - *begin)::zero();
|
|
|
|
std::size_t count = 0;
|
|
|
|
for (; begin != end; ++begin)
|
|
{
|
|
offset += *begin - first;
|
|
++count;
|
|
}
|
|
|
|
using scalar_type = std::remove_cvref_t<decltype((*begin)[0])>;
|
|
return first + offset / static_cast<scalar_type>(count);
|
|
}
|
|
|
|
template <typename Iterator>
|
|
auto polygon_mass_center(Iterator begin, Iterator end)
|
|
{
|
|
using scalar_type = std::remove_cvref_t<decltype((*begin)[0])>;
|
|
using result_type = std::remove_cvref_t<decltype(*begin)>;
|
|
|
|
auto result = result_type::zero();
|
|
|
|
for (auto it = begin, prev = std::prev(end); it != end; prev = it++)
|
|
{
|
|
auto const v0 = *prev;
|
|
auto const v1 = *it;
|
|
result[0] += (v1[1] - v0[1]) * (v0[0] * v0[0] + v0[0] * v1[0] + v1[0] * v1[0]);
|
|
result[1] -= (v1[0] - v0[0]) * (v0[1] * v0[1] + v0[1] * v1[1] + v1[1] * v1[1]);
|
|
}
|
|
|
|
scalar_type a = polygon_area(begin, end) * 6;
|
|
|
|
result[0] /= a;
|
|
result[1] /= a;
|
|
|
|
return result;
|
|
}
|
|
|
|
}
|