diff --git a/CMakeLists.txt b/CMakeLists.txt index ca9ca67476..8f648fc72b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,13 @@ if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden" ) endif() + find_package( OpenMP QUIET ) + if( OPENMP_FOUND ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" ) + add_definitions( -DUSE_OPENMP ) + endif() + if( MINGW ) set( CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" ) diff --git a/common/geometry/hetriang.cpp b/common/geometry/hetriang.cpp index c1523ac347..175e80dbd5 100644 --- a/common/geometry/hetriang.cpp +++ b/common/geometry/hetriang.cpp @@ -51,8 +51,6 @@ using namespace hed; using namespace std; -Triangulation* TTLtraits::triang_ = NULL; - #ifdef TTL_USE_NODE_ID int Node::id_count = 0; #endif @@ -164,11 +162,30 @@ EdgePtr Triangulation::initTwoEnclosingTriangles(NodesContainer::iterator first, } +//-------------------------------------------------------------------------------------------------- +Triangulation::Triangulation() { + helper = new ttl::TriangulationHelper( *this ); +} + + +//-------------------------------------------------------------------------------------------------- +Triangulation::Triangulation(const Triangulation& tr) { + std::cout << "Triangulation: Copy constructor not present - EXIT."; + exit(-1); +} + + +//-------------------------------------------------------------------------------------------------- +Triangulation::~Triangulation() { + cleanAll(); + delete helper; +} + + //-------------------------------------------------------------------------------------------------- void Triangulation::createDelaunay(NodesContainer::iterator first, NodesContainer::iterator last) { - - TTLtraits::triang_ = this; + cleanAll(); EdgePtr bedge = initTwoEnclosingTriangles(first, last); @@ -178,7 +195,7 @@ void Triangulation::createDelaunay(NodesContainer::iterator first, NodesContainer::iterator it; for (it = first; it != last; ++it) { - ttl::insertNode(d_iter, *it); + helper->insertNode(d_iter, *it); } // In general (e.g. for the triangle based data structure), the initial dart @@ -189,7 +206,7 @@ void Triangulation::createDelaunay(NodesContainer::iterator first, // triangle "outside" the triangulation.) // Assumes rectangular domain - ttl::removeRectangularBoundary(dc); + helper->removeRectangularBoundary(dc); } @@ -269,7 +286,7 @@ cout << "Iterate boundary 2" << endl; Dart dart_iter = dart; do { - if (ttl::isBoundaryEdge(dart_iter)) + if (helper->isBoundaryEdge(dart_iter)) dart_iter.alpha0().alpha1(); else dart_iter.alpha2().alpha1(); @@ -322,6 +339,31 @@ void Triangulation::cleanAll() { } +//-------------------------------------------------------------------------------------------------- +void Triangulation::swapEdge(Dart& dart) { + if (!dart.getEdge()->isConstrained()) swapEdge(dart.getEdge()); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::splitTriangle(Dart& dart, NodePtr point) { + EdgePtr edge = splitTriangle(dart.getEdge(), point); + dart.init(edge); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::reverse_splitTriangle(Dart& dart) { + reverse_splitTriangle(dart.getEdge()); +} + + +//-------------------------------------------------------------------------------------------------- +void Triangulation::removeBoundaryTriangle(Dart& d) { + removeTriangle(d.getEdge()); +} + + #ifdef TTL_USE_NODE_FLAG //-------------------------------------------------------------------------------------------------- // This is a "template" for accessing all nodes (but multiple tests) @@ -486,7 +528,7 @@ void Triangulation::swapEdge(EdgePtr& diagonal) { // Note that diagonal is both input and output and it is always // kept in counterclockwise direction (this is not required by all - // finctions in ttl:: now) + // functions in TriangulationHelper now) // Swap by rotating counterclockwise // Use the same objects - no deletion or new objects @@ -567,7 +609,7 @@ bool Triangulation::checkDelaunay() const { // only one of the half-edges if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { Dart dart(edge); - if (ttl::swapTestDelaunay(dart)) { + if (helper->swapTestDelaunay(dart)) { noNotDelaunay++; //printEdge(dart,os); os << "\n"; @@ -610,7 +652,7 @@ void Triangulation::optimizeDelaunay() { Dart dart(edge); // Constrained edges should not be swapped - if (!edge->isConstrained() && ttl::swapTestDelaunay(dart, cycling_check)) { + if (!edge->isConstrained() && helper->swapTestDelaunay(dart, cycling_check)) { optimal = false; swapEdge(edge); } @@ -632,7 +674,7 @@ EdgePtr Triangulation::getInteriorNode() const { for (int i = 0; i < 3; ++i) { if (edge->getTwinEdge()) { - if (!ttl::isBoundaryNode(Dart(edge))) + if (!helper->isBoundaryNode(Dart(edge))) return edge; } edge = edge->getNextEdgeInFace(); @@ -643,18 +685,18 @@ EdgePtr Triangulation::getInteriorNode() const { //-------------------------------------------------------------------------------------------------- -static EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) { +EdgePtr Triangulation::getBoundaryEdgeInTriangle(const EdgePtr& e) const { EdgePtr edge = e; - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; edge = edge->getNextEdgeInFace(); - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; edge = edge->getNextEdgeInFace(); - if (ttl::isBoundaryEdge(Dart(edge))) + if (helper->isBoundaryEdge(Dart(edge))) return edge; return EdgePtr(); diff --git a/include/ttl/halfedge/hetraits.h b/include/ttl/halfedge/hetraits.h index e25e993e0e..e24cd0697d 100644 --- a/include/ttl/halfedge/hetraits.h +++ b/include/ttl/halfedge/hetraits.h @@ -69,9 +69,6 @@ namespace hed { struct TTLtraits { - // The actual triangulation object - static Triangulation* triang_; - /** The floating point type used in calculations * involving scalar products and cross products. */ @@ -172,127 +169,6 @@ namespace hed { } //@} // End of Geometric Predicates Group - - - // A rationale for directing these functions to traits is: - // e.g., constraints - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart should be swapped - * according to the Delaunay criterion.
- * - * \note - * This function is also present in the TTL as ttl::swapTestDelaunay.
- * Thus, the function can be implemented simply as: - * \code - * { return ttl::swapTestDelaunay(dart); } - * \endcode - */ - //static bool swapTestDelaunay(const Dart& dart) { - // return ttl::swapTestDelaunay(dart); - //} - - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart can be swapped, i.e., - * if the edge is a diagonal in a (strictly) convex quadrilateral. - * This function is also present as ttl::swappableEdge. - */ - //static bool swappableEdge(const Dart& dart) { - // return ttl::swappableEdge(dart); - //} - - - //---------------------------------------------------------------------------------------------- - /* Checks if the edge associated with \e dart should be \e fixed, meaning - * that it should never be swapped. ??? Use when constraints. - */ - //static bool fixedEdge(const Dart& dart) { - // return dart.getEdge()->isConstrained(); - //} - - - //---------------------------------------------------------------------------------------------- - // ----------------------- Functions for Delaunay Triangulation Group ------------------------- - //---------------------------------------------------------------------------------------------- - - /** @name Functions for Delaunay Triangulation */ - //@{ - - //---------------------------------------------------------------------------------------------- - /** Swaps the edge associated with \e dart in the actual data structure. - * - *
- * \image html swapEdge.gif - *
- * - * \param dart - * Some of the functions require a dart as output. - * If this is required by the actual function, the dart should be delivered - * back in a position as seen if it was glued to the edge when swapping (rotating) - * the edge CCW; see the figure. - * - * \note - * - If the edge is \e constrained, or if it should not be swapped for - * some other reason, this function need not do the actual swap of the edge. - * - Some functions in TTL require that \c swapEdge is implemented such that - * darts outside the quadrilateral are not affected by the swap. - */ - static void swapEdge(Dart& dart) { - if (!dart.getEdge()->isConstrained()) triang_->swapEdge(dart.getEdge()); - } - - - //---------------------------------------------------------------------------------------------- - /** Splits the triangle associated with \e dart in the actual data structure into - * three new triangles joining at \e point. - * - *
- * \image html splitTriangle.gif - *
- * - * \param dart - * Output: A CCW dart incident with the new node; see the figure. - */ - static void splitTriangle(Dart& dart, NodePtr point) { - EdgePtr edge = triang_->splitTriangle(dart.getEdge(), point); - dart.init(edge); - } - - //@} // End of Functions for Delaunay Triangulation group - - - //---------------------------------------------------------------------------------------------- - // --------------------------- Functions for removing nodes Group ----------------------------- - //---------------------------------------------------------------------------------------------- - - /** @name Functions for removing nodes */ - //@{ - - //---------------------------------------------------------------------------------------------- - /** The reverse operation of TTLtraits::splitTriangle. - * This function is only required for functions that involve - * removal of interior nodes; see for example ttl::removeInteriorNode. - * - *
- * \image html reverse_splitTriangle.gif - *
- */ - static void reverse_splitTriangle(Dart& dart) { - triang_->reverse_splitTriangle(dart.getEdge()); - } - - - //---------------------------------------------------------------------------------------------- - /** Removes a triangle with an edge at the boundary of the triangulation - * in the actual data structure - */ - static void removeBoundaryTriangle(Dart& d) { - triang_->removeTriangle(d.getEdge()); - } - - //@} // End of Functions for removing nodes Group - }; }; // End of hed namespace diff --git a/include/ttl/halfedge/hetriang.h b/include/ttl/halfedge/hetriang.h index ccee31bc0c..c8326a417d 100644 --- a/include/ttl/halfedge/hetriang.h +++ b/include/ttl/halfedge/hetriang.h @@ -51,10 +51,13 @@ #include #include #include -#include #include #include +namespace ttl { + class TriangulationHelper; +}; + //-------------------------------------------------------------------------------------------------- // The half-edge data structure //-------------------------------------------------------------------------------------------------- @@ -242,26 +245,75 @@ public: class Triangulation { protected: - list leadingEdges_; // one half-edge for each arc + std::list leadingEdges_; // one half-edge for each arc + + ttl::TriangulationHelper* helper; + void addLeadingEdge(EdgePtr& edge) { edge->setAsLeadingEdge(); leadingEdges_.push_front( edge ); } + bool removeLeadingEdgeFromList(EdgePtr& leadingEdge); + void cleanAll(); + /** Swaps the edge associated with \e dart in the actual data structure. + * + *
+ * \image html swapEdge.gif + *
+ * + * \param dart + * Some of the functions require a dart as output. + * If this is required by the actual function, the dart should be delivered + * back in a position as seen if it was glued to the edge when swapping (rotating) + * the edge CCW; see the figure. + * + * \note + * - If the edge is \e constrained, or if it should not be swapped for + * some other reason, this function need not do the actual swap of the edge. + * - Some functions in TTL require that \c swapEdge is implemented such that + * darts outside the quadrilateral are not affected by the swap. + */ + void swapEdge(Dart& dart); + + /** Splits the triangle associated with \e dart in the actual data structure into + * three new triangles joining at \e point. + * + *
+ * \image html splitTriangle.gif + *
+ * + * \param dart + * Output: A CCW dart incident with the new node; see the figure. + */ + void splitTriangle(Dart& dart, NodePtr point); + + /** The reverse operation of TTLtraits::splitTriangle. + * This function is only required for functions that involve + * removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode. + * + *
+ * \image html reverse_splitTriangle.gif + *
+ */ + void reverse_splitTriangle(Dart& dart); + + /** Removes a triangle with an edge at the boundary of the triangulation + * in the actual data structure + */ + void removeBoundaryTriangle(Dart& d); + public: /// Default constructor - Triangulation() {} + Triangulation(); /// Copy constructor - Triangulation(const Triangulation& tr) { - std::cout << "Triangulation: Copy constructor not present - EXIT."; - exit(-1); - } + Triangulation(const Triangulation& tr); /// Destructor - ~Triangulation() { cleanAll(); } + ~Triangulation(); /// Creates a Delaunay triangulation from a set of points void createDelaunay(NodesContainer::iterator first, @@ -295,20 +347,20 @@ public: Dart createDart(); /// Returns a list of "triangles" (one leading half-edge for each triangle) - const list& getLeadingEdges() const { return leadingEdges_; } + const std::list& getLeadingEdges() const { return leadingEdges_; } /// Returns the number of triangles int noTriangles() const { return (int)leadingEdges_.size(); } /// Returns a list of half-edges (one half-edge for each arc) - list* getEdges(bool skip_boundary_edges = false) const; + std::list* getEdges(bool skip_boundary_edges = false) const; #ifdef TTL_USE_NODE_FLAG /// Sets flag in all the nodes void flagNodes(bool flag) const; /// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node. - list* getNodes() const; + std::list* getNodes() const; #endif /// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped) @@ -320,12 +372,16 @@ public: /// Returns an arbitrary interior node (as the source node of the returned edge) EdgePtr getInteriorNode() const; + EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) const; + /// Returns an arbitrary boundary edge EdgePtr getBoundaryEdge() const; /// Print edges for plotting with, e.g., gnuplot void printEdges(std::ofstream& os) const; + friend class ttl::TriangulationHelper; + }; // End of class Triangulation diff --git a/include/ttl/ttl.h b/include/ttl/ttl.h index 003e0d81c6..7d7c655843 100644 --- a/include/ttl/ttl.h +++ b/include/ttl/ttl.h @@ -52,8 +52,6 @@ } #endif - using std::list; - // Next on TOPOLOGY: // - get triangle strips @@ -102,7 +100,7 @@ * - \e CW - clockwise * - \e 0_orbit, \e 1_orbit and \e 2_orbit: A sequence of darts around * a node, around an edge and in a triangle respectively; -* see ttl::get_0_orbit_interior and ttl::get_0_orbit_boundary +* see get_0_orbit_interior and get_0_orbit_boundary * - \e arc - In a triangulation an arc is equivalent with an edge * * \see @@ -115,15 +113,15 @@ namespace ttl { - +class TriangulationHelper +{ #ifndef DOXYGEN_SHOULD_SKIP_THIS - //------------------------------------------------------------------------------------------------ - // ----------------------------------- Forward declarations ------------------------------------- - //------------------------------------------------------------------------------------------------ -#if ((_MSC_VER > 0) && (_MSC_VER < 1300)) -#else - +public: + TriangulationHelper(hed::Triangulation& triang) : triangulation(triang) + { + } + // Delaunay Triangulation // ---------------------- template @@ -145,55 +143,55 @@ namespace ttl { // Topological and Geometric Queries // --------------------------------- template - bool locateFaceSimplest(const PointType& point, DartType& dart); + static bool locateFaceSimplest(const PointType& point, DartType& dart); template - bool locateTriangle(const PointType& point, DartType& dart); + static bool locateTriangle(const PointType& point, DartType& dart); template - bool inTriangleSimplest(const PointType& point, const DartType& dart); + static bool inTriangleSimplest(const PointType& point, const DartType& dart); template - bool inTriangle(const PointType& point, const DartType& dart); + static bool inTriangle(const PointType& point, const DartType& dart); template - void getBoundary(const DartType& dart, DartListType& boundary); + static void getBoundary(const DartType& dart, DartListType& boundary); template - bool isBoundaryEdge(const DartType& dart); + static bool isBoundaryEdge(const DartType& dart); template - bool isBoundaryFace(const DartType& dart); + static bool isBoundaryFace(const DartType& dart); template - bool isBoundaryNode(const DartType& dart); + static bool isBoundaryNode(const DartType& dart); template - int getDegreeOfNode(const DartType& dart); + static int getDegreeOfNode(const DartType& dart); template - void get_0_orbit_interior(const DartType& dart, DartListType& orbit); + static void get_0_orbit_interior(const DartType& dart, DartListType& orbit); template - void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); + static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); template - bool same_0_orbit(const DartType& d1, const DartType& d2); + static bool same_0_orbit(const DartType& d1, const DartType& d2); template - bool same_1_orbit(const DartType& d1, const DartType& d2); + static bool same_1_orbit(const DartType& d1, const DartType& d2); template - bool same_2_orbit(const DartType& d1, const DartType& d2); + static bool same_2_orbit(const DartType& d1, const DartType& d2); template - bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); + static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); template - void positionAtNextBoundaryEdge(DartType& dart); + static void positionAtNextBoundaryEdge(DartType& dart); template - bool convexBoundary(const DartType& dart); + static bool convexBoundary(const DartType& dart); // Utilities for Delaunay Triangulation @@ -205,7 +203,7 @@ namespace ttl { void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end); template - bool swapTestDelaunay(const DartType& dart, bool cycling_check = false); + bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) const; template void recSwapDelaunay(DartType& diagonal); @@ -223,9 +221,29 @@ namespace ttl { // Constrained Triangulation // ------------------------- template - DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); - -#endif + static DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); + +private: + hed::Triangulation& triangulation; + + template + void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart); + + template + static bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart); + + template + static bool locateFaceWithNode(const NodeType& node, DartType& dart_iter); + + template + static void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3); + + template + static void getNeighborNodes(const DartType& dart, std::list& node_list, bool& boundary); + + template + static bool degenerateTriangle(const DartType& dart); +}; #endif // DOXYGEN_SHOULD_SKIP_THIS @@ -245,7 +263,7 @@ namespace ttl { * can be created as two triangles forming a rectangle that contains * all the points. * After \c insertNode has been called repeatedly with all the points, - * ttl::removeRectangularBoundary can be called to remove triangles + * removeRectangularBoundary can be called to remove triangles * at the boundary of the triangulation so that the boundary * form the convex hull of the points. * @@ -268,19 +286,19 @@ namespace ttl { * - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType&) * * \using - * - ttl::locateTriangle - * - ttl::recSwapDelaunay + * - locateTriangle + * - recSwapDelaunay * * \note * - For efficiency reasons \e dart should be close to the insertion \e point. * * \see - * ttl::removeRectangularBoundary + * removeRectangularBoundary */ template - bool insertNode(DartType& dart, PointType& point) { + bool TriangulationHelper::insertNode(DartType& dart, PointType& point) { - bool found = ttl::locateTriangle(point, dart); + bool found = locateTriangle(point, dart); if (!found) { #ifdef DEBUG_TTL cout << "ERROR: Triangulation::insertNode: NO triangle found. /n"; @@ -289,7 +307,7 @@ namespace ttl { } // ??? can we hide the dart? this is not possible if one triangle only - TraitsType::splitTriangle(dart, point); + triangulation.splitTriangle(dart, point); DartType d1 = dart; d1.alpha2().alpha1().alpha2().alpha0().alpha1(); @@ -304,14 +322,14 @@ namespace ttl { //DartType dsav = d3; d3.alpha0().alpha1(); - //if (!TraitsType::fixedEdge(d1) && !ttl::isBoundaryEdge(d1)) { - if (!ttl::isBoundaryEdge(d1)) { + //if (!TraitsType::fixedEdge(d1) && !isBoundaryEdge(d1)) { + if (!isBoundaryEdge(d1)) { d1.alpha2(); recSwapDelaunay(d1); } - //if (!TraitsType::fixedEdge(d2) && !ttl::isBoundaryEdge(d2)) { - if (!ttl::isBoundaryEdge(d2)) { + //if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) { + if (!isBoundaryEdge(d2)) { d2.alpha2(); recSwapDelaunay(d2); } @@ -319,8 +337,8 @@ namespace ttl { // Preserve the incoming dart as output incident to the node and CCW //d = dsav.alpha2(); dart.alpha2(); - //if (!TraitsType::fixedEdge(d3) && !ttl::isBoundaryEdge(d3)) { - if (!ttl::isBoundaryEdge(d3)) { + //if (!TraitsType::fixedEdge(d3) && !isBoundaryEdge(d3)) { + if (!isBoundaryEdge(d3)) { d3.alpha2(); recSwapDelaunay(d3); } @@ -332,7 +350,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart) { + void TriangulationHelper::insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart) { // Assumes that the dereferenced point objects are pointers. // References to the point objects are then passed to TTL. @@ -355,14 +373,14 @@ namespace ttl { * Output: A CCW dart at the new boundary * * \using - * - ttl::removeBoundaryNode + * - removeBoundaryNode * * \note * - This function requires that the boundary of the triangulation is * a rectangle with four nodes (one in each corner). */ template - void removeRectangularBoundary(DartType& dart) { + void TriangulationHelper::removeRectangularBoundary(DartType& dart) { DartType d_next = dart; DartType d_iter; @@ -370,8 +388,8 @@ namespace ttl { for (int i = 0; i < 4; i++) { d_iter = d_next; d_next.alpha0(); - ttl::positionAtNextBoundaryEdge(d_next); - ttl::removeBoundaryNode(d_iter); + positionAtNextBoundaryEdge(d_next); + removeBoundaryNode(d_iter); } dart = d_next; // Return a dart at the new boundary @@ -383,20 +401,20 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::removeBoundaryNode if \e dart represents a node at the boundary - * - ttl::removeInteriorNode if \e dart represents an interior node + * - removeBoundaryNode if \e dart represents a node at the boundary + * - removeInteriorNode if \e dart represents an interior node * * \note * - The node cannot belong to a fixed (constrained) edge that is not * swappable. (An endless loop is likely to occur in this case). */ template - void removeNode(DartType& dart) { + void TriangulationHelper::removeNode(DartType& dart) { - if (ttl::isBoundaryNode(dart)) - ttl::removeBoundaryNode(dart); + if (isBoundaryNode(dart)) + removeBoundaryNode(dart); else - ttl::removeInteriorNode(dart); + removeInteriorNode(dart); } @@ -405,14 +423,14 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::swapEdgesAwayFromBoundaryNode - * - ttl::optimizeDelaunay + * - swapEdgesAwayFromBoundaryNode + * - optimizeDelaunay * * \require * - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType::removeBoundaryTriangle" (Dart&) */ template - void removeBoundaryNode(DartType& dart) { + void TriangulationHelper::removeBoundaryNode(DartType& dart) { // ... and update Delaunay // - CCW dart must be given (for remove) @@ -420,13 +438,13 @@ namespace ttl { // we assume that there is not only one triangle left in the triangulation. // Position at boundary edge and CCW - if (!ttl::isBoundaryEdge(dart)) { + if (!isBoundaryEdge(dart)) { dart.alpha1(); // ensures that next function delivers back a CCW dart (if the given dart is CCW) - ttl::positionAtNextBoundaryEdge(dart); + positionAtNextBoundaryEdge(dart); } - list swapped_edges; - ttl::swapEdgesAwayFromBoundaryNode(dart, swapped_edges); + std::list swapped_edges; + swapEdgesAwayFromBoundaryNode(dart, swapped_edges); // Remove boundary triangles and remove the new boundary from the list // of swapped edges, see below. @@ -435,7 +453,7 @@ namespace ttl { bool bend = false; while (bend == false) { dnext.alpha1().alpha2(); - if (ttl::isBoundaryEdge(dnext)) + if (isBoundaryEdge(dnext)) bend = true; // Stop when boundary // Generic: Also remove the new boundary from the list of swapped edges @@ -443,20 +461,20 @@ namespace ttl { n_bedge.alpha1().alpha0().alpha1().alpha2(); // new boundary edge // ??? can we avoid find if we do this in swap away? - typename list::iterator it; + typename std::list::iterator it; it = find(swapped_edges.begin(), swapped_edges.end(), n_bedge); if (it != swapped_edges.end()) swapped_edges.erase(it); // Remove the boundary triangle - TraitsType::removeBoundaryTriangle(d_iter); + triangulation.removeBoundaryTriangle(d_iter); d_iter = dnext; } // Optimize Delaunay - typedef list DartListType; - ttl::optimizeDelaunay(swapped_edges); + typedef std::list DartListType; + optimizeDelaunay(swapped_edges); } @@ -465,8 +483,8 @@ namespace ttl { * updates the triangulation to be Delaunay. * * \using - * - ttl::swapEdgesAwayFromInteriorNode - * - ttl::optimizeDelaunay + * - swapEdgesAwayFromInteriorNode + * - optimizeDelaunay * * \require * - \ref hed::TTLtraits::reverse_splitTriangle "TraitsType::reverse_splitTriangle" (Dart&) @@ -476,7 +494,7 @@ namespace ttl { * swappable. (An endless loop is likely to occur in this case). */ template - void removeInteriorNode(DartType& dart) { + void TriangulationHelper::removeInteriorNode(DartType& dart) { // ... and update to Delaunay. // Must allow degeneracy temporarily, see comments in swap edges away @@ -492,13 +510,13 @@ namespace ttl { // Assumes dart is counterclockwise - list swapped_edges; - ttl::swapEdgesAwayFromInteriorNode(dart, swapped_edges); + std::list swapped_edges; + swapEdgesAwayFromInteriorNode(dart, swapped_edges); // The reverse operation of split triangle: // Make one triangle of the three triangles at the node associated with dart // TraitsType:: - TraitsType::reverse_splitTriangle(dart); + triangulation.reverse_splitTriangle(dart); // ???? Not generic yet if we are very strict: // When calling unsplit triangle, darts at the three opposite sides may @@ -511,7 +529,7 @@ namespace ttl { // Note the theoretical result: if there are no edges in the list, // the triangulation is Delaunay already - ttl::optimizeDelaunay(swapped_edges); + optimizeDelaunay(swapped_edges); } //@} // End of Delaunay Triangulation Group @@ -527,7 +545,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart) { + bool TriangulationHelper::isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart) { // Check if the given topology element (node, edge or face) is a member of the face // Assumes: @@ -547,7 +565,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - bool locateFaceWithNode(const NodeType& node, DartType& dart_iter) { + bool TriangulationHelper::locateFaceWithNode(const NodeType& node, DartType& dart_iter) { // Locate a face in the topology structure with the given node as a member // Assumes: // - TraitsType::orient2d(DartType, DartType, NodeType) @@ -594,10 +612,10 @@ namespace ttl { * \e regular as explained above. * * \see - * ttl::locateTriangle + * locateTriangle */ template - bool locateFaceSimplest(const PointType& point, DartType& dart) { + bool TriangulationHelper::locateFaceSimplest(const PointType& point, DartType& dart) { // Not degenerate triangles if point is on the extension of the edges // But inTriangle may be called in case of true (may update to inFace2) // Convex boundary @@ -660,11 +678,11 @@ namespace ttl { * then the edge associated with \e dart will be at the boundary of the triangulation. * * \using - * - ttl::locateFaceSimplest - * - ttl::inTriangle + * - locateFaceSimplest + * - inTriangle */ template - bool locateTriangle(const PointType& point, DartType& dart) { + bool TriangulationHelper::locateTriangle(const PointType& point, DartType& dart) { // The purpose is to have a fast and stable procedure that // i) avoids concluding that a point is inside a triangle if it is not inside // ii) avoids infinite loops @@ -713,10 +731,10 @@ namespace ttl { * - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&) * * \see - * ttl::inTriangle for a more robust function + * inTriangle for a more robust function */ template - bool inTriangleSimplest(const PointType& point, const DartType& dart) { + bool TriangulationHelper::inTriangleSimplest(const PointType& point, const DartType& dart) { // Fast and simple: Do not deal with degenerate faces, i.e., if there is // degeneracy, true will be returned if the point is on the extension of the @@ -757,10 +775,10 @@ namespace ttl { * - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, PointType&) * * \see - * ttl::inTriangleSimplest + * inTriangleSimplest */ template - bool inTriangle(const PointType& point, const DartType& dart) { + bool TriangulationHelper::inTriangle(const PointType& point, const DartType& dart) { // SHOULD WE INCLUDE A STRATEGY WITH EDGE X e_1 ETC? TO GUARANTEE THAT // ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH @@ -841,7 +859,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later) template - void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3) { + void TriangulationHelper::getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3) { DartType dart_iter = dart; @@ -886,7 +904,7 @@ namespace ttl { * - DartListType::push_back (DartType&) */ template - void getBoundary(const DartType& dart, DartListType& boundary) { + void TriangulationHelper::getBoundary(const DartType& dart, DartListType& boundary) { // assumes the given dart is at the boundary (by edge) DartType dart_iter(dart); @@ -932,7 +950,7 @@ namespace ttl { * \endcode */ template - bool isBoundaryEdge(const DartType& dart) { + bool TriangulationHelper::isBoundaryEdge(const DartType& dart) { DartType dart_iter = dart; if (dart_iter.alpha2() == dart) @@ -947,7 +965,7 @@ namespace ttl { * the boundary of the triangulation. */ template - bool isBoundaryFace(const DartType& dart) { + bool TriangulationHelper::isBoundaryFace(const DartType& dart) { // Strategy: boundary if alpha2(d)=d @@ -976,7 +994,7 @@ namespace ttl { * the boundary of the triangulation. */ template - bool isBoundaryNode(const DartType& dart) { + bool TriangulationHelper::isBoundaryNode(const DartType& dart) { // Strategy: boundary if alpha2(d)=d @@ -1009,7 +1027,7 @@ namespace ttl { * the number of edges joining \e V with another node in the triangulation. */ template - int getDegreeOfNode(const DartType& dart) { + int TriangulationHelper::getDegreeOfNode(const DartType& dart) { DartType dart_iter(dart); DartType dart_prev; @@ -1069,7 +1087,8 @@ namespace ttl { // Private/Hidden function template - void getNeighborNodes(const DartType& dart, std::list& node_list, bool& boundary) { + void TriangulationHelper::getNeighborNodes(const DartType& dart, + std::list& node_list, bool& boundary) { DartType dart_iter(dart); @@ -1131,10 +1150,10 @@ namespace ttl { * - DartListType::push_back (DartType&) * * \see - * ttl::get_0_orbit_boundary + * get_0_orbit_boundary */ template - void get_0_orbit_interior(const DartType& dart, DartListType& orbit) { + void TriangulationHelper::get_0_orbit_interior(const DartType& dart, DartListType& orbit) { DartType d_iter = dart; orbit.push_back(d_iter); @@ -1165,10 +1184,10 @@ namespace ttl { * - The last dart in the sequence have opposite orientation compared to the others! * * \see - * ttl::get_0_orbit_interior + * get_0_orbit_interior */ template - void get_0_orbit_boundary(const DartType& dart, DartListType& orbit) { + void TriangulationHelper::get_0_orbit_boundary(const DartType& dart, DartListType& orbit) { DartType dart_prev; DartType d_iter = dart; @@ -1195,17 +1214,17 @@ namespace ttl { * own version.) */ template - bool same_0_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_0_orbit(const DartType& d1, const DartType& d2) { // Two copies of the same dart DartType d_iter = d2; DartType d_end = d2; - if (ttl::isBoundaryNode(d_iter)) { + if (isBoundaryNode(d_iter)) { // position at both boundary edges - ttl::positionAtNextBoundaryEdge(d_iter); + positionAtNextBoundaryEdge(d_iter); d_end.alpha1(); - ttl::positionAtNextBoundaryEdge(d_end); + positionAtNextBoundaryEdge(d_end); } for (;;) { @@ -1229,7 +1248,7 @@ namespace ttl { * \e d1 and/or \e d2 can be CCW or CW. */ template - bool same_1_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_1_orbit(const DartType& d1, const DartType& d2) { DartType d_iter = d2; // (Also works at the boundary) @@ -1245,7 +1264,7 @@ namespace ttl { * \e d1 and/or \e d2 can be CCW or CW */ template - bool same_2_orbit(const DartType& d1, const DartType& d2) { + bool TriangulationHelper::same_2_orbit(const DartType& d1, const DartType& d2) { DartType d_iter = d2; if (d_iter == d1 || d_iter.alpha0() == d1 || @@ -1259,7 +1278,7 @@ namespace ttl { //------------------------------------------------------------------------------------------------ // Private/Hidden function template - bool degenerateTriangle(const DartType& dart) { + bool TriangulationHelper::degenerateTriangle(const DartType& dart) { // Check if triangle is degenerate // Assumes CCW dart @@ -1287,7 +1306,7 @@ namespace ttl { * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (Dart&, Dart&) */ template - bool swappableEdge(const DartType& dart, bool allowDegeneracy) { + bool TriangulationHelper::swappableEdge(const DartType& dart, bool allowDegeneracy) { // How "safe" is it? @@ -1340,7 +1359,7 @@ namespace ttl { * infinit loop occurs. */ template - void positionAtNextBoundaryEdge(DartType& dart) { + void TriangulationHelper::positionAtNextBoundaryEdge(DartType& dart) { DartType dart_prev; @@ -1365,14 +1384,14 @@ namespace ttl { * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (const Dart&, const Dart&) */ template - bool convexBoundary(const DartType& dart) { + bool TriangulationHelper::convexBoundary(const DartType& dart) { - list blist; - ttl::getBoundary(dart, blist); + std::list blist; + getBoundary(dart, blist); int no; no = (int)blist.size(); - typename list::const_iterator bit = blist.begin(); + typename std::list::const_iterator bit = blist.begin(); DartType d1 = *bit; ++bit; DartType d2; @@ -1428,17 +1447,17 @@ namespace ttl { * seen if it was glued to the edge when swapping (rotating) the edge CCW * * \using - * - ttl::swapTestDelaunay + * - swapTestDelaunay */ template - void optimizeDelaunay(DartListType& elist) { + void TriangulationHelper::optimizeDelaunay(DartListType& elist) { optimizeDelaunay(elist, elist.end()); } //------------------------------------------------------------------------------------------------ template - void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) { + void TriangulationHelper::optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) { // CCW darts // Optimize here means Delaunay, but could be any criterion by @@ -1481,14 +1500,14 @@ namespace ttl { while(!optimal) { optimal = true; for (it = elist.begin(); it != end_opt; ++it) { - if (ttl::swapTestDelaunay(*it, cycling_check)) { + if (swapTestDelaunay(*it, cycling_check)) { // Preserve darts. Potential darts in the list are: // - The current dart // - the four CCW darts on the boundary of the quadrilateral // (the current arc has only one dart) - ttl::swapEdgeInList(it, elist); + swapEdgeInList(it, elist); optimal = false; } // end if should swap @@ -1513,9 +1532,9 @@ namespace ttl { */ template #if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER - bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) { + bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check = false) const { #else - bool swapTestDelaunay(const DartType& dart, bool cycling_check) { + bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check) const { #endif // The general strategy is taken from Cline & Renka. They claim that @@ -1627,17 +1646,17 @@ namespace ttl { * - Calls itself recursively */ template - void recSwapDelaunay(DartType& diagonal) { + void TriangulationHelper::recSwapDelaunay(DartType& diagonal) { - if (!ttl::swapTestDelaunay(diagonal)) - // ??? ttl::swapTestDelaunay also checks if boundary, so this can be optimized + if (!swapTestDelaunay(diagonal)) + // ??? swapTestDelaunay also checks if boundary, so this can be optimized return; // Get the other "edges" of the current triangle; see illustration above. DartType oppEdge1 = diagonal; oppEdge1.alpha1(); bool b1; - if (ttl::isBoundaryEdge(oppEdge1)) + if (isBoundaryEdge(oppEdge1)) b1 = true; else { b1 = false; @@ -1648,7 +1667,7 @@ namespace ttl { DartType oppEdge2 = diagonal; oppEdge2.alpha0().alpha1().alpha0(); bool b2; - if (ttl::isBoundaryEdge(oppEdge2)) + if (isBoundaryEdge(oppEdge2)) b2 = true; else { b2 = false; @@ -1656,7 +1675,7 @@ namespace ttl { } // Swap the given diagonal - TraitsType::swapEdge(diagonal); + triangulation.swapEdge(diagonal); if (!b1) recSwapDelaunay(oppEdge1); @@ -1669,7 +1688,7 @@ namespace ttl { /** Swaps edges away from the (interior) node associated with * \e dart such that that exactly three edges remain incident * with the node. - * This function is used as a first step in ttl::removeInteriorNode + * This function is used as a first step in removeInteriorNode * * \retval dart * A CCW dart incident with the node @@ -1689,10 +1708,10 @@ namespace ttl { * at the node that is given as input. * * \see - * ttl::swapEdgesAwayFromBoundaryNode + * swapEdgesAwayFromBoundaryNode */ template - void swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { + void TriangulationHelper::swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { // Same iteration as in fixEdgesAtCorner, but not boundary DartType dnext = dart; @@ -1706,14 +1725,14 @@ namespace ttl { // infinite loop with degree > 3. bool allowDegeneracy = true; - int degree = ttl::getDegreeOfNode(dart); + int degree = getDegreeOfNode(dart); DartType d_iter; while (degree > 3) { d_iter = dnext; dnext.alpha1().alpha2(); - if (ttl::swappableEdge(d_iter, allowDegeneracy)) { - TraitsType::swapEdge(d_iter); // swap the edge away + if (swappableEdge(d_iter, allowDegeneracy)) { + triangulation.swapEdge(d_iter); // swap the edge away // Collect swapped edges in the list // "Hide" the dart on the other side of the edge to avoid it being changed for // other swaps @@ -1733,7 +1752,7 @@ namespace ttl { /** Swaps edges away from the (boundary) node associated with * \e dart in such a way that when removing the edges that remain incident * with the node, the boundary of the triangulation will be convex. - * This function is used as a first step in ttl::removeBoundaryNode + * This function is used as a first step in removeBoundaryNode * * \retval dart * A CCW dart incident with the node @@ -1747,10 +1766,10 @@ namespace ttl { * - The node associated with \e dart is at the boundary of the triangulation. * * \see - * ttl::swapEdgesAwayFromInteriorNode + * swapEdgesAwayFromInteriorNode */ template - void swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { + void TriangulationHelper::swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { // All darts that are swappable. // To treat collinear nodes at an existing boundary, we must allow degeneracy @@ -1762,7 +1781,7 @@ namespace ttl { // - A dart on the swapped edge is delivered back in a position as // seen if it was glued to the edge when swapping (rotating) the edge CCW - //int degree = ttl::getDegreeOfNode(dart); + //int degree = getDegreeOfNode(dart); passes: @@ -1780,7 +1799,7 @@ passes: while (!bend) { d_next.alpha1().alpha2(); - if (ttl::isBoundaryEdge(d_next)) + if (isBoundaryEdge(d_next)) bend = true; // then it is CW since alpha2 // To allow removing among collinear nodes at the boundary, @@ -1789,13 +1808,13 @@ passes: tmp1 = d_iter; tmp1.alpha1(); tmp2 = d_iter; tmp2.alpha2().alpha1(); // don't bother with boundary (checked later) - if (ttl::isBoundaryEdge(tmp1) && ttl::isBoundaryEdge(tmp2)) + if (isBoundaryEdge(tmp1) && isBoundaryEdge(tmp2)) allowDegeneracy = true; else allowDegeneracy = false; - if (ttl::swappableEdge(d_iter, allowDegeneracy)) { - TraitsType::swapEdge(d_iter); + if (swappableEdge(d_iter, allowDegeneracy)) { + triangulation.swapEdge(d_iter); // Collect swapped edges in the list // "Hide" the dart on the other side of the edge to avoid it being changed for @@ -1821,7 +1840,7 @@ passes: else { d_iter.alpha1(); // CW and see below } - ttl::positionAtNextBoundaryEdge(d_iter); // CCW + positionAtNextBoundaryEdge(d_iter); // CCW dart = d_iter; // for next pass or output @@ -1839,7 +1858,7 @@ passes: * keep them in \e elist. */ template - void swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist) { + void TriangulationHelper::swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist) { typename DartListType::iterator it1, it2, it3, it4; DartType dart(*it); @@ -1867,7 +1886,7 @@ passes: it3 = find(elist.begin(), elist.end(), d3); it4 = find(elist.begin(), elist.end(), d4); - TraitsType::swapEdge(dart); + triangulation.swapEdge(dart); // Update the current dart which may have changed *it = dart; diff --git a/include/ttl/ttl_constr.h b/include/ttl/ttl_constr.h index 67b46fcbf0..125bddeb23 100644 --- a/include/ttl/ttl_constr.h +++ b/include/ttl/ttl_constr.h @@ -51,9 +51,6 @@ static ofstream ofile_constr("qweCons.dat"); #endif - -//using namespace std; - /** \brief Constrained Delaunay triangulation * * Basic generic algorithms in TTL for inserting a constrained edge between two existing nodes.\n @@ -61,7 +58,7 @@ * See documentation for the namespace ttl for general requirements and assumptions. * * \author -* Øyvind Hjelle, oyvindhj@ifi.uio.no +* �yvind Hjelle, oyvindhj@ifi.uio.no */ namespace ttl_constr { @@ -73,6 +70,9 @@ namespace ttl_constr { #endif +class ConstrainedTriangulation +{ + public: //------------------------------------------------------------------------------------------------ /* Checks if \e dart has start and end points in \e dstart and \e dend. * @@ -89,14 +89,14 @@ namespace ttl_constr { * A bool confirming that it's the constraint or not * * \using - * ttl::same_0_orbit + * same_0_orbit */ template - bool isTheConstraint(const DartType& dart, const DartType& dstart, const DartType& dend) { + static bool isTheConstraint(const DartType& dart, const DartType& dstart, const DartType& dend) { DartType d0 = dart; d0.alpha0(); // CW - if ((ttl::same_0_orbit(dstart, dart) && ttl::same_0_orbit(dend, d0)) || - (ttl::same_0_orbit(dstart, d0) && ttl::same_0_orbit(dend, dart))) { + if ((ttl::TriangulationHelper::same_0_orbit(dstart, dart) && ttl::TriangulationHelper::same_0_orbit(dend, d0)) || + (ttl::TriangulationHelper::same_0_orbit(dstart, d0) && ttl::TriangulationHelper::same_0_orbit(dend, dart))) { return true; } return false; @@ -123,7 +123,7 @@ namespace ttl_constr { * TraitsType::orient2d */ template - bool crossesConstraint(DartType& dstart, DartType& dend, DartType& d1, DartType& d2) { + static bool crossesConstraint(DartType& dstart, DartType& dend, DartType& d1, DartType& d2) { typename TraitsType::real_type orient_1 = TraitsType::orient2d(dstart,d1,dend); typename TraitsType::real_type orient_2 = TraitsType::orient2d(dstart,d2,dend); @@ -156,12 +156,12 @@ namespace ttl_constr { * The dart \e d making the smallest positive (or == 0) angle * * \using - * ttl::isBoundaryNode - * ttl::positionAtNextBoundaryEdge + * isBoundaryNode + * positionAtNextBoundaryEdge * TraitsType::orient2d */ template - DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) { + static DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) { // - Must boundary be convex??? // - Handle the case where the constraint is already present??? @@ -169,9 +169,9 @@ namespace ttl_constr { // (dstart and dend may define a boundary edge) DartType d_iter = dstart; - if (ttl::isBoundaryNode(d_iter)) { + if (ttl::TriangulationHelper::isBoundaryNode(d_iter)) { d_iter.alpha1(); // CW - ttl::positionAtNextBoundaryEdge(d_iter); // CCW (was rotated CW to the boundary) + ttl::TriangulationHelper::positionAtNextBoundaryEdge(d_iter); // CCW (was rotated CW to the boundary) } // assume convex boundary; see comments @@ -273,7 +273,7 @@ namespace ttl_constr { * Returns the next "collinear" starting node such that dend is returned when done. */ template - DartType findCrossingEdges(const DartType& dstart, const DartType& dend, ListType& elist) { + static DartType findCrossingEdges(const DartType& dstart, const DartType& dend, ListType& elist) { const DartType my_start = getAtSmallestAngle(dstart, dend); DartType my_end = getAtSmallestAngle(dend, dstart); @@ -387,15 +387,16 @@ namespace ttl_constr { * A list containing all the edges crossing the spesified constraint * * \using - * ttl::swappableEdge - * ttl::swapEdgeInList - * ttl::crossesConstraint - * ttl::isTheConstraint + * swappableEdge + * swapEdgeInList + * crossesConstraint + * isTheConstraint */ template - void transformToConstraint(DartType& dstart, DartType& dend, std::list& elist) { + void transformToConstraint(ttl::TriangulationHelper helper, DartType& dstart, DartType& dend, + std::list& elist) const { - typename list::iterator it, used; + typename std::list::iterator it, used; // We may enter in a situation where dstart and dend are altered because of a swap. // (The general rule is that darts inside the actual quadrilateral can be changed, @@ -423,7 +424,7 @@ namespace ttl_constr { if (counter > dartsInList) break; - if (ttl::swappableEdge(*it, true)) { + if (ttl::TriangulationHelper::swappableEdge(*it, true)) { // Dyn & Goren & Rippa 's notation: // The node assosiated with dart *it is denoted u_m. u_m has edges crossing the constraint // named w_1, ... , w_r . The other node to the edge assosiated with dart *it is w_s. @@ -456,7 +457,7 @@ namespace ttl_constr { end = true; // This is the only place swapping is called when inserting a constraint - ttl::swapEdgeInList(it,elist); + helper.swapEdgeInList(it,elist); // If we, during look-ahead, found that dstart and/or dend were in the quadrilateral, // we update them. @@ -512,6 +513,8 @@ namespace ttl_constr { } +}; // End of ConstrainedTriangulation class + }; // End of ttl_constr namespace scope @@ -546,14 +549,14 @@ namespace ttl { // (extension) * - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&) * * \using - * - ttl::optimizeDelaunay if \e optimize_delaunay is set to \c true + * - optimizeDelaunay if \e optimize_delaunay is set to \c true * * \par Assumes: * - The constrained edge must be inside the existing triangulation (and it cannot * cross the boundary of the triangulation). */ template - DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) { + DartType TriangulationHelper::insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) { // Assumes: // - It is the users responsibility to avoid crossing constraints @@ -567,8 +570,8 @@ namespace ttl { // (extension) // calls itself recursively. // RECURSION - list elist; - DartType next_start = ttl_constr::findCrossingEdges(dstart, dend, elist); + std::list elist; + DartType next_start = ttl_constr::ConstrainedTriangulation::findCrossingEdges(dstart, dend, elist); // If there are no crossing edges (elist is empty), we assume that the constraint // is an existing edge. @@ -583,7 +586,7 @@ namespace ttl { // (extension) // findCrossingEdges stops if it finds a node lying on the constraint. // A dart with this node as start node is returned // We call insertConstraint recursivly until the received dart is dend - if (!ttl::same_0_orbit(next_start, dend)) { + if (!same_0_orbit(next_start, dend)) { #ifdef DEBUG_TTL_CONSTR_PLOT cout << "RECURSION due to collinearity along constraint" << endl; @@ -594,7 +597,7 @@ namespace ttl { // (extension) // Swap edges such that the constraint edge is present in the transformed triangulation. if (elist.size() > 0) // by Thomas Sevaldrud - ttl_constr::transformToConstraint(dstart, next_start, elist); + ttl_constr::ConstrainedTriangulation::transformToConstraint(dstart, next_start, elist); #ifdef DEBUG_TTL_CONSTR_PLOT cout << "size of elist = " << elist.size() << endl; @@ -607,13 +610,13 @@ namespace ttl { // (extension) #endif // Optimize to constrained Delaunay triangulation if required. - typename list::iterator end_opt = elist.end(); + typename std::list::iterator end_opt = elist.end(); if (optimize_delaunay) { // Indicate that the constrained edge, which is the last element in the list, // should not be swapped --end_opt; - ttl::optimizeDelaunay(elist, end_opt); + optimizeDelaunay(elist, end_opt); } if(elist.size() == 0) // by Thomas Sevaldrud diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index 4f49e6bed4..430674887c 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -27,6 +27,10 @@ * @brief Class that computes missing connections on a PCB. */ +#ifdef USE_OPENMP +#include +#endif /* USE_OPENMP */ + #include #include @@ -964,13 +968,25 @@ void RN_DATA::Recalculate( int aNet ) { if( aNet < 0 ) // Recompute everything { - // Start with net number 1, as 0 stands for not connected - for( unsigned int i = 1; i < m_nets.size(); ++i ) + unsigned int tid, i, chunk, netCount; + netCount = m_board->GetNetCount(); + chunk = 1; + +#ifdef USE_OPENMP + #pragma omp parallel shared(chunk, netCount) private(i, tid) { - // Recompute only nets that require it - if( m_nets[i].IsDirty() ) - updateNet( i ); - } + tid = omp_get_thread_num(); + #pragma omp for schedule(guided, chunk) +#else /* USE_OPENMP */ + { +#endif + // Start with net number 1, as 0 stand for not connected + for( i = 1; i < netCount; ++i ) + { + if( m_nets[i].IsDirty() ) + updateNet( i ); + } + } /* end of parallel section */ } else if( aNet > 0 ) // Recompute only specific net { @@ -982,6 +998,7 @@ void RN_DATA::Recalculate( int aNet ) void RN_DATA::updateNet( int aNetCode ) { assert( aNetCode < (int) m_nets.size() ); + if( aNetCode < 1 ) return;