// Copyright (C) 2022 Davis E. King (davis@dlib.net), AdriĆ Arrufat
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_POLYGOn_
#define DLIB_POLYGOn_
#include "polygon_abstract.h"
#include "rectangle.h"
#include "vector.h"
namespace dlib
{
class polygon
{
public:
using size_type = std::vector<point>::size_type;
polygon(std::vector<point> points) : points(std::move(points)) {}
size_type size() const { return points.size(); }
point& operator[](const size_type idx) { return points[idx]; }
const point& operator[](const size_type idx) const { return points[idx]; }
const point& at(const size_type idx) const { return points.at(idx); }
std::vector<point>::iterator begin() { return points.begin(); }
std::vector<point>::iterator end() { return points.end(); }
const std::vector<point>::const_iterator begin() const { return points.begin(); }
const std::vector<point>::const_iterator end() const { return points.end(); }
rectangle get_rect() const
{
rectangle rect;
for (const auto& p : points)
rect += p;
return rect;
}
double area() const { return polygon_area(points); }
template <typename alloc>
void get_left_and_right_bounds (
const long top,
const long bottom,
std::vector<double, alloc>& left_boundary,
std::vector<double, alloc>& right_boundary
) const
{
using std::min;
using std::max;
left_boundary.assign(bottom-top+1, std::numeric_limits<double>::infinity());
right_boundary.assign(bottom-top+1, -std::numeric_limits<double>::infinity());
// trace out the points along the edge of the polynomial and record them
for (unsigned long i = 0; i < points.size(); ++i)
{
const point p1 = points[i];
const point p2 = points[(i+1)%points.size()];
if (p1.y() == p2.y())
{
if (top <= p1.y() && p1.y() <= bottom)
{
const long y = p1.y() - top;
const double xmin = min(p1.x(), p2.x());
const double xmax = min(p1.x(), p2.x());
left_boundary[y] = min(left_boundary[y], xmin);
right_boundary[y] = max(right_boundary[y], xmax);
}
}
else
{
// Here we trace out the line from p1 to p2 and record where it hits.
// x = m*y + b
const double m = (p2.x() - p1.x())/(double)(p2.y()-p1.y());
const double b = p1.x() - m*p1.y(); // because: x1 = m*y1 + b
const long ymin = max(top,min(p1.y(), p2.y()));
const long ymax = min(bottom,max(p1.y(), p2.y()));
for (long y = ymin; y <= ymax; ++y)
{
const double x = m*y + b;
const unsigned long idx = y-top;
left_boundary[idx] = min(left_boundary[idx], x);
right_boundary[idx] = max(right_boundary[idx], x);
}
}
}
}
private:
std::vector<point> points;
};
}
#endif // polygon_h_INCLUDED