Commit a10d918c authored by Maciej Suminski's avatar Maciej Suminski

Thread-safe version of Delaunay triangulation.

parent fe97521b
......@@ -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<TTLtraits>(d_iter, *it);
helper->insertNode<TTLtraits>(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<TTLtraits>(dc);
helper->removeRectangularBoundary<TTLtraits>(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<TTLtraits>(dart)) {
if (helper->swapTestDelaunay<TTLtraits>(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<TTLtraits>(dart, cycling_check)) {
if (!edge->isConstrained() && helper->swapTestDelaunay<TTLtraits>(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();
......
......@@ -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.<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
......
......@@ -51,10 +51,13 @@
#include <vector>
#include <iostream>
#include <fstream>
#include <ttl/ttl.h>
#include <ttl/ttl_util.h>
#include <boost/shared_ptr.hpp>
namespace ttl {
class TriangulationHelper;
};
//--------------------------------------------------------------------------------------------------
// The half-edge data structure
//--------------------------------------------------------------------------------------------------
......@@ -242,26 +245,75 @@ public:
class Triangulation {
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) {
edge->setAsLeadingEdge();
leadingEdges_.push_front( edge );
}
bool removeLeadingEdgeFromList(EdgePtr& leadingEdge);
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:
/// 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<EdgePtr>& getLeadingEdges() const { return leadingEdges_; }
const std::list<EdgePtr>& 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<EdgePtr>* getEdges(bool skip_boundary_edges = false) const;
std::list<EdgePtr>* 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<NodePtr>* getNodes() const;
std::list<NodePtr>* 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
......
......@@ -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,14 +113,14 @@
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
// ----------------------
......@@ -145,55 +143,55 @@ namespace ttl {
// Topological and Geometric Queries
// ---------------------------------
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>
bool locateTriangle(const PointType& point, DartType& dart);
static bool locateTriangle(const PointType& point, DartType& dart);
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>
bool inTriangle(const PointType& point, const DartType& dart);
static bool inTriangle(const PointType& point, const DartType& dart);
template<class DartType, class DartListType>
void getBoundary(const DartType& dart, DartListType& boundary);
static void getBoundary(const DartType& dart, DartListType& boundary);
template<class DartType>
bool isBoundaryEdge(const DartType& dart);
static bool isBoundaryEdge(const DartType& dart);
template<class DartType>
bool isBoundaryFace(const DartType& dart);
static bool isBoundaryFace(const DartType& dart);
template<class DartType>
bool isBoundaryNode(const DartType& dart);
static bool isBoundaryNode(const DartType& dart);
template<class DartType>
int getDegreeOfNode(const DartType& dart);
static int getDegreeOfNode(const DartType& dart);
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>
void get_0_orbit_boundary(const DartType& dart, DartListType& orbit);
static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit);
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>
bool same_1_orbit(const DartType& d1, const DartType& d2);
static bool same_1_orbit(const DartType& d1, const DartType& d2);
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>
bool swappableEdge(const DartType& dart, bool allowDegeneracy = false);
static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false);
template<class DartType>
void positionAtNextBoundaryEdge(DartType& dart);
static void positionAtNextBoundaryEdge(DartType& dart);
template<class TraitsType, class DartType>
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<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>
void recSwapDelaunay(DartType& diagonal);
......@@ -223,9 +221,29 @@ namespace ttl {
// Constrained Triangulation
// -------------------------
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
......@@ -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 <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) {
#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<TraitsType>(d1);
}
//if (!TraitsType::fixedEdge(d2) && !ttl::isBoundaryEdge(d2)) {
if (!ttl::isBoundaryEdge(d2)) {
//if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) {
if (!isBoundaryEdge(d2)) {
d2.alpha2();
recSwapDelaunay<TraitsType>(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<TraitsType>(d3);
}
......@@ -332,7 +350,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
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.
// 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 <class TraitsType, class DartType>
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<TraitsType>(d_iter);
positionAtNextBoundaryEdge(d_next);
removeBoundaryNode<TraitsType>(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 <class TraitsType, class DartType>
void removeNode(DartType& dart) {
void TriangulationHelper::removeNode(DartType& dart) {
if (ttl::isBoundaryNode(dart))
ttl::removeBoundaryNode<TraitsType>(dart);
if (isBoundaryNode(dart))
removeBoundaryNode<TraitsType>(dart);
else
ttl::removeInteriorNode<TraitsType>(dart);
removeInteriorNode<TraitsType>(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 <class TraitsType, class DartType>
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<DartType> swapped_edges;
ttl::swapEdgesAwayFromBoundaryNode<TraitsType>(dart, swapped_edges);
std::list<DartType> swapped_edges;
swapEdgesAwayFromBoundaryNode<TraitsType>(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<DartType>::iterator it;
typename std::list<DartType>::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<DartType> DartListType;
ttl::optimizeDelaunay<TraitsType, DartType, DartListType>(swapped_edges);
typedef std::list<DartType> DartListType;
optimizeDelaunay<TraitsType, DartType, DartListType>(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 <class TraitsType, class DartType>
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<DartType> swapped_edges;
ttl::swapEdgesAwayFromInteriorNode<TraitsType>(dart, swapped_edges);
std::list<DartType> swapped_edges;
swapEdgesAwayFromInteriorNode<TraitsType>(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<TraitsType, DartType>(swapped_edges);
optimizeDelaunay<TraitsType, DartType>(swapped_edges);
}
//@} // End of Delaunay Triangulation Group
......@@ -527,7 +545,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
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
// Assumes:
......@@ -547,7 +565,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
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
// Assumes:
// - TraitsType::orient2d(DartType, DartType, NodeType)
......@@ -594,10 +612,10 @@ namespace ttl {
* \e regular as explained above.
*
* \see
* ttl::locateTriangle
* locateTriangle
*/
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
// 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 <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
// 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 <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
// 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 <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
// ONLY ON ONE EDGE? BUT THIS DOES NOT SOLVE PROBLEMS WITH
......@@ -841,7 +859,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
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;
......@@ -886,7 +904,7 @@ namespace ttl {
* - DartListType::push_back (DartType&)
*/
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)
DartType dart_iter(dart);
......@@ -932,7 +950,7 @@ namespace ttl {
* \endcode
*/
template <class DartType>
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 <class DartType>
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 <class DartType>
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 <class DartType>
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 <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);
......@@ -1131,10 +1150,10 @@ namespace ttl {
* - DartListType::push_back (DartType&)
*
* \see
* ttl::get_0_orbit_boundary
* get_0_orbit_boundary
*/
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;
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 <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 d_iter = dart;
......@@ -1195,17 +1214,17 @@ namespace ttl {
* own version.)
*/
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
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 <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;
// (Also works at the boundary)
......@@ -1245,7 +1264,7 @@ namespace ttl {
* \e d1 and/or \e d2 can be CCW or CW
*/
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;
if (d_iter == d1 || d_iter.alpha0() == d1 ||
......@@ -1259,7 +1278,7 @@ namespace ttl {
//------------------------------------------------------------------------------------------------
// Private/Hidden function
template <class TraitsType, class DartType>
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 <class TraitsType, class DartType>
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 <class DartType>
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 <class TraitsType, class DartType>
bool convexBoundary(const DartType& dart) {
bool TriangulationHelper::convexBoundary(const DartType& dart) {
list<DartType> blist;
ttl::getBoundary(dart, blist);
std::list<DartType> blist;
getBoundary(dart, blist);
int no;
no = (int)blist.size();
typename list<DartType>::const_iterator bit = blist.begin();
typename std::list<DartType>::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 <class TraitsType, class DartType, class DartListType>
void optimizeDelaunay(DartListType& elist) {
void TriangulationHelper::optimizeDelaunay(DartListType& elist) {
optimizeDelaunay<TraitsType, DartType, DartListType>(elist, elist.end());
}
//------------------------------------------------------------------------------------------------
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
// 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<TraitsType>(*it, cycling_check)) {
if (swapTestDelaunay<TraitsType>(*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<TraitsType, DartType>(it, elist);
swapEdgeInList<TraitsType, DartType>(it, elist);
optimal = false;
} // end if should swap
......@@ -1513,9 +1532,9 @@ namespace ttl {
*/
template <class TraitsType, class DartType>
#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 <class TraitsType, class DartType>
void recSwapDelaunay(DartType& diagonal) {
void TriangulationHelper::recSwapDelaunay(DartType& diagonal) {
if (!ttl::swapTestDelaunay<TraitsType>(diagonal))
// ??? ttl::swapTestDelaunay also checks if boundary, so this can be optimized
if (!swapTestDelaunay<TraitsType>(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<TraitsType>(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 <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
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<TraitsType>(d_iter, allowDegeneracy)) {
TraitsType::swapEdge(d_iter); // swap the edge away
if (swappableEdge<TraitsType>(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 <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.
// 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<TraitsType>(d_iter, allowDegeneracy)) {
TraitsType::swapEdge(d_iter);
if (swappableEdge<TraitsType>(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 <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;
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;
......
......@@ -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 <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;
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 <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_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 <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???
// - 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 <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);
DartType my_end = getAtSmallestAngle<TraitsType>(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 <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.
// (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<TraitsType, DartType>(*it, true)) {
if (ttl::TriangulationHelper::swappableEdge<TraitsType, DartType>(*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<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,
// 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 <class TraitsType, class DartType>
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<DartType> elist;
DartType next_start = ttl_constr::findCrossingEdges<TraitsType>(dstart, dend, elist);
std::list<DartType> 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
// 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<TraitsType>(dstart, next_start, elist);
ttl_constr::ConstrainedTriangulation::transformToConstraint<TraitsType>(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<DartType>::iterator end_opt = elist.end();
typename std::list<DartType>::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<TraitsType, DartType>(elist, end_opt);
optimizeDelaunay<TraitsType, DartType>(elist, end_opt);
}
if(elist.size() == 0) // by Thomas Sevaldrud
......
......@@ -240,7 +240,7 @@ void RN_NET::compute()
return;
}
else if( boardNodes.size() == 1 ) // This case is even simpler
else if( boardNodes.size() <= 1 ) // This case is even simpler
{
m_rnEdges.reset( new std::vector<RN_EDGE_PTR>( 0 ) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment