polypartition.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. //Copyright (C) 2011 by Ivan Fratric
  2. //
  3. //Permission is hereby granted, free of charge, to any person obtaining a copy
  4. //of this software and associated documentation files (the "Software"), to deal
  5. //in the Software without restriction, including without limitation the rights
  6. //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. //copies of the Software, and to permit persons to whom the Software is
  8. //furnished to do so, subject to the following conditions:
  9. //
  10. //The above copyright notice and this permission notice shall be included in
  11. //all copies or substantial portions of the Software.
  12. //
  13. //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. //THE SOFTWARE.
  20. #include <list>
  21. using namespace std;
  22. typedef double tppl_float;
  23. #define TPPL_CCW 1
  24. #define TPPL_CW -1
  25. //2D point structure
  26. struct TPPLPoint {
  27. tppl_float x;
  28. tppl_float y;
  29. TPPLPoint operator + (const TPPLPoint& p) const {
  30. TPPLPoint r;
  31. r.x = x + p.x;
  32. r.y = y + p.y;
  33. return r;
  34. }
  35. TPPLPoint operator - (const TPPLPoint& p) const {
  36. TPPLPoint r;
  37. r.x = x - p.x;
  38. r.y = y - p.y;
  39. return r;
  40. }
  41. TPPLPoint operator * (const tppl_float f ) const {
  42. TPPLPoint r;
  43. r.x = x*f;
  44. r.y = y*f;
  45. return r;
  46. }
  47. TPPLPoint operator / (const tppl_float f ) const {
  48. TPPLPoint r;
  49. r.x = x/f;
  50. r.y = y/f;
  51. return r;
  52. }
  53. bool operator==(const TPPLPoint& p) const {
  54. if((x == p.x)&&(y==p.y)) return true;
  55. else return false;
  56. }
  57. bool operator!=(const TPPLPoint& p) const {
  58. if((x == p.x)&&(y==p.y)) return false;
  59. else return true;
  60. }
  61. };
  62. //Polygon implemented as an array of points with a 'hole' flag
  63. class TPPLPoly {
  64. protected:
  65. TPPLPoint *points;
  66. long numpoints;
  67. bool hole;
  68. public:
  69. //constructors/destructors
  70. TPPLPoly();
  71. ~TPPLPoly();
  72. TPPLPoly(const TPPLPoly &src);
  73. TPPLPoly& operator=(const TPPLPoly &src);
  74. //getters and setters
  75. long GetNumPoints() const {
  76. return numpoints;
  77. }
  78. bool IsHole() const {
  79. return hole;
  80. }
  81. void SetHole(bool hole) {
  82. this->hole = hole;
  83. }
  84. TPPLPoint &GetPoint(long i) {
  85. return points[i];
  86. }
  87. TPPLPoint *GetPoints() {
  88. return points;
  89. }
  90. TPPLPoint& operator[] (int i) {
  91. return points[i];
  92. }
  93. //clears the polygon points
  94. void Clear();
  95. //inits the polygon with numpoints vertices
  96. void Init(long numpoints);
  97. //creates a triangle with points p1,p2,p3
  98. void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
  99. //inverts the orfer of vertices
  100. void Invert();
  101. //returns the orientation of the polygon
  102. //possible values:
  103. // TPPL_CCW : polygon vertices are in counter-clockwise order
  104. // TPPL_CW : polygon vertices are in clockwise order
  105. // 0 : the polygon has no (measurable) area
  106. int GetOrientation() const;
  107. //sets the polygon orientation
  108. //orientation can be
  109. // TPPL_CCW : sets vertices in counter-clockwise order
  110. // TPPL_CW : sets vertices in clockwise order
  111. void SetOrientation(int orientation);
  112. };
  113. class TPPLPartition {
  114. protected:
  115. struct PartitionVertex {
  116. bool isActive;
  117. bool isConvex;
  118. bool isEar;
  119. TPPLPoint p;
  120. tppl_float angle;
  121. PartitionVertex *previous;
  122. PartitionVertex *next;
  123. };
  124. struct MonotoneVertex {
  125. TPPLPoint p;
  126. long previous;
  127. long next;
  128. };
  129. class VertexSorter{
  130. MonotoneVertex *vertices;
  131. public:
  132. VertexSorter(MonotoneVertex *v) : vertices(v) {}
  133. bool operator() (long index1, long index2) const;
  134. };
  135. struct Diagonal {
  136. long index1;
  137. long index2;
  138. };
  139. //dynamic programming state for minimum-weight triangulation
  140. struct DPState {
  141. bool visible;
  142. tppl_float weight;
  143. long bestvertex;
  144. };
  145. //dynamic programming state for convex partitioning
  146. struct DPState2 {
  147. bool visible;
  148. long weight;
  149. list<Diagonal> pairs;
  150. };
  151. //edge that intersects the scanline
  152. struct ScanLineEdge {
  153. long index;
  154. TPPLPoint p1;
  155. TPPLPoint p2;
  156. //determines if the edge is to the left of another edge
  157. bool operator< (const ScanLineEdge & other) const;
  158. bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const;
  159. };
  160. //standard helper functions
  161. bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
  162. bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3);
  163. bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p);
  164. bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
  165. bool InCone(PartitionVertex *v, TPPLPoint &p);
  166. int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
  167. TPPLPoint Normalize(const TPPLPoint &p);
  168. tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
  169. //helper functions for Triangulate_EC
  170. void UpdateVertexReflexity(PartitionVertex *v);
  171. void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices);
  172. //helper functions for ConvexPartition_OPT
  173. void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
  174. void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
  175. void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
  176. //helper functions for MonotonePartition
  177. bool Below(TPPLPoint &p1, TPPLPoint &p2);
  178. void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2);
  179. //triangulates a monotone polygon, used in Triangulate_MONO
  180. int TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles);
  181. public:
  182. //simple heuristic procedure for removing holes from a list of polygons
  183. //works by creating a diagonal from the rightmost hole vertex to some visible vertex
  184. //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
  185. //space complexity: O(n)
  186. //params:
  187. // inpolys : a list of polygons that can contain holes
  188. // vertices of all non-hole polys have to be in counter-clockwise order
  189. // vertices of all hole polys have to be in clockwise order
  190. // outpolys : a list of polygons without holes
  191. //returns 1 on success, 0 on failure
  192. int RemoveHoles(list<TPPLPoly> *inpolys, list<TPPLPoly> *outpolys);
  193. //triangulates a polygon by ear clipping
  194. //time complexity O(n^2), n is the number of vertices
  195. //space complexity: O(n)
  196. //params:
  197. // poly : an input polygon to be triangulated
  198. // vertices have to be in counter-clockwise order
  199. // triangles : a list of triangles (result)
  200. //returns 1 on success, 0 on failure
  201. int Triangulate_EC(TPPLPoly *poly, list<TPPLPoly> *triangles);
  202. //triangulates a list of polygons that may contain holes by ear clipping algorithm
  203. //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
  204. //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices
  205. //space complexity: O(n)
  206. //params:
  207. // inpolys : a list of polygons to be triangulated (can contain holes)
  208. // vertices of all non-hole polys have to be in counter-clockwise order
  209. // vertices of all hole polys have to be in clockwise order
  210. // triangles : a list of triangles (result)
  211. //returns 1 on success, 0 on failure
  212. int Triangulate_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
  213. //creates an optimal polygon triangulation in terms of minimal edge length
  214. //time complexity: O(n^3), n is the number of vertices
  215. //space complexity: O(n^2)
  216. //params:
  217. // poly : an input polygon to be triangulated
  218. // vertices have to be in counter-clockwise order
  219. // triangles : a list of triangles (result)
  220. //returns 1 on success, 0 on failure
  221. int Triangulate_OPT(TPPLPoly *poly, list<TPPLPoly> *triangles);
  222. //triangulates a polygons by firstly partitioning it into monotone polygons
  223. //time complexity: O(n*log(n)), n is the number of vertices
  224. //space complexity: O(n)
  225. //params:
  226. // poly : an input polygon to be triangulated
  227. // vertices have to be in counter-clockwise order
  228. // triangles : a list of triangles (result)
  229. //returns 1 on success, 0 on failure
  230. int Triangulate_MONO(TPPLPoly *poly, list<TPPLPoly> *triangles);
  231. //triangulates a list of polygons by firstly partitioning them into monotone polygons
  232. //time complexity: O(n*log(n)), n is the number of vertices
  233. //space complexity: O(n)
  234. //params:
  235. // inpolys : a list of polygons to be triangulated (can contain holes)
  236. // vertices of all non-hole polys have to be in counter-clockwise order
  237. // vertices of all hole polys have to be in clockwise order
  238. // triangles : a list of triangles (result)
  239. //returns 1 on success, 0 on failure
  240. int Triangulate_MONO(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
  241. //creates a monotone partition of a list of polygons that can contain holes
  242. //time complexity: O(n*log(n)), n is the number of vertices
  243. //space complexity: O(n)
  244. //params:
  245. // inpolys : a list of polygons to be triangulated (can contain holes)
  246. // vertices of all non-hole polys have to be in counter-clockwise order
  247. // vertices of all hole polys have to be in clockwise order
  248. // monotonePolys : a list of monotone polygons (result)
  249. //returns 1 on success, 0 on failure
  250. int MonotonePartition(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys);
  251. //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm
  252. //the algorithm gives at most four times the number of parts as the optimal algorithm
  253. //however, in practice it works much better than that and often gives optimal partition
  254. //uses triangulation obtained by ear clipping as intermediate result
  255. //time complexity O(n^2), n is the number of vertices
  256. //space complexity: O(n)
  257. //params:
  258. // poly : an input polygon to be partitioned
  259. // vertices have to be in counter-clockwise order
  260. // parts : resulting list of convex polygons
  261. //returns 1 on success, 0 on failure
  262. int ConvexPartition_HM(TPPLPoly *poly, list<TPPLPoly> *parts);
  263. //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm
  264. //the algorithm gives at most four times the number of parts as the optimal algorithm
  265. //however, in practice it works much better than that and often gives optimal partition
  266. //uses triangulation obtained by ear clipping as intermediate result
  267. //time complexity O(n^2), n is the number of vertices
  268. //space complexity: O(n)
  269. //params:
  270. // inpolys : an input list of polygons to be partitioned
  271. // vertices of all non-hole polys have to be in counter-clockwise order
  272. // vertices of all hole polys have to be in clockwise order
  273. // parts : resulting list of convex polygons
  274. //returns 1 on success, 0 on failure
  275. int ConvexPartition_HM(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts);
  276. //optimal convex partitioning (in terms of number of resulting convex polygons)
  277. //using the Keil-Snoeyink algorithm
  278. //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998
  279. //time complexity O(n^3), n is the number of vertices
  280. //space complexity: O(n^3)
  281. // poly : an input polygon to be partitioned
  282. // vertices have to be in counter-clockwise order
  283. // parts : resulting list of convex polygons
  284. //returns 1 on success, 0 on failure
  285. int ConvexPartition_OPT(TPPLPoly *poly, list<TPPLPoly> *parts);
  286. };