/** * \file Polygon.cpp * \brief a polygon class * \author Gapchich Vladislav, Sven Sickert * \date 23/10/2011 (07/10/2015) */ #include "vislearning/cbaselib/Polygon.h" using namespace OBJREC; using namespace std; using namespace NICE; //! A constructor Polygon::Polygon() { points_.clear(); id_ = -1; unique_id_ = -1; } // A copy-constructor Polygon::Polygon(const Polygon ©) { points_ = PointsList(*(copy.points())); id_ = copy.id(); unique_id_ = copy.unique_id_; } //! A desctructor Polygon::~Polygon() { } //! appends aPoint coordinate to the end of the point list void Polygon::push(const CoordT< int > &aPoint) { if (aPoint.x < 0 || aPoint.y < 0) { return; /* NOTREACHED */ } points_.push_back(aPoint); } //! overloaded /*! * \see push(const CoordT< int > &aPoint) */ void Polygon::push(const int &x, const int &y) { if (x < 0 || y < 0) { return; /* NOTREACHED */ } CoordT< int > point; point.x = x; point.y = y; points_.push_back(point); } //! Sets a category ID(label ID) for the polygon /*! * /param[in] anID should not be less than zero */ void Polygon::setID(const int &anID) { if (anID < 0) { return; /* NOTREACHED */ } this->id_ = anID; } //! returns a constant pointer to the list of polygon points(coordinates) const PointsList * Polygon::points() const { return &points_; } //! deletes last added point of the polygon and returns it CoordT< int > Polygon::pop() { CoordT< int > ret = points_.back(); points_.pop_back(); return ret; } //! returns a category ID of the polygon int Polygon::id() const { return id_; } // check whether point is inside polygon or not bool Polygon::handleEdge ( const int px, const int py, const int x1, const int y1, const int x2, const int y2, int & lastdir, int & c ) { if (py == y1) { if (px == x1) return true; if (y1 > y2) { if (lastdir == -1) // decreasing (cont.) if (x1 < px) c++; } if (y1 < y2) { if (lastdir == 1) // increasing (cont.) if (x1 < px) c++; } if (y1 == y2) { if ((x1 <= px) && (x2 >= px)) return true; } } if ( (y1 > py && y2 < py) || (y1 < py && y2 > py) ) { int xz = (int)( (py - y1) * (x2 - x1) / (y2 - y1) + x1 ); /* is point laying on the polygon curve? */ if (xz == px) return true; /* does the scanning line cut the polygon curve left of the point? */ if (xz < px) c++; } if (y2 > y1) lastdir = 1; if (y2 < y1) lastdir = -1; return false; } bool Polygon::insidePolygon ( const int &px, const int &py ) { int i, j, c = 0; int lastdir = 0; if ( points_.size() < 2 ) { cerr << "Polygon::insidePolygon: Not a valid Polygon curve" << endl; return false; } for ( PointsList::const_iterator i = points_.begin(); i != points_.end(); ++i ) { PointsList::const_iterator j = i; j++; if ( j == points_.end() ) j = points_.begin(); CoordT pi = *i; CoordT pj = *j; if (pj.y > pi.y) lastdir = 1; if (pj.y < pi.y) lastdir = -1; } if (lastdir == 0) { cerr << "Polygon::insidePolygon: Polygon is degenerated" << endl; return false; } for ( PointsList::const_iterator i = points_.begin(); i != points_.end(); ++i ) { PointsList::const_iterator j = i; j++; if ( j == points_.end() ) j = points_.begin(); CoordT pi = *i; CoordT pj = *j; if ( handleEdge( px, py, pi.x, pi.y, pj.x, pj.y, lastdir, c ) ) return false; } if (c & 1) return true; return false; } bool Polygon::insidePolygon ( const CoordT< int > &aPoint ) { if (aPoint.x < 0 || aPoint.y < 0) { cerr << "Polygon::insidePolygon(): point does not have valid coordinates" << endl; return false; } return insidePolygon ( aPoint.x, aPoint.y ); }