123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*************************************************************************/
- /* Copyright (c) 2011-2021 Ivan Fratric and contributors. */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /*************************************************************************/
- #ifndef POLYPARTITION_H
- #define POLYPARTITION_H
- #include "core/math/vector2.h"
- #include "core/templates/list.h"
- #include "core/templates/rb_set.h"
- typedef double tppl_float;
- enum TPPLOrientation {
- TPPL_ORIENTATION_CW = -1,
- TPPL_ORIENTATION_NONE = 0,
- TPPL_ORIENTATION_CCW = 1,
- };
- enum TPPLVertexType {
- TPPL_VERTEXTYPE_REGULAR = 0,
- TPPL_VERTEXTYPE_START = 1,
- TPPL_VERTEXTYPE_END = 2,
- TPPL_VERTEXTYPE_SPLIT = 3,
- TPPL_VERTEXTYPE_MERGE = 4,
- };
- // 2D point structure.
- typedef Vector2 TPPLPoint;
- // Polygon implemented as an array of points with a "hole" flag.
- class TPPLPoly {
- protected:
- TPPLPoint *points;
- long numpoints;
- bool hole;
- public:
- // Constructors and destructors.
- TPPLPoly();
- ~TPPLPoly();
- TPPLPoly(const TPPLPoly &src);
- TPPLPoly &operator=(const TPPLPoly &src);
- // Getters and setters.
- long GetNumPoints() const {
- return numpoints;
- }
- bool IsHole() const {
- return hole;
- }
- void SetHole(bool p_hole) {
- this->hole = p_hole;
- }
- TPPLPoint &GetPoint(long i) {
- return points[i];
- }
- const TPPLPoint &GetPoint(long i) const {
- return points[i];
- }
- TPPLPoint *GetPoints() {
- return points;
- }
- TPPLPoint &operator[](int i) {
- return points[i];
- }
- const TPPLPoint &operator[](int i) const {
- return points[i];
- }
- // Clears the polygon points.
- void Clear();
- // Inits the polygon with numpoints vertices.
- void Init(long numpoints);
- // Creates a triangle with points p1, p2, and p3.
- void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
- // Inverts the orfer of vertices.
- void Invert();
- // Returns the orientation of the polygon.
- // Possible values:
- // TPPL_ORIENTATION_CCW: Polygon vertices are in counter-clockwise order.
- // TPPL_ORIENTATION_CW: Polygon vertices are in clockwise order.
- // TPPL_ORIENTATION_NONE: The polygon has no (measurable) area.
- TPPLOrientation GetOrientation() const;
- // Sets the polygon orientation.
- // Possible values:
- // TPPL_ORIENTATION_CCW: Sets vertices in counter-clockwise order.
- // TPPL_ORIENTATION_CW: Sets vertices in clockwise order.
- // TPPL_ORIENTATION_NONE: Reverses the orientation of the vertices if there
- // is one, otherwise does nothing (if orientation is already NONE).
- void SetOrientation(TPPLOrientation orientation);
- // Checks whether a polygon is valid or not.
- inline bool Valid() const { return this->numpoints >= 3; }
- };
- #ifdef TPPL_ALLOCATOR
- typedef List<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList;
- #else
- typedef List<TPPLPoly> TPPLPolyList;
- #endif
- class TPPLPartition {
- protected:
- struct PartitionVertex {
- bool isActive;
- bool isConvex;
- bool isEar;
- TPPLPoint p;
- tppl_float angle;
- PartitionVertex *previous;
- PartitionVertex *next;
- PartitionVertex();
- };
- struct MonotoneVertex {
- TPPLPoint p;
- long previous;
- long next;
- };
- class VertexSorter {
- MonotoneVertex *vertices;
- public:
- VertexSorter(MonotoneVertex *v) :
- vertices(v) {}
- bool operator()(long index1, long index2);
- };
- struct Diagonal {
- long index1;
- long index2;
- };
- #ifdef TPPL_ALLOCATOR
- typedef List<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList;
- #else
- typedef List<Diagonal> DiagonalList;
- #endif
- // Dynamic programming state for minimum-weight triangulation.
- struct DPState {
- bool visible;
- tppl_float weight;
- long bestvertex;
- };
- // Dynamic programming state for convex partitioning.
- struct DPState2 {
- bool visible;
- long weight;
- DiagonalList pairs;
- };
- // Edge that intersects the scanline.
- struct ScanLineEdge {
- mutable long index;
- TPPLPoint p1;
- TPPLPoint p2;
- // Determines if the edge is to the left of another edge.
- bool operator<(const ScanLineEdge &other) const;
- bool IsConvex(const TPPLPoint &p1, const TPPLPoint &p2, const TPPLPoint &p3) const;
- };
- // Standard helper functions.
- bool IsConvex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
- bool IsReflex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3);
- bool IsInside(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
- bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p);
- bool InCone(PartitionVertex *v, TPPLPoint &p);
- int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22);
- TPPLPoint Normalize(const TPPLPoint &p);
- tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2);
- // Helper functions for Triangulate_EC.
- void UpdateVertexReflexity(PartitionVertex *v);
- void UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices);
- // Helper functions for ConvexPartition_OPT.
- void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates);
- void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
- void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates);
- // Helper functions for MonotonePartition.
- bool Below(TPPLPoint &p1, TPPLPoint &p2);
- void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
- TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators,
- RBSet<ScanLineEdge> *edgeTree, long *helpers);
- // Triangulates a monotone polygon, used in Triangulate_MONO.
- int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles);
- public:
- // Simple heuristic procedure for removing holes from a list of polygons.
- // It works by creating a diagonal from the right-most hole vertex
- // to some other visible vertex.
- // Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices.
- // Space complexity: O(n)
- // params:
- // inpolys:
- // A list of polygons that can contain holes.
- // Vertices of all non-hole polys have to be in counter-clockwise order.
- // Vertices of all hole polys have to be in clockwise order.
- // outpolys:
- // A list of polygons without holes.
- // Returns 1 on success, 0 on failure.
- int RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys);
- // Triangulates a polygon by ear clipping.
- // Time complexity: O(n^2), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // poly:
- // An input polygon to be triangulated.
- // Vertices have to be in counter-clockwise order.
- // triangles:
- // A list of triangles (result).
- // Returns 1 on success, 0 on failure.
- int Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles);
- // Triangulates a list of polygons that may contain holes by ear clipping
- // algorithm. It first calls RemoveHoles to get rid of the holes, and then
- // calls Triangulate_EC for each resulting polygon.
- // Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices.
- // Space complexity: O(n)
- // params:
- // inpolys:
- // A list of polygons to be triangulated (can contain holes).
- // Vertices of all non-hole polys have to be in counter-clockwise order.
- // Vertices of all hole polys have to be in clockwise order.
- // triangles:
- // A list of triangles (result).
- // Returns 1 on success, 0 on failure.
- int Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles);
- // Creates an optimal polygon triangulation in terms of minimal edge length.
- // Time complexity: O(n^3), n is the number of vertices
- // Space complexity: O(n^2)
- // params:
- // poly:
- // An input polygon to be triangulated.
- // Vertices have to be in counter-clockwise order.
- // triangles:
- // A list of triangles (result).
- // Returns 1 on success, 0 on failure.
- int Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles);
- // Triangulates a polygon by first partitioning it into monotone polygons.
- // Time complexity: O(n*log(n)), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // poly:
- // An input polygon to be triangulated.
- // Vertices have to be in counter-clockwise order.
- // triangles:
- // A list of triangles (result).
- // Returns 1 on success, 0 on failure.
- int Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles);
- // Triangulates a list of polygons by first
- // partitioning them into monotone polygons.
- // Time complexity: O(n*log(n)), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // inpolys:
- // A list of polygons to be triangulated (can contain holes).
- // Vertices of all non-hole polys have to be in counter-clockwise order.
- // Vertices of all hole polys have to be in clockwise order.
- // triangles:
- // A list of triangles (result).
- // Returns 1 on success, 0 on failure.
- int Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles);
- // Creates a monotone partition of a list of polygons that
- // can contain holes. Triangulates a set of polygons by
- // first partitioning them into monotone polygons.
- // Time complexity: O(n*log(n)), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // inpolys:
- // A list of polygons to be triangulated (can contain holes).
- // Vertices of all non-hole polys have to be in counter-clockwise order.
- // Vertices of all hole polys have to be in clockwise order.
- // monotonePolys:
- // A list of monotone polygons (result).
- // Returns 1 on success, 0 on failure.
- int MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys);
- // Partitions a polygon into convex polygons by using the
- // Hertel-Mehlhorn algorithm. The algorithm gives at most four times
- // the number of parts as the optimal algorithm, however, in practice
- // it works much better than that and often gives optimal partition.
- // It uses triangulation obtained by ear clipping as intermediate result.
- // Time complexity O(n^2), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // poly:
- // An input polygon to be partitioned.
- // Vertices have to be in counter-clockwise order.
- // parts:
- // Resulting list of convex polygons.
- // Returns 1 on success, 0 on failure.
- int ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts);
- // Partitions a list of polygons into convex parts by using the
- // Hertel-Mehlhorn algorithm. The algorithm gives at most four times
- // the number of parts as the optimal algorithm, however, in practice
- // it works much better than that and often gives optimal partition.
- // It uses triangulation obtained by ear clipping as intermediate result.
- // Time complexity O(n^2), n is the number of vertices.
- // Space complexity: O(n)
- // params:
- // inpolys:
- // An input list of polygons to be partitioned. Vertices of
- // all non-hole polys have to be in counter-clockwise order.
- // Vertices of all hole polys have to be in clockwise order.
- // parts:
- // Resulting list of convex polygons.
- // Returns 1 on success, 0 on failure.
- int ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts);
- // Optimal convex partitioning (in terms of number of resulting
- // convex polygons) using the Keil-Snoeyink algorithm.
- // For reference, see M. Keil, J. Snoeyink, "On the time bound for
- // convex decomposition of simple polygons", 1998.
- // Time complexity O(n^3), n is the number of vertices.
- // Space complexity: O(n^3)
- // params:
- // poly:
- // An input polygon to be partitioned.
- // Vertices have to be in counter-clockwise order.
- // parts:
- // Resulting list of convex polygons.
- // Returns 1 on success, 0 on failure.
- int ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts);
- };
- #endif
|