// 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