Merged ratsnest_threadsafe branch.

This commit is contained in:
Maciej Suminski 2014-02-05 11:55:04 +01:00
commit 468e14f003
7 changed files with 346 additions and 326 deletions

View File

@ -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" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden" )
endif() 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 ) if( MINGW )
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" ) set( CMAKE_EXE_LINKER_FLAGS_RELEASE "-s" )

View File

@ -51,8 +51,6 @@ using namespace hed;
using namespace std; using namespace std;
Triangulation* TTLtraits::triang_ = NULL;
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
int Node::id_count = 0; int Node::id_count = 0;
#endif #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, void Triangulation::createDelaunay(NodesContainer::iterator first,
NodesContainer::iterator last) { NodesContainer::iterator last) {
TTLtraits::triang_ = this;
cleanAll(); cleanAll();
EdgePtr bedge = initTwoEnclosingTriangles(first, last); EdgePtr bedge = initTwoEnclosingTriangles(first, last);
@ -178,7 +195,7 @@ void Triangulation::createDelaunay(NodesContainer::iterator first,
NodesContainer::iterator it; NodesContainer::iterator it;
for (it = first; it != last; ++it) { for (it = first; it != last; ++it) {
ttl::insertNode<TTLtraits>(d_iter, *it); helper->insertNode<TTLtraits>(d_iter, *it);
} }
// In general (e.g. for the triangle based data structure), the initial dart // 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.) // triangle "outside" the triangulation.)
// Assumes rectangular domain // Assumes rectangular domain
ttl::removeRectangularBoundary<TTLtraits>(dc); helper->removeRectangularBoundary<TTLtraits>(dc);
} }
@ -269,7 +286,7 @@ cout << "Iterate boundary 2" << endl;
Dart dart_iter = dart; Dart dart_iter = dart;
do { do {
if (ttl::isBoundaryEdge(dart_iter)) if (helper->isBoundaryEdge(dart_iter))
dart_iter.alpha0().alpha1(); dart_iter.alpha0().alpha1();
else else
dart_iter.alpha2().alpha1(); 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 #ifdef TTL_USE_NODE_FLAG
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// This is a "template" for accessing all nodes (but multiple tests) // 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 // Note that diagonal is both input and output and it is always
// kept in counterclockwise direction (this is not required by all // kept in counterclockwise direction (this is not required by all
// finctions in ttl:: now) // functions in TriangulationHelper now)
// Swap by rotating counterclockwise // Swap by rotating counterclockwise
// Use the same objects - no deletion or new objects // Use the same objects - no deletion or new objects
@ -567,7 +609,7 @@ bool Triangulation::checkDelaunay() const {
// only one of the half-edges // only one of the half-edges
if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) {
Dart dart(edge); Dart dart(edge);
if (ttl::swapTestDelaunay<TTLtraits>(dart)) { if (helper->swapTestDelaunay<TTLtraits>(dart)) {
noNotDelaunay++; noNotDelaunay++;
//printEdge(dart,os); os << "\n"; //printEdge(dart,os); os << "\n";
@ -610,7 +652,7 @@ void Triangulation::optimizeDelaunay() {
Dart dart(edge); Dart dart(edge);
// Constrained edges should not be swapped // Constrained edges should not be swapped
if (!edge->isConstrained() && ttl::swapTestDelaunay<TTLtraits>(dart, cycling_check)) { if (!edge->isConstrained() && helper->swapTestDelaunay<TTLtraits>(dart, cycling_check)) {
optimal = false; optimal = false;
swapEdge(edge); swapEdge(edge);
} }
@ -632,7 +674,7 @@ EdgePtr Triangulation::getInteriorNode() const {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (edge->getTwinEdge()) { if (edge->getTwinEdge()) {
if (!ttl::isBoundaryNode(Dart(edge))) if (!helper->isBoundaryNode(Dart(edge)))
return edge; return edge;
} }
edge = edge->getNextEdgeInFace(); 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; EdgePtr edge = e;
if (ttl::isBoundaryEdge(Dart(edge))) if (helper->isBoundaryEdge(Dart(edge)))
return edge; return edge;
edge = edge->getNextEdgeInFace(); edge = edge->getNextEdgeInFace();
if (ttl::isBoundaryEdge(Dart(edge))) if (helper->isBoundaryEdge(Dart(edge)))
return edge; return edge;
edge = edge->getNextEdgeInFace(); edge = edge->getNextEdgeInFace();
if (ttl::isBoundaryEdge(Dart(edge))) if (helper->isBoundaryEdge(Dart(edge)))
return edge; return edge;
return EdgePtr(); return EdgePtr();

View File

@ -69,9 +69,6 @@ namespace hed {
struct TTLtraits { struct TTLtraits {
// The actual triangulation object
static Triangulation* triang_;
/** The floating point type used in calculations /** The floating point type used in calculations
* involving scalar products and cross products. * involving scalar products and cross products.
*/ */
@ -172,127 +169,6 @@ namespace hed {
} }
//@} // End of Geometric Predicates Group //@} // 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.<br>
*
* \note
* This function is also present in the TTL as ttl::swapTestDelaunay.<br>
* Thus, the function can be implemented simply as:
* \code
* { return ttl::swapTestDelaunay<TTLtraits>(dart); }
* \endcode
*/
//static bool swapTestDelaunay(const Dart& dart) {
// return ttl::swapTestDelaunay<TTLtraits>(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<TTLtraits>(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.
*
* <center>
* \image html swapEdge.gif
* </center>
*
* \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.
*
* <center>
* \image html splitTriangle.gif
* </center>
*
* \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.
*
* <center>
* \image html reverse_splitTriangle.gif
* </center>
*/
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 }; // End of hed namespace

View File

@ -51,10 +51,13 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <ttl/ttl.h>
#include <ttl/ttl_util.h> #include <ttl/ttl_util.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
namespace ttl {
class TriangulationHelper;
};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// The half-edge data structure // The half-edge data structure
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -242,26 +245,75 @@ public:
class Triangulation { class Triangulation {
protected: protected:
list<EdgePtr> leadingEdges_; // one half-edge for each arc std::list<EdgePtr> leadingEdges_; // one half-edge for each arc
ttl::TriangulationHelper* helper;
void addLeadingEdge(EdgePtr& edge) { void addLeadingEdge(EdgePtr& edge) {
edge->setAsLeadingEdge(); edge->setAsLeadingEdge();
leadingEdges_.push_front( edge ); leadingEdges_.push_front( edge );
} }
bool removeLeadingEdgeFromList(EdgePtr& leadingEdge); bool removeLeadingEdgeFromList(EdgePtr& leadingEdge);
void cleanAll(); void cleanAll();
/** Swaps the edge associated with \e dart in the actual data structure.
*
* <center>
* \image html swapEdge.gif
* </center>
*
* \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.
*
* <center>
* \image html splitTriangle.gif
* </center>
*
* \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.
*
* <center>
* \image html reverse_splitTriangle.gif
* </center>
*/
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: public:
/// Default constructor /// Default constructor
Triangulation() {} Triangulation();
/// Copy constructor /// Copy constructor
Triangulation(const Triangulation& tr) { Triangulation(const Triangulation& tr);
std::cout << "Triangulation: Copy constructor not present - EXIT.";
exit(-1);
}
/// Destructor /// Destructor
~Triangulation() { cleanAll(); } ~Triangulation();
/// Creates a Delaunay triangulation from a set of points /// Creates a Delaunay triangulation from a set of points
void createDelaunay(NodesContainer::iterator first, void createDelaunay(NodesContainer::iterator first,
@ -295,20 +347,20 @@ public:
Dart createDart(); Dart createDart();
/// Returns a list of "triangles" (one leading half-edge for each triangle) /// Returns a list of "triangles" (one leading half-edge for each triangle)
const list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; } const std::list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; }
/// Returns the number of triangles /// Returns the number of triangles
int noTriangles() const { return (int)leadingEdges_.size(); } int noTriangles() const { return (int)leadingEdges_.size(); }
/// Returns a list of half-edges (one half-edge for each arc) /// Returns a list of half-edges (one half-edge for each arc)
list<EdgePtr>* getEdges(bool skip_boundary_edges = false) const; std::list<EdgePtr>* getEdges(bool skip_boundary_edges = false) const;
#ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG
/// Sets flag in all the nodes /// Sets flag in all the nodes
void flagNodes(bool flag) const; void flagNodes(bool flag) const;
/// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node. /// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node.
list<NodePtr>* getNodes() const; std::list<NodePtr>* getNodes() const;
#endif #endif
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped) /// 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) /// Returns an arbitrary interior node (as the source node of the returned edge)
EdgePtr getInteriorNode() const; EdgePtr getInteriorNode() const;
EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) const;
/// Returns an arbitrary boundary edge /// Returns an arbitrary boundary edge
EdgePtr getBoundaryEdge() const; EdgePtr getBoundaryEdge() const;
/// Print edges for plotting with, e.g., gnuplot /// Print edges for plotting with, e.g., gnuplot
void printEdges(std::ofstream& os) const; void printEdges(std::ofstream& os) const;
friend class ttl::TriangulationHelper;
}; // End of class Triangulation }; // End of class Triangulation

View File

@ -52,8 +52,6 @@
} }
#endif #endif
using std::list;
// Next on TOPOLOGY: // Next on TOPOLOGY:
// - get triangle strips // - get triangle strips
@ -102,7 +100,7 @@
* - \e CW - clockwise * - \e CW - clockwise
* - \e 0_orbit, \e 1_orbit and \e 2_orbit: A sequence of darts around * - \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; * 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 * - \e arc - In a triangulation an arc is equivalent with an edge
* *
* \see * \see
@ -115,15 +113,15 @@
namespace ttl { namespace ttl {
class TriangulationHelper
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS
//------------------------------------------------------------------------------------------------
// ----------------------------------- Forward declarations -------------------------------------
//------------------------------------------------------------------------------------------------
#if ((_MSC_VER > 0) && (_MSC_VER < 1300)) public:
#else TriangulationHelper(hed::Triangulation& triang) : triangulation(triang)
{
}
// Delaunay Triangulation // Delaunay Triangulation
// ---------------------- // ----------------------
template<class TraitsType, class DartType, class PointType> template<class TraitsType, class DartType, class PointType>
@ -145,55 +143,55 @@ namespace ttl {
// Topological and Geometric Queries // Topological and Geometric Queries
// --------------------------------- // ---------------------------------
template<class TraitsType, class PointType, class DartType> template<class TraitsType, class PointType, class DartType>
bool locateFaceSimplest(const PointType& point, DartType& dart); static bool locateFaceSimplest(const PointType& point, DartType& dart);
template<class TraitsType, class PointType, class DartType> template<class TraitsType, class PointType, class DartType>
bool locateTriangle(const PointType& point, DartType& dart); static bool locateTriangle(const PointType& point, DartType& dart);
template<class TraitsType, class PointType, class DartType> template<class TraitsType, class PointType, class DartType>
bool inTriangleSimplest(const PointType& point, const DartType& dart); static bool inTriangleSimplest(const PointType& point, const DartType& dart);
template<class TraitsType, class PointType, class DartType> template<class TraitsType, class PointType, class DartType>
bool inTriangle(const PointType& point, const DartType& dart); static bool inTriangle(const PointType& point, const DartType& dart);
template<class DartType, class DartListType> template<class DartType, class DartListType>
void getBoundary(const DartType& dart, DartListType& boundary); static void getBoundary(const DartType& dart, DartListType& boundary);
template<class DartType> template<class DartType>
bool isBoundaryEdge(const DartType& dart); static bool isBoundaryEdge(const DartType& dart);
template<class DartType> template<class DartType>
bool isBoundaryFace(const DartType& dart); static bool isBoundaryFace(const DartType& dart);
template<class DartType> template<class DartType>
bool isBoundaryNode(const DartType& dart); static bool isBoundaryNode(const DartType& dart);
template<class DartType> template<class DartType>
int getDegreeOfNode(const DartType& dart); static int getDegreeOfNode(const DartType& dart);
template<class DartType, class DartListType> template<class DartType, class DartListType>
void get_0_orbit_interior(const DartType& dart, DartListType& orbit); static void get_0_orbit_interior(const DartType& dart, DartListType& orbit);
template<class DartType, class DartListType> template<class DartType, class DartListType>
void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit);
template<class DartType> template<class DartType>
bool same_0_orbit(const DartType& d1, const DartType& d2); static bool same_0_orbit(const DartType& d1, const DartType& d2);
template<class DartType> template<class DartType>
bool same_1_orbit(const DartType& d1, const DartType& d2); static bool same_1_orbit(const DartType& d1, const DartType& d2);
template<class DartType> template<class DartType>
bool same_2_orbit(const DartType& d1, const DartType& d2); static bool same_2_orbit(const DartType& d1, const DartType& d2);
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false);
template<class DartType> template<class DartType>
void positionAtNextBoundaryEdge(DartType& dart); static void positionAtNextBoundaryEdge(DartType& dart);
template<class TraitsType, class DartType> template<class TraitsType, class DartType>
bool convexBoundary(const DartType& dart); static bool convexBoundary(const DartType& dart);
// Utilities for Delaunay Triangulation // Utilities for Delaunay Triangulation
@ -205,7 +203,7 @@ namespace ttl {
void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end); void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end);
template<class TraitsType, class DartType> template<class TraitsType, class DartType>
bool swapTestDelaunay(const DartType& dart, bool cycling_check = false); bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) const;
template<class TraitsType, class DartType> template<class TraitsType, class DartType>
void recSwapDelaunay(DartType& diagonal); void recSwapDelaunay(DartType& diagonal);
@ -223,9 +221,29 @@ namespace ttl {
// Constrained Triangulation // Constrained Triangulation
// ------------------------- // -------------------------
template<class TraitsType, class DartType> template<class TraitsType, class DartType>
DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); static DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay);
#endif private:
hed::Triangulation& triangulation;
template <class TraitsType, class ForwardIterator, class DartType>
void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart);
template <class TopologyElementType, class DartType>
static bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart);
template <class TraitsType, class NodeType, class DartType>
static bool locateFaceWithNode(const NodeType& node, DartType& dart_iter);
template <class DartType>
static void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3);
template <class DartType>
static void getNeighborNodes(const DartType& dart, std::list<DartType>& node_list, bool& boundary);
template <class TraitsType, class DartType>
static bool degenerateTriangle(const DartType& dart);
};
#endif // DOXYGEN_SHOULD_SKIP_THIS #endif // DOXYGEN_SHOULD_SKIP_THIS
@ -245,7 +263,7 @@ namespace ttl {
* can be created as two triangles forming a rectangle that contains * can be created as two triangles forming a rectangle that contains
* all the points. * all the points.
* After \c insertNode has been called repeatedly with 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 * at the boundary of the triangulation so that the boundary
* form the convex hull of the points. * form the convex hull of the points.
* *
@ -268,19 +286,19 @@ namespace ttl {
* - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType&) * - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType&)
* *
* \using * \using
* - ttl::locateTriangle * - locateTriangle
* - ttl::recSwapDelaunay * - recSwapDelaunay
* *
* \note * \note
* - For efficiency reasons \e dart should be close to the insertion \e point. * - For efficiency reasons \e dart should be close to the insertion \e point.
* *
* \see * \see
* ttl::removeRectangularBoundary * removeRectangularBoundary
*/ */
template <class TraitsType, class DartType, class PointType> template <class TraitsType, class DartType, class PointType>
bool insertNode(DartType& dart, PointType& point) { bool TriangulationHelper::insertNode(DartType& dart, PointType& point) {
bool found = ttl::locateTriangle<TraitsType>(point, dart); bool found = locateTriangle<TraitsType>(point, dart);
if (!found) { if (!found) {
#ifdef DEBUG_TTL #ifdef DEBUG_TTL
cout << "ERROR: Triangulation::insertNode: NO triangle found. /n"; 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 // ??? can we hide the dart? this is not possible if one triangle only
TraitsType::splitTriangle(dart, point); triangulation.splitTriangle(dart, point);
DartType d1 = dart; DartType d1 = dart;
d1.alpha2().alpha1().alpha2().alpha0().alpha1(); d1.alpha2().alpha1().alpha2().alpha0().alpha1();
@ -304,14 +322,14 @@ namespace ttl {
//DartType dsav = d3; //DartType dsav = d3;
d3.alpha0().alpha1(); d3.alpha0().alpha1();
//if (!TraitsType::fixedEdge(d1) && !ttl::isBoundaryEdge(d1)) { //if (!TraitsType::fixedEdge(d1) && !isBoundaryEdge(d1)) {
if (!ttl::isBoundaryEdge(d1)) { if (!isBoundaryEdge(d1)) {
d1.alpha2(); d1.alpha2();
recSwapDelaunay<TraitsType>(d1); recSwapDelaunay<TraitsType>(d1);
} }
//if (!TraitsType::fixedEdge(d2) && !ttl::isBoundaryEdge(d2)) { //if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) {
if (!ttl::isBoundaryEdge(d2)) { if (!isBoundaryEdge(d2)) {
d2.alpha2(); d2.alpha2();
recSwapDelaunay<TraitsType>(d2); recSwapDelaunay<TraitsType>(d2);
} }
@ -319,8 +337,8 @@ namespace ttl {
// Preserve the incoming dart as output incident to the node and CCW // Preserve the incoming dart as output incident to the node and CCW
//d = dsav.alpha2(); //d = dsav.alpha2();
dart.alpha2(); dart.alpha2();
//if (!TraitsType::fixedEdge(d3) && !ttl::isBoundaryEdge(d3)) { //if (!TraitsType::fixedEdge(d3) && !isBoundaryEdge(d3)) {
if (!ttl::isBoundaryEdge(d3)) { if (!isBoundaryEdge(d3)) {
d3.alpha2(); d3.alpha2();
recSwapDelaunay<TraitsType>(d3); recSwapDelaunay<TraitsType>(d3);
} }
@ -332,7 +350,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class TraitsType, class ForwardIterator, class DartType> template <class TraitsType, class ForwardIterator, class DartType>
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. // Assumes that the dereferenced point objects are pointers.
// References to the point objects are then passed to TTL. // References to the point objects are then passed to TTL.
@ -355,14 +373,14 @@ namespace ttl {
* Output: A CCW dart at the new boundary * Output: A CCW dart at the new boundary
* *
* \using * \using
* - ttl::removeBoundaryNode * - removeBoundaryNode
* *
* \note * \note
* - This function requires that the boundary of the triangulation is * - This function requires that the boundary of the triangulation is
* a rectangle with four nodes (one in each corner). * a rectangle with four nodes (one in each corner).
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void removeRectangularBoundary(DartType& dart) { void TriangulationHelper::removeRectangularBoundary(DartType& dart) {
DartType d_next = dart; DartType d_next = dart;
DartType d_iter; DartType d_iter;
@ -370,8 +388,8 @@ namespace ttl {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
d_iter = d_next; d_iter = d_next;
d_next.alpha0(); d_next.alpha0();
ttl::positionAtNextBoundaryEdge(d_next); positionAtNextBoundaryEdge(d_next);
ttl::removeBoundaryNode<TraitsType>(d_iter); removeBoundaryNode<TraitsType>(d_iter);
} }
dart = d_next; // Return a dart at the new boundary dart = d_next; // Return a dart at the new boundary
@ -383,20 +401,20 @@ namespace ttl {
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - ttl::removeBoundaryNode if \e dart represents a node at the boundary * - removeBoundaryNode if \e dart represents a node at the boundary
* - ttl::removeInteriorNode if \e dart represents an interior node * - removeInteriorNode if \e dart represents an interior node
* *
* \note * \note
* - The node cannot belong to a fixed (constrained) edge that is not * - The node cannot belong to a fixed (constrained) edge that is not
* swappable. (An endless loop is likely to occur in this case). * swappable. (An endless loop is likely to occur in this case).
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void removeNode(DartType& dart) { void TriangulationHelper::removeNode(DartType& dart) {
if (ttl::isBoundaryNode(dart)) if (isBoundaryNode(dart))
ttl::removeBoundaryNode<TraitsType>(dart); removeBoundaryNode<TraitsType>(dart);
else else
ttl::removeInteriorNode<TraitsType>(dart); removeInteriorNode<TraitsType>(dart);
} }
@ -405,14 +423,14 @@ namespace ttl {
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - ttl::swapEdgesAwayFromBoundaryNode * - swapEdgesAwayFromBoundaryNode
* - ttl::optimizeDelaunay * - optimizeDelaunay
* *
* \require * \require
* - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType::removeBoundaryTriangle" (Dart&) * - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType::removeBoundaryTriangle" (Dart&)
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void removeBoundaryNode(DartType& dart) { void TriangulationHelper::removeBoundaryNode(DartType& dart) {
// ... and update Delaunay // ... and update Delaunay
// - CCW dart must be given (for remove) // - 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. // we assume that there is not only one triangle left in the triangulation.
// Position at boundary edge and CCW // 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) dart.alpha1(); // ensures that next function delivers back a CCW dart (if the given dart is CCW)
ttl::positionAtNextBoundaryEdge(dart); positionAtNextBoundaryEdge(dart);
} }
list<DartType> swapped_edges; std::list<DartType> swapped_edges;
ttl::swapEdgesAwayFromBoundaryNode<TraitsType>(dart, swapped_edges); swapEdgesAwayFromBoundaryNode<TraitsType>(dart, swapped_edges);
// Remove boundary triangles and remove the new boundary from the list // Remove boundary triangles and remove the new boundary from the list
// of swapped edges, see below. // of swapped edges, see below.
@ -435,7 +453,7 @@ namespace ttl {
bool bend = false; bool bend = false;
while (bend == false) { while (bend == false) {
dnext.alpha1().alpha2(); dnext.alpha1().alpha2();
if (ttl::isBoundaryEdge(dnext)) if (isBoundaryEdge(dnext))
bend = true; // Stop when boundary bend = true; // Stop when boundary
// Generic: Also remove the new boundary from the list of swapped edges // 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 n_bedge.alpha1().alpha0().alpha1().alpha2(); // new boundary edge
// ??? can we avoid find if we do this in swap away? // ??? can we avoid find if we do this in swap away?
typename list<DartType>::iterator it; typename std::list<DartType>::iterator it;
it = find(swapped_edges.begin(), swapped_edges.end(), n_bedge); it = find(swapped_edges.begin(), swapped_edges.end(), n_bedge);
if (it != swapped_edges.end()) if (it != swapped_edges.end())
swapped_edges.erase(it); swapped_edges.erase(it);
// Remove the boundary triangle // Remove the boundary triangle
TraitsType::removeBoundaryTriangle(d_iter); triangulation.removeBoundaryTriangle(d_iter);
d_iter = dnext; d_iter = dnext;
} }
// Optimize Delaunay // Optimize Delaunay
typedef list<DartType> DartListType; typedef std::list<DartType> DartListType;
ttl::optimizeDelaunay<TraitsType, DartType, DartListType>(swapped_edges); optimizeDelaunay<TraitsType, DartType, DartListType>(swapped_edges);
} }
@ -465,8 +483,8 @@ namespace ttl {
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - ttl::swapEdgesAwayFromInteriorNode * - swapEdgesAwayFromInteriorNode
* - ttl::optimizeDelaunay * - optimizeDelaunay
* *
* \require * \require
* - \ref hed::TTLtraits::reverse_splitTriangle "TraitsType::reverse_splitTriangle" (Dart&) * - \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). * swappable. (An endless loop is likely to occur in this case).
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void removeInteriorNode(DartType& dart) { void TriangulationHelper::removeInteriorNode(DartType& dart) {
// ... and update to Delaunay. // ... and update to Delaunay.
// Must allow degeneracy temporarily, see comments in swap edges away // Must allow degeneracy temporarily, see comments in swap edges away
@ -492,13 +510,13 @@ namespace ttl {
// Assumes dart is counterclockwise // Assumes dart is counterclockwise
list<DartType> swapped_edges; std::list<DartType> swapped_edges;
ttl::swapEdgesAwayFromInteriorNode<TraitsType>(dart, swapped_edges); swapEdgesAwayFromInteriorNode<TraitsType>(dart, swapped_edges);
// The reverse operation of split triangle: // The reverse operation of split triangle:
// Make one triangle of the three triangles at the node associated with dart // Make one triangle of the three triangles at the node associated with dart
// TraitsType:: // TraitsType::
TraitsType::reverse_splitTriangle(dart); triangulation.reverse_splitTriangle(dart);
// ???? Not generic yet if we are very strict: // ???? Not generic yet if we are very strict:
// When calling unsplit triangle, darts at the three opposite sides may // 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, // Note the theoretical result: if there are no edges in the list,
// the triangulation is Delaunay already // the triangulation is Delaunay already
ttl::optimizeDelaunay<TraitsType, DartType>(swapped_edges); optimizeDelaunay<TraitsType, DartType>(swapped_edges);
} }
//@} // End of Delaunay Triangulation Group //@} // End of Delaunay Triangulation Group
@ -527,7 +545,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class TopologyElementType, class DartType> template <class TopologyElementType, class DartType>
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 // Check if the given topology element (node, edge or face) is a member of the face
// Assumes: // Assumes:
@ -547,7 +565,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class TraitsType, class NodeType, class DartType> template <class TraitsType, class NodeType, class DartType>
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 // Locate a face in the topology structure with the given node as a member
// Assumes: // Assumes:
// - TraitsType::orient2d(DartType, DartType, NodeType) // - TraitsType::orient2d(DartType, DartType, NodeType)
@ -594,10 +612,10 @@ namespace ttl {
* \e regular as explained above. * \e regular as explained above.
* *
* \see * \see
* ttl::locateTriangle * locateTriangle
*/ */
template <class TraitsType, class PointType, class DartType> template <class TraitsType, class PointType, class DartType>
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 // 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) // But inTriangle may be called in case of true (may update to inFace2)
// Convex boundary // Convex boundary
@ -660,11 +678,11 @@ namespace ttl {
* then the edge associated with \e dart will be at the boundary of the triangulation. * then the edge associated with \e dart will be at the boundary of the triangulation.
* *
* \using * \using
* - ttl::locateFaceSimplest * - locateFaceSimplest
* - ttl::inTriangle * - inTriangle
*/ */
template <class TraitsType, class PointType, class DartType> template <class TraitsType, class PointType, class DartType>
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 // 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 // i) avoids concluding that a point is inside a triangle if it is not inside
// ii) avoids infinite loops // ii) avoids infinite loops
@ -713,10 +731,10 @@ namespace ttl {
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&) * - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&)
* *
* \see * \see
* ttl::inTriangle for a more robust function * inTriangle for a more robust function
*/ */
template <class TraitsType, class PointType, class DartType> template <class TraitsType, class PointType, class DartType>
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 // 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 // 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&) * - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, PointType&)
* *
* \see * \see
* ttl::inTriangleSimplest * inTriangleSimplest
*/ */
template <class TraitsType, class PointType, class DartType> template <class TraitsType, class PointType, class DartType>
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 // 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 // ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH
@ -841,7 +859,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class DartType> template <class DartType>
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; DartType dart_iter = dart;
@ -886,7 +904,7 @@ namespace ttl {
* - DartListType::push_back (DartType&) * - DartListType::push_back (DartType&)
*/ */
template <class DartType, class DartListType> template <class DartType, class DartListType>
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) // assumes the given dart is at the boundary (by edge)
DartType dart_iter(dart); DartType dart_iter(dart);
@ -932,7 +950,7 @@ namespace ttl {
* \endcode * \endcode
*/ */
template <class DartType> template <class DartType>
bool isBoundaryEdge(const DartType& dart) { bool TriangulationHelper::isBoundaryEdge(const DartType& dart) {
DartType dart_iter = dart; DartType dart_iter = dart;
if (dart_iter.alpha2() == dart) if (dart_iter.alpha2() == dart)
@ -947,7 +965,7 @@ namespace ttl {
* the boundary of the triangulation. * the boundary of the triangulation.
*/ */
template <class DartType> template <class DartType>
bool isBoundaryFace(const DartType& dart) { bool TriangulationHelper::isBoundaryFace(const DartType& dart) {
// Strategy: boundary if alpha2(d)=d // Strategy: boundary if alpha2(d)=d
@ -976,7 +994,7 @@ namespace ttl {
* the boundary of the triangulation. * the boundary of the triangulation.
*/ */
template <class DartType> template <class DartType>
bool isBoundaryNode(const DartType& dart) { bool TriangulationHelper::isBoundaryNode(const DartType& dart) {
// Strategy: boundary if alpha2(d)=d // 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. * the number of edges joining \e V with another node in the triangulation.
*/ */
template <class DartType> template <class DartType>
int getDegreeOfNode(const DartType& dart) { int TriangulationHelper::getDegreeOfNode(const DartType& dart) {
DartType dart_iter(dart); DartType dart_iter(dart);
DartType dart_prev; DartType dart_prev;
@ -1069,7 +1087,8 @@ namespace ttl {
// Private/Hidden function // Private/Hidden function
template <class DartType> template <class DartType>
void getNeighborNodes(const DartType& dart, std::list<DartType>& node_list, bool& boundary) { void TriangulationHelper::getNeighborNodes(const DartType& dart,
std::list<DartType>& node_list, bool& boundary) {
DartType dart_iter(dart); DartType dart_iter(dart);
@ -1131,10 +1150,10 @@ namespace ttl {
* - DartListType::push_back (DartType&) * - DartListType::push_back (DartType&)
* *
* \see * \see
* ttl::get_0_orbit_boundary * get_0_orbit_boundary
*/ */
template <class DartType, class DartListType> template <class DartType, class DartListType>
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; DartType d_iter = dart;
orbit.push_back(d_iter); orbit.push_back(d_iter);
@ -1165,10 +1184,10 @@ namespace ttl {
* - The last dart in the sequence have opposite orientation compared to the others! * - The last dart in the sequence have opposite orientation compared to the others!
* *
* \see * \see
* ttl::get_0_orbit_interior * get_0_orbit_interior
*/ */
template <class DartType, class DartListType> template <class DartType, class DartListType>
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 dart_prev;
DartType d_iter = dart; DartType d_iter = dart;
@ -1195,17 +1214,17 @@ namespace ttl {
* own version.) * own version.)
*/ */
template <class DartType> template <class DartType>
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 // Two copies of the same dart
DartType d_iter = d2; DartType d_iter = d2;
DartType d_end = d2; DartType d_end = d2;
if (ttl::isBoundaryNode(d_iter)) { if (isBoundaryNode(d_iter)) {
// position at both boundary edges // position at both boundary edges
ttl::positionAtNextBoundaryEdge(d_iter); positionAtNextBoundaryEdge(d_iter);
d_end.alpha1(); d_end.alpha1();
ttl::positionAtNextBoundaryEdge(d_end); positionAtNextBoundaryEdge(d_end);
} }
for (;;) { for (;;) {
@ -1229,7 +1248,7 @@ namespace ttl {
* \e d1 and/or \e d2 can be CCW or CW. * \e d1 and/or \e d2 can be CCW or CW.
*/ */
template <class DartType> template <class DartType>
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; DartType d_iter = d2;
// (Also works at the boundary) // (Also works at the boundary)
@ -1245,7 +1264,7 @@ namespace ttl {
* \e d1 and/or \e d2 can be CCW or CW * \e d1 and/or \e d2 can be CCW or CW
*/ */
template <class DartType> template <class DartType>
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; DartType d_iter = d2;
if (d_iter == d1 || d_iter.alpha0() == d1 || if (d_iter == d1 || d_iter.alpha0() == d1 ||
@ -1259,7 +1278,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function // Private/Hidden function
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
bool degenerateTriangle(const DartType& dart) { bool TriangulationHelper::degenerateTriangle(const DartType& dart) {
// Check if triangle is degenerate // Check if triangle is degenerate
// Assumes CCW dart // Assumes CCW dart
@ -1287,7 +1306,7 @@ namespace ttl {
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (Dart&, Dart&) * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (Dart&, Dart&)
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
bool swappableEdge(const DartType& dart, bool allowDegeneracy) { bool TriangulationHelper::swappableEdge(const DartType& dart, bool allowDegeneracy) {
// How "safe" is it? // How "safe" is it?
@ -1340,7 +1359,7 @@ namespace ttl {
* infinit loop occurs. * infinit loop occurs.
*/ */
template <class DartType> template <class DartType>
void positionAtNextBoundaryEdge(DartType& dart) { void TriangulationHelper::positionAtNextBoundaryEdge(DartType& dart) {
DartType dart_prev; DartType dart_prev;
@ -1365,14 +1384,14 @@ namespace ttl {
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (const Dart&, const Dart&) * - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (const Dart&, const Dart&)
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
bool convexBoundary(const DartType& dart) { bool TriangulationHelper::convexBoundary(const DartType& dart) {
list<DartType> blist; std::list<DartType> blist;
ttl::getBoundary(dart, blist); getBoundary(dart, blist);
int no; int no;
no = (int)blist.size(); no = (int)blist.size();
typename list<DartType>::const_iterator bit = blist.begin(); typename std::list<DartType>::const_iterator bit = blist.begin();
DartType d1 = *bit; DartType d1 = *bit;
++bit; ++bit;
DartType d2; DartType d2;
@ -1428,17 +1447,17 @@ namespace ttl {
* seen if it was glued to the edge when swapping (rotating) the edge CCW * seen if it was glued to the edge when swapping (rotating) the edge CCW
* *
* \using * \using
* - ttl::swapTestDelaunay * - swapTestDelaunay
*/ */
template <class TraitsType, class DartType, class DartListType> template <class TraitsType, class DartType, class DartListType>
void optimizeDelaunay(DartListType& elist) { void TriangulationHelper::optimizeDelaunay(DartListType& elist) {
optimizeDelaunay<TraitsType, DartType, DartListType>(elist, elist.end()); optimizeDelaunay<TraitsType, DartType, DartListType>(elist, elist.end());
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
template <class TraitsType, class DartType, class DartListType> template <class TraitsType, class DartType, class DartListType>
void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) { void TriangulationHelper::optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) {
// CCW darts // CCW darts
// Optimize here means Delaunay, but could be any criterion by // Optimize here means Delaunay, but could be any criterion by
@ -1481,14 +1500,14 @@ namespace ttl {
while(!optimal) { while(!optimal) {
optimal = true; optimal = true;
for (it = elist.begin(); it != end_opt; ++it) { for (it = elist.begin(); it != end_opt; ++it) {
if (ttl::swapTestDelaunay<TraitsType>(*it, cycling_check)) { if (swapTestDelaunay<TraitsType>(*it, cycling_check)) {
// Preserve darts. Potential darts in the list are: // Preserve darts. Potential darts in the list are:
// - The current dart // - The current dart
// - the four CCW darts on the boundary of the quadrilateral // - the four CCW darts on the boundary of the quadrilateral
// (the current arc has only one dart) // (the current arc has only one dart)
ttl::swapEdgeInList<TraitsType, DartType>(it, elist); swapEdgeInList<TraitsType, DartType>(it, elist);
optimal = false; optimal = false;
} // end if should swap } // end if should swap
@ -1513,9 +1532,9 @@ namespace ttl {
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
#if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER #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 #else
bool swapTestDelaunay(const DartType& dart, bool cycling_check) { bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check) const {
#endif #endif
// The general strategy is taken from Cline & Renka. They claim that // The general strategy is taken from Cline & Renka. They claim that
@ -1627,17 +1646,17 @@ namespace ttl {
* - Calls itself recursively * - Calls itself recursively
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void recSwapDelaunay(DartType& diagonal) { void TriangulationHelper::recSwapDelaunay(DartType& diagonal) {
if (!ttl::swapTestDelaunay<TraitsType>(diagonal)) if (!swapTestDelaunay<TraitsType>(diagonal))
// ??? ttl::swapTestDelaunay also checks if boundary, so this can be optimized // ??? swapTestDelaunay also checks if boundary, so this can be optimized
return; return;
// Get the other "edges" of the current triangle; see illustration above. // Get the other "edges" of the current triangle; see illustration above.
DartType oppEdge1 = diagonal; DartType oppEdge1 = diagonal;
oppEdge1.alpha1(); oppEdge1.alpha1();
bool b1; bool b1;
if (ttl::isBoundaryEdge(oppEdge1)) if (isBoundaryEdge(oppEdge1))
b1 = true; b1 = true;
else { else {
b1 = false; b1 = false;
@ -1648,7 +1667,7 @@ namespace ttl {
DartType oppEdge2 = diagonal; DartType oppEdge2 = diagonal;
oppEdge2.alpha0().alpha1().alpha0(); oppEdge2.alpha0().alpha1().alpha0();
bool b2; bool b2;
if (ttl::isBoundaryEdge(oppEdge2)) if (isBoundaryEdge(oppEdge2))
b2 = true; b2 = true;
else { else {
b2 = false; b2 = false;
@ -1656,7 +1675,7 @@ namespace ttl {
} }
// Swap the given diagonal // Swap the given diagonal
TraitsType::swapEdge(diagonal); triangulation.swapEdge(diagonal);
if (!b1) if (!b1)
recSwapDelaunay<TraitsType>(oppEdge1); recSwapDelaunay<TraitsType>(oppEdge1);
@ -1669,7 +1688,7 @@ namespace ttl {
/** Swaps edges away from the (interior) node associated with /** Swaps edges away from the (interior) node associated with
* \e dart such that that exactly three edges remain incident * \e dart such that that exactly three edges remain incident
* with the node. * 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 * \retval dart
* A CCW dart incident with the node * A CCW dart incident with the node
@ -1689,10 +1708,10 @@ namespace ttl {
* at the node that is given as input. * at the node that is given as input.
* *
* \see * \see
* ttl::swapEdgesAwayFromBoundaryNode * swapEdgesAwayFromBoundaryNode
*/ */
template <class TraitsType, class DartType, class ListType> template <class TraitsType, class DartType, class ListType>
void swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { void TriangulationHelper::swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) {
// Same iteration as in fixEdgesAtCorner, but not boundary // Same iteration as in fixEdgesAtCorner, but not boundary
DartType dnext = dart; DartType dnext = dart;
@ -1706,14 +1725,14 @@ namespace ttl {
// infinite loop with degree > 3. // infinite loop with degree > 3.
bool allowDegeneracy = true; bool allowDegeneracy = true;
int degree = ttl::getDegreeOfNode(dart); int degree = getDegreeOfNode(dart);
DartType d_iter; DartType d_iter;
while (degree > 3) { while (degree > 3) {
d_iter = dnext; d_iter = dnext;
dnext.alpha1().alpha2(); dnext.alpha1().alpha2();
if (ttl::swappableEdge<TraitsType>(d_iter, allowDegeneracy)) { if (swappableEdge<TraitsType>(d_iter, allowDegeneracy)) {
TraitsType::swapEdge(d_iter); // swap the edge away triangulation.swapEdge(d_iter); // swap the edge away
// Collect swapped edges in the list // Collect swapped edges in the list
// "Hide" the dart on the other side of the edge to avoid it being changed for // "Hide" the dart on the other side of the edge to avoid it being changed for
// other swaps // other swaps
@ -1733,7 +1752,7 @@ namespace ttl {
/** Swaps edges away from the (boundary) node associated with /** Swaps edges away from the (boundary) node associated with
* \e dart in such a way that when removing the edges that remain incident * \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. * 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 * \retval dart
* A CCW dart incident with the node * 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. * - The node associated with \e dart is at the boundary of the triangulation.
* *
* \see * \see
* ttl::swapEdgesAwayFromInteriorNode * swapEdgesAwayFromInteriorNode
*/ */
template <class TraitsType, class DartType, class ListType> template <class TraitsType, class DartType, class ListType>
void swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { void TriangulationHelper::swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) {
// All darts that are swappable. // All darts that are swappable.
// To treat collinear nodes at an existing boundary, we must allow degeneracy // 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 // - 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 // seen if it was glued to the edge when swapping (rotating) the edge CCW
//int degree = ttl::getDegreeOfNode(dart); //int degree = getDegreeOfNode(dart);
passes: passes:
@ -1780,7 +1799,7 @@ passes:
while (!bend) { while (!bend) {
d_next.alpha1().alpha2(); d_next.alpha1().alpha2();
if (ttl::isBoundaryEdge(d_next)) if (isBoundaryEdge(d_next))
bend = true; // then it is CW since alpha2 bend = true; // then it is CW since alpha2
// To allow removing among collinear nodes at the boundary, // To allow removing among collinear nodes at the boundary,
@ -1789,13 +1808,13 @@ passes:
tmp1 = d_iter; tmp1.alpha1(); tmp1 = d_iter; tmp1.alpha1();
tmp2 = d_iter; tmp2.alpha2().alpha1(); // don't bother with boundary (checked later) 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; allowDegeneracy = true;
else else
allowDegeneracy = false; allowDegeneracy = false;
if (ttl::swappableEdge<TraitsType>(d_iter, allowDegeneracy)) { if (swappableEdge<TraitsType>(d_iter, allowDegeneracy)) {
TraitsType::swapEdge(d_iter); triangulation.swapEdge(d_iter);
// Collect swapped edges in the list // Collect swapped edges in the list
// "Hide" the dart on the other side of the edge to avoid it being changed for // "Hide" the dart on the other side of the edge to avoid it being changed for
@ -1821,7 +1840,7 @@ passes:
else { else {
d_iter.alpha1(); // CW and see below d_iter.alpha1(); // CW and see below
} }
ttl::positionAtNextBoundaryEdge(d_iter); // CCW positionAtNextBoundaryEdge(d_iter); // CCW
dart = d_iter; // for next pass or output dart = d_iter; // for next pass or output
@ -1839,7 +1858,7 @@ passes:
* keep them in \e elist. * keep them in \e elist.
*/ */
template <class TraitsType, class DartType, class DartListType> template <class TraitsType, class DartType, class DartListType>
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; typename DartListType::iterator it1, it2, it3, it4;
DartType dart(*it); DartType dart(*it);
@ -1867,7 +1886,7 @@ passes:
it3 = find(elist.begin(), elist.end(), d3); it3 = find(elist.begin(), elist.end(), d3);
it4 = find(elist.begin(), elist.end(), d4); it4 = find(elist.begin(), elist.end(), d4);
TraitsType::swapEdge(dart); triangulation.swapEdge(dart);
// Update the current dart which may have changed // Update the current dart which may have changed
*it = dart; *it = dart;

View File

@ -51,9 +51,6 @@
static ofstream ofile_constr("qweCons.dat"); static ofstream ofile_constr("qweCons.dat");
#endif #endif
//using namespace std;
/** \brief Constrained Delaunay triangulation /** \brief Constrained Delaunay triangulation
* *
* Basic generic algorithms in TTL for inserting a constrained edge between two existing nodes.\n * 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. * See documentation for the namespace ttl for general requirements and assumptions.
* *
* \author * \author
* Øyvind Hjelle, oyvindhj@ifi.uio.no * <EFBFBD>yvind Hjelle, oyvindhj@ifi.uio.no
*/ */
namespace ttl_constr { namespace ttl_constr {
@ -73,6 +70,9 @@ namespace ttl_constr {
#endif #endif
class ConstrainedTriangulation
{
public:
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
/* Checks if \e dart has start and end points in \e dstart and \e dend. /* 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 * A bool confirming that it's the constraint or not
* *
* \using * \using
* ttl::same_0_orbit * same_0_orbit
*/ */
template <class DartType> template <class DartType>
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; DartType d0 = dart;
d0.alpha0(); // CW d0.alpha0(); // CW
if ((ttl::same_0_orbit(dstart, dart) && ttl::same_0_orbit(dend, d0)) || if ((ttl::TriangulationHelper::same_0_orbit(dstart, dart) && ttl::TriangulationHelper::same_0_orbit(dend, d0)) ||
(ttl::same_0_orbit(dstart, d0) && ttl::same_0_orbit(dend, dart))) { (ttl::TriangulationHelper::same_0_orbit(dstart, d0) && ttl::TriangulationHelper::same_0_orbit(dend, dart))) {
return true; return true;
} }
return false; return false;
@ -123,7 +123,7 @@ namespace ttl_constr {
* TraitsType::orient2d * TraitsType::orient2d
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
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_1 = TraitsType::orient2d(dstart,d1,dend);
typename TraitsType::real_type orient_2 = TraitsType::orient2d(dstart,d2,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 * The dart \e d making the smallest positive (or == 0) angle
* *
* \using * \using
* ttl::isBoundaryNode * isBoundaryNode
* ttl::positionAtNextBoundaryEdge * positionAtNextBoundaryEdge
* TraitsType::orient2d * TraitsType::orient2d
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) { static DartType getAtSmallestAngle(const DartType& dstart, const DartType& dend) {
// - Must boundary be convex??? // - Must boundary be convex???
// - Handle the case where the constraint is already present??? // - Handle the case where the constraint is already present???
@ -169,9 +169,9 @@ namespace ttl_constr {
// (dstart and dend may define a boundary edge) // (dstart and dend may define a boundary edge)
DartType d_iter = dstart; DartType d_iter = dstart;
if (ttl::isBoundaryNode(d_iter)) { if (ttl::TriangulationHelper::isBoundaryNode(d_iter)) {
d_iter.alpha1(); // CW 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 // 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. * Returns the next "collinear" starting node such that dend is returned when done.
*/ */
template <class TraitsType, class DartType, class ListType> template <class TraitsType, class DartType, class ListType>
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<TraitsType>(dstart, dend); const DartType my_start = getAtSmallestAngle<TraitsType>(dstart, dend);
DartType my_end = getAtSmallestAngle<TraitsType>(dend, dstart); DartType my_end = getAtSmallestAngle<TraitsType>(dend, dstart);
@ -387,15 +387,16 @@ namespace ttl_constr {
* A list containing all the edges crossing the spesified constraint * A list containing all the edges crossing the spesified constraint
* *
* \using * \using
* ttl::swappableEdge * swappableEdge
* ttl::swapEdgeInList * swapEdgeInList
* ttl::crossesConstraint * crossesConstraint
* ttl::isTheConstraint * isTheConstraint
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
void transformToConstraint(DartType& dstart, DartType& dend, std::list<DartType>& elist) { void transformToConstraint(ttl::TriangulationHelper helper, DartType& dstart, DartType& dend,
std::list<DartType>& elist) const {
typename list<DartType>::iterator it, used; typename std::list<DartType>::iterator it, used;
// We may enter in a situation where dstart and dend are altered because of a swap. // 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, // (The general rule is that darts inside the actual quadrilateral can be changed,
@ -423,7 +424,7 @@ namespace ttl_constr {
if (counter > dartsInList) if (counter > dartsInList)
break; break;
if (ttl::swappableEdge<TraitsType, DartType>(*it, true)) { if (ttl::TriangulationHelper::swappableEdge<TraitsType, DartType>(*it, true)) {
// Dyn & Goren & Rippa 's notation: // Dyn & Goren & Rippa 's notation:
// The node assosiated with dart *it is denoted u_m. u_m has edges crossing the constraint // 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. // 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; end = true;
// This is the only place swapping is called when inserting a constraint // This is the only place swapping is called when inserting a constraint
ttl::swapEdgeInList<TraitsType, DartType>(it,elist); helper.swapEdgeInList<TraitsType, DartType>(it,elist);
// If we, during look-ahead, found that dstart and/or dend were in the quadrilateral, // If we, during look-ahead, found that dstart and/or dend were in the quadrilateral,
// we update them. // we update them.
@ -512,6 +513,8 @@ namespace ttl_constr {
} }
}; // End of ConstrainedTriangulation class
}; // End of ttl_constr namespace scope }; // End of ttl_constr namespace scope
@ -546,14 +549,14 @@ namespace ttl { // (extension)
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&) * - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&)
* *
* \using * \using
* - ttl::optimizeDelaunay if \e optimize_delaunay is set to \c true * - optimizeDelaunay if \e optimize_delaunay is set to \c true
* *
* \par Assumes: * \par Assumes:
* - The constrained edge must be inside the existing triangulation (and it cannot * - The constrained edge must be inside the existing triangulation (and it cannot
* cross the boundary of the triangulation). * cross the boundary of the triangulation).
*/ */
template <class TraitsType, class DartType> template <class TraitsType, class DartType>
DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) { DartType TriangulationHelper::insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay) {
// Assumes: // Assumes:
// - It is the users responsibility to avoid crossing constraints // - It is the users responsibility to avoid crossing constraints
@ -567,8 +570,8 @@ namespace ttl { // (extension)
// calls itself recursively. // calls itself recursively.
// RECURSION // RECURSION
list<DartType> elist; std::list<DartType> elist;
DartType next_start = ttl_constr::findCrossingEdges<TraitsType>(dstart, dend, elist); DartType next_start = ttl_constr::ConstrainedTriangulation::findCrossingEdges<TraitsType>(dstart, dend, elist);
// If there are no crossing edges (elist is empty), we assume that the constraint // If there are no crossing edges (elist is empty), we assume that the constraint
// is an existing edge. // is an existing edge.
@ -583,7 +586,7 @@ namespace ttl { // (extension)
// findCrossingEdges stops if it finds a node lying on the constraint. // findCrossingEdges stops if it finds a node lying on the constraint.
// A dart with this node as start node is returned // A dart with this node as start node is returned
// We call insertConstraint recursivly until the received dart is dend // 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 #ifdef DEBUG_TTL_CONSTR_PLOT
cout << "RECURSION due to collinearity along constraint" << endl; 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. // Swap edges such that the constraint edge is present in the transformed triangulation.
if (elist.size() > 0) // by Thomas Sevaldrud if (elist.size() > 0) // by Thomas Sevaldrud
ttl_constr::transformToConstraint<TraitsType>(dstart, next_start, elist); ttl_constr::ConstrainedTriangulation::transformToConstraint<TraitsType>(dstart, next_start, elist);
#ifdef DEBUG_TTL_CONSTR_PLOT #ifdef DEBUG_TTL_CONSTR_PLOT
cout << "size of elist = " << elist.size() << endl; cout << "size of elist = " << elist.size() << endl;
@ -607,13 +610,13 @@ namespace ttl { // (extension)
#endif #endif
// Optimize to constrained Delaunay triangulation if required. // Optimize to constrained Delaunay triangulation if required.
typename list<DartType>::iterator end_opt = elist.end(); typename std::list<DartType>::iterator end_opt = elist.end();
if (optimize_delaunay) { if (optimize_delaunay) {
// Indicate that the constrained edge, which is the last element in the list, // Indicate that the constrained edge, which is the last element in the list,
// should not be swapped // should not be swapped
--end_opt; --end_opt;
ttl::optimizeDelaunay<TraitsType, DartType>(elist, end_opt); optimizeDelaunay<TraitsType, DartType>(elist, end_opt);
} }
if(elist.size() == 0) // by Thomas Sevaldrud if(elist.size() == 0) // by Thomas Sevaldrud

View File

@ -27,6 +27,10 @@
* @brief Class that computes missing connections on a PCB. * @brief Class that computes missing connections on a PCB.
*/ */
#ifdef USE_OPENMP
#include <omp.h>
#endif /* USE_OPENMP */
#include <ratsnest_data.h> #include <ratsnest_data.h>
#include <class_board.h> #include <class_board.h>
@ -964,13 +968,25 @@ void RN_DATA::Recalculate( int aNet )
{ {
if( aNet < 0 ) // Recompute everything if( aNet < 0 ) // Recompute everything
{ {
// Start with net number 1, as 0 stands for not connected unsigned int tid, i, chunk, netCount;
for( unsigned int i = 1; i < m_nets.size(); ++i ) netCount = m_board->GetNetCount();
chunk = 1;
#ifdef USE_OPENMP
#pragma omp parallel shared(chunk, netCount) private(i, tid)
{ {
// Recompute only nets that require it tid = omp_get_thread_num();
if( m_nets[i].IsDirty() ) #pragma omp for schedule(guided, chunk)
updateNet( i ); #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 else if( aNet > 0 ) // Recompute only specific net
{ {
@ -982,6 +998,7 @@ void RN_DATA::Recalculate( int aNet )
void RN_DATA::updateNet( int aNetCode ) void RN_DATA::updateNet( int aNetCode )
{ {
assert( aNetCode < (int) m_nets.size() ); assert( aNetCode < (int) m_nets.size() );
if( aNetCode < 1 ) if( aNetCode < 1 )
return; return;