polypartition.h 13 KB

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