123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /*
- * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
- * http://code.google.com/p/poly2tri/
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * * Neither the name of Poly2Tri nor the names of its contributors may be
- * used to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- /**
- * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and
- * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
- * International Journal of Geographical Information Science
- *
- * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
- */
- #ifndef SWEEP_H
- #define SWEEP_H
- #include <vector>
- namespace p2t {
- class SweepContext;
- struct Node;
- struct Point;
- struct Edge;
- class Triangle;
- class Sweep
- {
- public:
- /**
- * Triangulate
- *
- * @param tcx
- */
- void Triangulate(SweepContext& tcx);
- /**
- * Destructor - clean up memory
- */
- ~Sweep();
- private:
- /**
- * Start sweeping the Y-sorted point set from bottom to top
- *
- * @param tcx
- */
- void SweepPoints(SweepContext& tcx);
- /**
- * Find closes node to the left of the new point and
- * create a new triangle. If needed new holes and basins
- * will be filled to.
- *
- * @param tcx
- * @param point
- * @return
- */
- Node& PointEvent(SweepContext& tcx, Point& point);
- /**
- *
- *
- * @param tcx
- * @param edge
- * @param node
- */
- void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
- void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point);
- /**
- * Creates a new front triangle and legalize it
- *
- * @param tcx
- * @param point
- * @param node
- * @return
- */
- Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node);
- /**
- * Adds a triangle to the advancing front to fill a hole.
- * @param tcx
- * @param node - middle node, that is the bottom of the hole
- */
- void Fill(SweepContext& tcx, Node& node);
- /**
- * Returns true if triangle was legalized
- */
- bool Legalize(SweepContext& tcx, Triangle& t);
- /**
- * <b>Requirement</b>:<br>
- * 1. a,b and c form a triangle.<br>
- * 2. a and d is know to be on opposite side of bc<br>
- * <pre>
- * a
- * +
- * / \
- * / \
- * b/ \c
- * +-------+
- * / d \
- * / \
- * </pre>
- * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
- * a,b and c<br>
- * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
- * This preknowledge gives us a way to optimize the incircle test
- * @param a - triangle point, opposite d
- * @param b - triangle point
- * @param c - triangle point
- * @param d - point opposite a
- * @return true if d is inside circle, false if on circle edge
- */
- bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const;
- /**
- * Rotates a triangle pair one vertex CW
- *<pre>
- * n2 n2
- * P +-----+ P +-----+
- * | t /| |\ t |
- * | / | | \ |
- * n1| / |n3 n1| \ |n3
- * | / | after CW | \ |
- * |/ oT | | oT \|
- * +-----+ oP +-----+
- * n4 n4
- * </pre>
- */
- void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const;
- /**
- * Fills holes in the Advancing Front
- *
- *
- * @param tcx
- * @param n
- */
- void FillAdvancingFront(SweepContext& tcx, Node& n);
- // Decision-making about when to Fill hole.
- // Contributed by ToolmakerSteve2
- bool LargeHole_DontFill(const Node* node) const;
- bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const;
- bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const;
- double Angle(const Point* origin, const Point* pa, const Point* pb) const;
- /**
- *
- * @param node - middle node
- * @return the angle between 3 front nodes
- */
- double HoleAngle(const Node& node) const;
- /**
- * The basin angle is decided against the horizontal line [1,0]
- */
- double BasinAngle(const Node& node) const;
- /**
- * Fills a basin that has formed on the Advancing Front to the right
- * of given node.<br>
- * First we decide a left,bottom and right node that forms the
- * boundaries of the basin. Then we do a reqursive fill.
- *
- * @param tcx
- * @param node - starting node, this or next node will be left node
- */
- void FillBasin(SweepContext& tcx, Node& node);
- /**
- * Recursive algorithm to fill a Basin with triangles
- *
- * @param tcx
- * @param node - bottom_node
- * @param cnt - counter used to alternate on even and odd numbers
- */
- void FillBasinReq(SweepContext& tcx, Node* node);
- bool IsShallow(SweepContext& tcx, Node& node);
- bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq);
- void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
- void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
- void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);
- void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);
- void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p);
- /**
- * After a flip we have two triangles and know that only one will still be
- * intersecting the edge. So decide which to contiune with and legalize the other
- *
- * @param tcx
- * @param o - should be the result of an orient2d( eq, op, ep )
- * @param t - triangle 1
- * @param ot - triangle 2
- * @param p - a point shared by both triangles
- * @param op - another point shared by both triangles
- * @return returns the triangle still intersecting the edge
- */
- Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op);
- /**
- * When we need to traverse from one triangle to the next we need
- * the point in current triangle that is the opposite point to the next
- * triangle.
- *
- * @param ep
- * @param eq
- * @param ot
- * @param op
- * @return
- */
- Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op);
- /**
- * Scan part of the FlipScan algorithm<br>
- * When a triangle pair isn't flippable we will scan for the next
- * point that is inside the flip triangle scan area. When found
- * we generate a new flipEdgeEvent
- *
- * @param tcx
- * @param ep - last point on the edge we are traversing
- * @param eq - first point on the edge we are traversing
- * @param flipTriangle - the current triangle sharing the point eq with edge
- * @param t
- * @param p
- */
- void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p);
- void FinalizationPolygon(SweepContext& tcx);
- std::vector<Node*> nodes_;
- };
- }
- #endif
|