Polygon.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /**
  2. * \file Polygon.cpp
  3. * \brief a polygon class
  4. * \author Gapchich Vladislav, Sven Sickert
  5. * \date 23/10/2011 (07/10/2015)
  6. */
  7. #include "vislearning/cbaselib/Polygon.h"
  8. using namespace OBJREC;
  9. using namespace std;
  10. using namespace NICE;
  11. //! A constructor
  12. Polygon::Polygon()
  13. {
  14. points_.clear();
  15. id_ = -1;
  16. unique_id_ = -1;
  17. }
  18. // A copy-constructor
  19. Polygon::Polygon(const Polygon &copy)
  20. {
  21. points_ = PointsList(*(copy.points()));
  22. id_ = copy.id();
  23. unique_id_ = copy.unique_id_;
  24. }
  25. //! A desctructor
  26. Polygon::~Polygon()
  27. {
  28. }
  29. //! appends aPoint coordinate to the end of the point list
  30. void
  31. Polygon::push(const CoordT< int > &aPoint)
  32. {
  33. if (aPoint.x < 0 || aPoint.y < 0) {
  34. return;
  35. /* NOTREACHED */
  36. }
  37. points_.push_back(aPoint);
  38. }
  39. //! overloaded
  40. /*!
  41. * \see push(const CoordT< int > &aPoint)
  42. */
  43. void
  44. Polygon::push(const int &x, const int &y)
  45. {
  46. if (x < 0 || y < 0) {
  47. return;
  48. /* NOTREACHED */
  49. }
  50. CoordT< int > point;
  51. point.x = x;
  52. point.y = y;
  53. points_.push_back(point);
  54. }
  55. //! Sets a category ID(label ID) for the polygon
  56. /*!
  57. * /param[in] anID should not be less than zero
  58. */
  59. void
  60. Polygon::setID(const int &anID)
  61. {
  62. if (anID < 0) {
  63. return;
  64. /* NOTREACHED */
  65. }
  66. this->id_ = anID;
  67. }
  68. //! returns a constant pointer to the list of polygon points(coordinates)
  69. const PointsList *
  70. Polygon::points() const
  71. {
  72. return &points_;
  73. }
  74. //! deletes last added point of the polygon and returns it
  75. CoordT< int >
  76. Polygon::pop()
  77. {
  78. CoordT< int > ret = points_.back();
  79. points_.pop_back();
  80. return ret;
  81. }
  82. //! returns a category ID of the polygon
  83. int
  84. Polygon::id() const
  85. {
  86. return id_;
  87. }
  88. // check whether point is inside polygon or not
  89. bool
  90. Polygon::handleEdge ( const int px, const int py,
  91. const int x1, const int y1,
  92. const int x2, const int y2,
  93. int & lastdir, int & c )
  94. {
  95. if (py == y1)
  96. {
  97. if (px == x1) return true;
  98. if (y1 > y2)
  99. {
  100. if (lastdir == -1) // decreasing (cont.)
  101. if (x1 < px) c++;
  102. }
  103. if (y1 < y2)
  104. {
  105. if (lastdir == 1) // increasing (cont.)
  106. if (x1 < px) c++;
  107. }
  108. if (y1 == y2)
  109. {
  110. if ((x1 <= px) && (x2 >= px)) return true;
  111. }
  112. }
  113. if ( (y1 > py && y2 < py) || (y1 < py && y2 > py) )
  114. {
  115. int xz = (int)( (py - y1) * (x2 - x1) / (y2 - y1) + x1 );
  116. /* is point laying on the polygon curve? */
  117. if (xz == px) return true;
  118. /* does the scanning line cut the polygon curve left of the point? */
  119. if (xz < px) c++;
  120. }
  121. if (y2 > y1) lastdir = 1;
  122. if (y2 < y1) lastdir = -1;
  123. return false;
  124. }
  125. bool
  126. Polygon::insidePolygon ( const int &px, const int &py )
  127. {
  128. int i, j, c = 0;
  129. int lastdir = 0;
  130. if ( points_.size() < 2 )
  131. {
  132. cerr << "Polygon::insidePolygon: Not a valid Polygon curve" << endl;
  133. return false;
  134. }
  135. for ( PointsList::const_iterator i = points_.begin();
  136. i != points_.end(); ++i )
  137. {
  138. PointsList::const_iterator j = i;
  139. j++;
  140. if ( j == points_.end() ) j = points_.begin();
  141. CoordT<int> pi = *i;
  142. CoordT<int> pj = *j;
  143. if (pj.y > pi.y) lastdir = 1;
  144. if (pj.y < pi.y) lastdir = -1;
  145. }
  146. if (lastdir == 0)
  147. {
  148. cerr << "Polygon::insidePolygon: Polygon is degenerated" << endl;
  149. return false;
  150. }
  151. for ( PointsList::const_iterator i = points_.begin();
  152. i != points_.end(); ++i )
  153. {
  154. PointsList::const_iterator j = i;
  155. j++;
  156. if ( j == points_.end() ) j = points_.begin();
  157. CoordT<int> pi = *i;
  158. CoordT<int> pj = *j;
  159. if ( handleEdge( px, py, pi.x, pi.y, pj.x, pj.y, lastdir, c ) )
  160. return false;
  161. }
  162. if (c & 1) return true;
  163. return false;
  164. }
  165. bool
  166. Polygon::insidePolygon ( const CoordT< int > &aPoint )
  167. {
  168. if (aPoint.x < 0 || aPoint.y < 0) {
  169. cerr << "Polygon::insidePolygon(): point does not have valid coordinates"
  170. << endl;
  171. return false;
  172. }
  173. return insidePolygon ( aPoint.x, aPoint.y );
  174. }