123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- //Copyright (C) 2011 by Ivan Fratric
- //
- //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.
- #include <list>
- using namespace std;
- typedef double tppl_float;
- #define TPPL_CCW 1
- #define TPPL_CW -1
- //2D point structure
- struct TPPLPoint {
- tppl_float x;
- tppl_float y;
- TPPLPoint operator + (const TPPLPoint& p) const {
- TPPLPoint r;
- r.x = x + p.x;
- r.y = y + p.y;
- return r;
- }
- TPPLPoint operator - (const TPPLPoint& p) const {
- TPPLPoint r;
- r.x = x - p.x;
- r.y = y - p.y;
- return r;
- }
- TPPLPoint operator * (const tppl_float f ) const {
- TPPLPoint r;
- r.x = x*f;
- r.y = y*f;
- return r;
- }
- TPPLPoint operator / (const tppl_float f ) const {
- TPPLPoint r;
- r.x = x/f;
- r.y = y/f;
- return r;
- }
- bool operator==(const TPPLPoint& p) const {
- if((x == p.x)&&(y==p.y)) return true;
- else return false;
- }
- bool operator!=(const TPPLPoint& p) const {
- if((x == p.x)&&(y==p.y)) return false;
- else return true;
- }
- };
- //Polygon implemented as an array of points with a 'hole' flag
- class TPPLPoly {
- protected:
- TPPLPoint *points;
- long numpoints;
- bool hole;
- public:
- //constructors/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 hole) {
- this->hole = hole;
- }
- TPPLPoint &GetPoint(long i) {
- return points[i];
- }
- TPPLPoint *GetPoints() {
- return points;
- }
- TPPLPoint& operator[] (int i) {
- 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,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_CCW : polygon vertices are in counter-clockwise order
- // TPPL_CW : polygon vertices are in clockwise order
- // 0 : the polygon has no (measurable) area
- int GetOrientation() const;
- //sets the polygon orientation
- //orientation can be
- // TPPL_CCW : sets vertices in counter-clockwise order
- // TPPL_CW : sets vertices in clockwise order
- void SetOrientation(int orientation);
- };
- class TPPLPartition {
- protected:
- struct PartitionVertex {
- bool isActive;
- bool isConvex;
- bool isEar;
- TPPLPoint p;
- tppl_float angle;
- PartitionVertex *previous;
- PartitionVertex *next;
- };
- struct MonotoneVertex {
- TPPLPoint p;
- long previous;
- long next;
- };
- class VertexSorter{
- MonotoneVertex *vertices;
- public:
- VertexSorter(MonotoneVertex *v) : vertices(v) {}
- bool operator() (long index1, long index2) const;
- };
- struct Diagonal {
- long index1;
- long index2;
- };
- //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;
- list<Diagonal> pairs;
- };
- //edge that intersects the scanline
- struct ScanLineEdge {
- 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);
- //triangulates a monotone polygon, used in Triangulate_MONO
- int TriangulateMonotone(TPPLPoly *inPoly, list<TPPLPoly> *triangles);
- public:
- //simple heuristic procedure for removing holes from a list of polygons
- //works by creating a diagonal from the rightmost hole vertex to some visible vertex
- //time complexity: O(h*(n^2)), h is the number of holes, n is the number 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(list<TPPLPoly> *inpolys, list<TPPLPoly> *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, list<TPPLPoly> *triangles);
- //triangulates a list of polygons that may contain holes by ear clipping algorithm
- //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon
- //time complexity: O(h*(n^2)), h is the number of holes, 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_EC(list<TPPLPoly> *inpolys, list<TPPLPoly> *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, list<TPPLPoly> *triangles);
- //triangulates a polygons by firstly 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, list<TPPLPoly> *triangles);
- //triangulates a list of polygons by firstly 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(list<TPPLPoly> *inpolys, list<TPPLPoly> *triangles);
- //creates a monotone partition of a list of polygons that can contain holes
- //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(list<TPPLPoly> *inpolys, list<TPPLPoly> *monotonePolys);
- //partitions a polygon into convex polygons by using 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
- //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, list<TPPLPoly> *parts);
- //partitions a list of polygons into convex parts by using 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
- //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(list<TPPLPoly> *inpolys, list<TPPLPoly> *parts);
- //optimal convex partitioning (in terms of number of resulting convex polygons)
- //using the Keil-Snoeyink algorithm
- //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)
- // 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, list<TPPLPoly> *parts);
- };
|