You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

simple_polygon.cpp 10 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright 2001 softSurfer, 2012 Dan Sunday
  2. // This code may be freely used and modified for any purpose
  3. // providing that this copyright notice is included with it.
  4. // SoftSurfer makes no warranty for this code, and cannot be held
  5. // liable for any real or imagined damage resulting from its use.
  6. // Users of this code must verify correctness for their application.
  7. // Assume that classes are already given for the objects:
  8. // Point with 2D coordinates {float x, y;}
  9. // Polygon with n vertices {int n; Point *V;} with V[n]=V[0]
  10. // Tnode is a node element structure for a BBT
  11. // BBT is a class for a Balanced Binary Tree
  12. // such as an AVL, a 2-3, or a red-black tree
  13. // with methods given by the placeholder code:
  14. typedef struct _BBTnode Tnode;
  15. struct _BBTnode {
  16. void* val;
  17. // plus node mgmt info ...
  18. };
  19. class BBT {
  20. Tnode *root;
  21. public:
  22. BBT() {root = (Tnode*)0;} // constructor
  23. ~BBT() {freetree();} // destructor
  24. Tnode* insert( void* ){}; // insert data into the tree
  25. Tnode* find( void* ){}; // find data from the tree
  26. Tnode* next( Tnode* ){}; // get next tree node
  27. Tnode* prev( Tnode* ){}; // get previous tree node
  28. void remove( Tnode* ){}; // remove node from the tree
  29. void freetree(){}; // free all tree data structs
  30. };
  31. // NOTE:
  32. // Code for these methods must be provided for the algorithm to work.
  33. // We have not provided it since binary tree algorithms are well-known
  34. // and code is widely available. Further, we want to reduce the clutter
  35. // accompanying the essential sweep line algorithm.
  36. //===================================================================
  37. #define FALSE 0
  38. #define TRUE 1
  39. #define LEFT 0
  40. #define RIGHT 1
  41. extern void
  42. qsort(void*, unsigned, unsigned, int(*)(const void*,const void*));
  43. // xyorder(): determines the xy lexicographical order of two points
  44. // returns: (+1) if p1 > p2; (-1) if p1 < p2; and 0 if equal
  45. int xyorder( Point* p1, Point* p2 )
  46. {
  47. // test the x-coord first
  48. if (p1->x > p2->x) return 1;
  49. if (p1->x < p2->x) return (-1);
  50. // and test the y-coord second
  51. if (p1->y > p2->y) return 1;
  52. if (p1->y < p2->y) return (-1);
  53. // when you exclude all other possibilities, what remains is...
  54. return 0; // they are the same point
  55. }
  56. // isLeft(): tests if point P2 is Left|On|Right of the line P0 to P1.
  57. // returns: >0 for left, 0 for on, and <0 for right of the line.
  58. // (see Algorithm 1 on Area of Triangles)
  59. inline float
  60. isLeft( Point P0, Point P1, Point P2 )
  61. {
  62. return (P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y);
  63. }
  64. //===================================================================
  65. // EventQueue Class
  66. // Event element data struct
  67. typedef struct _event Event;
  68. struct _event {
  69. int edge; // polygon edge i is V[i] to V[i+1]
  70. int type; // event type: LEFT or RIGHT vertex
  71. Point* eV; // event vertex
  72. };
  73. int E_compare( const void* v1, const void* v2 ) // qsort compare two events
  74. {
  75. Event** pe1 = (Event**)v1;
  76. Event** pe2 = (Event**)v2;
  77. return xyorder( (*pe1)->eV, (*pe2)->eV );
  78. }
  79. // the EventQueue is a presorted array (no insertions needed)
  80. class EventQueue {
  81. int ne; // total number of events in array
  82. int ix; // index of next event on queue
  83. Event* Edata; // array of all events
  84. Event** Eq; // sorted list of event pointers
  85. public:
  86. EventQueue(Polygon P); // constructor
  87. ~EventQueue(void) // destructor
  88. { delete Eq; delete Edata;}
  89. Event* next(); // next event on queue
  90. };
  91. // EventQueue Routines
  92. EventQueue::EventQueue( Polygon P )
  93. {
  94. ix = 0;
  95. ne = 2 * P.n; // 2 vertex events for each edge
  96. Edata = (Event*)new Event[ne];
  97. Eq = (Event**)new (Event*)[ne];
  98. for (int i=0; i < ne; i++) // init Eq array pointers
  99. Eq[i] = &Edata[i];
  100. // Initialize event queue with edge segment endpoints
  101. for (int i=0; i < P.n; i++) { // init data for edge i
  102. Eq[2*i]->edge = i;
  103. Eq[2*i+1]->edge = i;
  104. Eq[2*i]->eV = &(P.V[i]);
  105. Eq[2*i+1]->eV = &(P.V[i+1]);
  106. if (xyorder( &P.V[i], &P.V[i+1]) < 0) { // determine type
  107. Eq[2*i]->type = LEFT;
  108. Eq[2*i+1]->type = RIGHT;
  109. }
  110. else {
  111. Eq[2*i]->type = RIGHT;
  112. Eq[2*i+1]->type = LEFT;
  113. }
  114. }
  115. // Sort Eq[] by increasing x and y
  116. qsort( Eq, ne, sizeof(Event*), E_compare );
  117. }
  118. Event* EventQueue::next()
  119. {
  120. if (ix >= ne)
  121. return (Event*)0;
  122. else
  123. return Eq[ix++];
  124. }
  125. //===================================================================
  126. // SweepLine Class
  127. // SweepLine segment data struct
  128. typedef struct _SL_segment SLseg;
  129. struct _SL_segment {
  130. int edge; // polygon edge i is V[i] to V[i+1]
  131. Point lP; // leftmost vertex point
  132. Point rP; // rightmost vertex point
  133. SLseg* above; // segment above this one
  134. SLseg* below; // segment below this one
  135. };
  136. // the Sweep Line itself
  137. class SweepLine {
  138. int nv; // number of vertices in polygon
  139. Polygon* Pn; // initial Polygon
  140. BBT Tree; // balanced binary tree
  141. public:
  142. SweepLine(Polygon P) // constructor
  143. { nv = P.n; Pn = &P; }
  144. ~SweepLine(void) // destructor
  145. { Tree.freetree();}
  146. SLseg* add( Event* );
  147. SLseg* find( Event* );
  148. int intersect( SLseg*, SLseg* );
  149. void remove( SLseg* );
  150. };
  151. SLseg* SweepLine::add( Event* E )
  152. {
  153. // fill in SLseg element data
  154. SLseg* s = new SLseg;
  155. s->edge = E->edge;
  156. // if it is being added, then it must be a LEFT edge event
  157. // but need to determine which endpoint is the left one
  158. Point* v1 = &(Pn->V[s->edge]);
  159. Point* v2 = &(Pn->V[s->edge+1]);
  160. if (xyorder( v1, v2) < 0) { // determine which is leftmost
  161. s->lP = *v1;
  162. s->rP = *v2;
  163. }
  164. else {
  165. s->rP = *v1;
  166. s->lP = *v2;
  167. }
  168. s->above = (SLseg*)0;
  169. s->below = (SLseg*)0;
  170. // add a node to the balanced binary tree
  171. Tnode* nd = Tree.insert(s);
  172. Tnode* nx = Tree.next(nd);
  173. Tnode* np = Tree.prev(nd);
  174. if (nx != (Tnode*)0) {
  175. s->above = (SLseg*)nx->val;
  176. s->above->below = s;
  177. }
  178. if (np != (Tnode*)0) {
  179. s->below = (SLseg*)np->val;
  180. s->below->above = s;
  181. }
  182. return s;
  183. }
  184. SLseg* SweepLine::find( Event* E )
  185. {
  186. // need a segment to find it in the tree
  187. SLseg* s = new SLseg;
  188. s->edge = E->edge;
  189. s->above = (SLseg*)0;
  190. s->below = (SLseg*)0;
  191. Tnode* nd = Tree.find(s);
  192. delete s;
  193. if (nd == (Tnode*)0)
  194. return (SLseg*)0;
  195. return (SLseg*)nd->val;
  196. }
  197. void SweepLine::remove( SLseg* s )
  198. {
  199. // remove the node from the balanced binary tree
  200. Tnode* nd = Tree.find(s);
  201. if (nd == (Tnode*)0)
  202. return; // not there
  203. // get the above and below segments pointing to each other
  204. Tnode* nx = Tree.next(nd);
  205. if (nx != (Tnode*)0) {
  206. SLseg* sx = (SLseg*)(nx->val);
  207. sx->below = s->below;
  208. }
  209. Tnode* np = Tree.prev(nd);
  210. if (np != (Tnode*)0) {
  211. SLseg* sp = (SLseg*)(np->val);
  212. sp->above = s->above;
  213. }
  214. Tree.remove(nd); // now can safely remove it
  215. delete s;
  216. }
  217. // test intersect of 2 segments and return: 0=none, 1=intersect
  218. int SweepLine::intersect( SLseg* s1, SLseg* s2)
  219. {
  220. if (s1 == (SLseg*)0 || s2 == (SLseg*)0)
  221. return FALSE; // no intersect if either segment doesn't exist
  222. // check for consecutive edges in polygon
  223. int e1 = s1->edge;
  224. int e2 = s2->edge;
  225. if (((e1+1)%nv == e2) || (e1 == (e2+1)%nv))
  226. return FALSE; // no non-simple intersect since consecutive
  227. // test for existence of an intersect point
  228. float lsign, rsign;
  229. lsign = isLeft(s1->lP, s1->rP, s2->lP); // s2 left point sign
  230. rsign = isLeft(s1->lP, s1->rP, s2->rP); // s2 right point sign
  231. if (lsign * rsign > 0) // s2 endpoints have same sign relative to s1
  232. return FALSE; // => on same side => no intersect is possible
  233. lsign = isLeft(s2->lP, s2->rP, s1->lP); // s1 left point sign
  234. rsign = isLeft(s2->lP, s2->rP, s1->rP); // s1 right point sign
  235. if (lsign * rsign > 0) // s1 endpoints have same sign relative to s2
  236. return FALSE; // => on same side => no intersect is possible
  237. // the segments s1 and s2 straddle each other
  238. return TRUE; // => an intersect exists
  239. }
  240. //===================================================================
  241. // simple_Polygon(): test if a Polygon is simple or not
  242. // Input: Pn = a polygon with n vertices V[]
  243. // Return: FALSE(0) = is NOT simple
  244. // TRUE(1) = IS simple
  245. int
  246. simple_Polygon( Polygon Pn )
  247. {
  248. EventQueue Eq(Pn);
  249. SweepLine SL(Pn);
  250. Event* e; // the current event
  251. SLseg* s; // the current SL segment
  252. // This loop processes all events in the sorted queue
  253. // Events are only left or right vertices since
  254. // No new events will be added (an intersect => Done)
  255. while (e = Eq.next()) { // while there are events
  256. if (e->type == LEFT) { // process a left vertex
  257. s = SL.add(e); // add it to the sweep line
  258. if (SL.intersect( s, s->above))
  259. return FALSE; // Pn is NOT simple
  260. if (SL.intersect( s, s->below))
  261. return FALSE; // Pn is NOT simple
  262. }
  263. else { // processs a right vertex
  264. s = SL.find(e);
  265. if (SL.intersect( s->above, s->below))
  266. return FALSE; // Pn is NOT simple
  267. SL.remove(s); // remove it from the sweep line
  268. }
  269. }
  270. return TRUE; // Pn IS simple
  271. }
  272. //===================================================================