psemek/libs/cg/include/psemek/cg/area.hpp

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