#ifndef slic3r_Polygon_hpp_
#define slic3r_Polygon_hpp_

#include <myinit.h>
#include <vector>
#include "Line.hpp"
#include "MultiPoint.hpp"
#include "Polyline.hpp"

namespace Slic3r {

class Polygon : public MultiPoint {
    public:
    Point* last_point() const;
    SV* to_SV_ref();
    SV* to_SV_clone_ref() const;
    Lines lines() const;
    Polyline* split_at(const Point* point);
    Polyline* split_at_index(int index);
    Polyline* split_at_first_point();
    double area() const;
    bool is_counter_clockwise() const;
    bool is_clockwise() const;
    bool make_counter_clockwise();
    bool make_clockwise();
    bool is_valid() const;
    
    #ifndef NOBOOST
    bool encloses_point(Point* point) const;
    void push_back(const Point& point);
    typedef const Point& const_reference;
    #endif
};

typedef std::vector<Polygon> Polygons;

}

#ifndef NOBOOST
#include <boost/geometry/geometries/register/ring.hpp>
BOOST_GEOMETRY_REGISTER_RING(Polygon);

#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/closure.hpp>
namespace boost { namespace geometry { namespace traits {
    template<>
    struct point_order<Polygon>
    {
        static const order_selector value = counterclockwise;
    };
    
    template <>
    struct closure<Polygon>
    {
        static const closure_selector value = open;
    };
}}}

#include <boost/range.hpp>
namespace boost
{
    template<>
    struct range_iterator<Polygon>
    { typedef Points::iterator type; };

    template<>
    struct range_const_iterator<Polygon>
    { typedef Points::const_iterator type; };
}

namespace Slic3r {
    inline Points::iterator
    range_begin(Polygon& poly) {return poly.points.begin();}
    
    inline Points::iterator
    range_end(Polygon& poly) {return poly.points.end();}
    
    inline Points::const_iterator
    range_begin(const Polygon& poly) {return poly.points.begin();}
    
    inline Points::const_iterator
    range_end(const Polygon& poly) {return poly.points.end();}
}
#endif

#endif
