Commit 6fa2f060 authored by Maciej Suminski's avatar Maciej Suminski

Formatted ttl library to comply with KiCad coding policy.

parent a0fb4ed0
...@@ -48,154 +48,154 @@ ...@@ -48,154 +48,154 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
using namespace hed; using namespace hed;
using namespace std;
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
int Node::id_count = 0; int NODE::id_count = 0;
#endif #endif
//#define DEBUG_HE //#define DEBUG_HE
#ifdef DEBUG_HE #ifdef DEBUG_HE
#include <iostream> #include <iostream>
static void errorAndExit(char* message) { static void errorAndExit( char* aMessage )
cout << "\n!!! ERROR: "<< message << " !!!\n" << endl; exit(-1); {
} cout << "\n!!! ERROR: "<< aMessage << " !!!\n" << endl;
exit( -1 );
}
#endif #endif
//-------------------------------------------------------------------------------------------------- static EDGE_PTR getLeadingEdgeInTriangle( const EDGE_PTR& aEdge )
static EdgePtr getLeadingEdgeInTriangle(const EdgePtr& e) { {
EdgePtr edge = e; EDGE_PTR edge = aEdge;
// Code: 3EF (assumes triangle) // Code: 3EF (assumes triangle)
if (!edge->isLeadingEdge()) { if( !edge->IsLeadingEdge() )
edge = edge->getNextEdgeInFace(); {
if (!edge->isLeadingEdge()) edge = edge->GetNextEdgeInFace();
edge = edge->getNextEdgeInFace();
if( !edge->IsLeadingEdge() )
edge = edge->GetNextEdgeInFace();
} }
if (!edge->isLeadingEdge()) { if( !edge->IsLeadingEdge() )
return EdgePtr(); {
return EDGE_PTR();
} }
return edge; return edge;
} }
//-------------------------------------------------------------------------------------------------- static void getLimits( NODES_CONTAINER::iterator aFirst, NODES_CONTAINER::iterator aLast,
static void getLimits(NodesContainer::iterator first, int& aXmin, int& aYmin, int& aXmax, int& aYmax)
NodesContainer::iterator last, {
int& xmin, int& ymin, aXmin = aYmin = std::numeric_limits<int>::min();
int& xmax, int& ymax) { aXmax = aYmax = std::numeric_limits<int>::max();
xmin = ymin = std::numeric_limits<int>::min(); NODES_CONTAINER::iterator it;
xmax = ymax = std::numeric_limits<int>::max();
NodesContainer::iterator it; for( it = aFirst; it != aLast; ++it )
for (it = first; it != last; ++it) { {
xmin = min(xmin, (*it)->GetX()); aXmin = std::min( aXmin, ( *it )->GetX() );
ymin = min(ymin, (*it)->GetY()); aYmin = std::min( aYmin, ( *it )->GetY() );
xmax = max(xmax, (*it)->GetX()); aXmax = std::max( aXmax, ( *it )->GetX() );
ymax = max(ymax, (*it)->GetY()); aYmax = std::max( aYmax, ( *it )->GetY() );
} }
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::InitTwoEnclosingTriangles( NODES_CONTAINER::iterator aFirst,
EdgePtr Triangulation::initTwoEnclosingTriangles(NodesContainer::iterator first, NODES_CONTAINER::iterator aLast)
NodesContainer::iterator last) { {
int xmin, ymin, xmax, ymax; int xmin, ymin, xmax, ymax;
getLimits(first, last, xmin, ymin, xmax, ymax); getLimits( aFirst, aLast, xmin, ymin, xmax, ymax );
// Add 10% of range: // Add 10% of range:
double fac = 10.0; double fac = 10.0;
double dx = (xmax-xmin)/fac; double dx = ( xmax - xmin ) / fac;
double dy = (ymax-ymin)/fac; double dy = ( ymax - ymin ) / fac;
NodePtr n1 = boost::make_shared<Node>(xmin-dx, ymin-dy); NODE_PTR n1 = boost::make_shared<NODE>( xmin - dx, ymin - dy );
NodePtr n2 = boost::make_shared<Node>(xmax+dx, ymin-dy); NODE_PTR n2 = boost::make_shared<NODE>( xmax + dx, ymin - dy );
NodePtr n3 = boost::make_shared<Node>(xmax+dx, ymax+dy); NODE_PTR n3 = boost::make_shared<NODE>( xmax + dx, ymax + dy );
NodePtr n4 = boost::make_shared<Node>(xmin-dx, ymax+dy); NODE_PTR n4 = boost::make_shared<NODE>( xmin - dx, ymax + dy );
// diagonal // diagonal
EdgePtr e1d = boost::make_shared<Edge>(); EDGE_PTR e1d = boost::make_shared<EDGE>();
EdgePtr e2d = boost::make_shared<Edge>(); EDGE_PTR e2d = boost::make_shared<EDGE>();
// lower triangle // lower triangle
EdgePtr e11 = boost::make_shared<Edge>(); EDGE_PTR e11 = boost::make_shared<EDGE>();
EdgePtr e12 = boost::make_shared<Edge>(); EDGE_PTR e12 = boost::make_shared<EDGE>();
// upper triangle // upper triangle
EdgePtr e21 = boost::make_shared<Edge>(); EDGE_PTR e21 = boost::make_shared<EDGE>();
EdgePtr e22 = boost::make_shared<Edge>(); EDGE_PTR e22 = boost::make_shared<EDGE>();
// lower triangle // lower triangle
e1d->setSourceNode(n3); e1d->SetSourceNode( n3 );
e1d->setNextEdgeInFace(e11); e1d->SetNextEdgeInFace( e11 );
e1d->setTwinEdge(e2d); e1d->SetTwinEdge( e2d );
addLeadingEdge(e1d); addLeadingEdge( e1d );
e11->setSourceNode(n1); e11->SetSourceNode( n1 );
e11->setNextEdgeInFace(e12); e11->SetNextEdgeInFace( e12 );
e12->setSourceNode(n2); e12->SetSourceNode( n2 );
e12->setNextEdgeInFace(e1d); e12->SetNextEdgeInFace( e1d );
// upper triangle // upper triangle
e2d->setSourceNode(n1); e2d->SetSourceNode( n1 );
e2d->setNextEdgeInFace(e21); e2d->SetNextEdgeInFace( e21 );
e2d->setTwinEdge(e1d); e2d->SetTwinEdge( e1d );
addLeadingEdge(e2d); addLeadingEdge( e2d );
e21->setSourceNode(n3); e21->SetSourceNode( n3 );
e21->setNextEdgeInFace(e22); e21->SetNextEdgeInFace( e22 );
e22->setSourceNode(n4); e22->SetSourceNode( n4 );
e22->setNextEdgeInFace(e2d); e22->SetNextEdgeInFace( e2d );
return e11; return e11;
} }
//-------------------------------------------------------------------------------------------------- TRIANGULATION::TRIANGULATION()
Triangulation::Triangulation() { {
helper = new ttl::TriangulationHelper( *this ); m_helper = new ttl::TRIANGULATION_HELPER( *this );
} }
//-------------------------------------------------------------------------------------------------- TRIANGULATION::TRIANGULATION( const TRIANGULATION& aTriangulation )
Triangulation::Triangulation(const Triangulation& tr) { {
std::cout << "Triangulation: Copy constructor not present - EXIT."; // Triangulation: Copy constructor not present
exit(-1); assert( false );
} }
//-------------------------------------------------------------------------------------------------- TRIANGULATION::~TRIANGULATION()
Triangulation::~Triangulation() { {
cleanAll(); cleanAll();
delete helper; delete m_helper;
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::CreateDelaunay( NODES_CONTAINER::iterator aFirst,
void Triangulation::createDelaunay(NodesContainer::iterator first, NODES_CONTAINER::iterator aLast )
NodesContainer::iterator last) { {
cleanAll(); cleanAll();
EdgePtr bedge = initTwoEnclosingTriangles(first, last); EDGE_PTR bedge = InitTwoEnclosingTriangles( aFirst, aLast );
Dart dc(bedge); DART dc( bedge );
Dart d_iter = dc; DART d_iter = dc;
NodesContainer::iterator it; NODES_CONTAINER::iterator it;
for (it = first; it != last; ++it) { for( it = aFirst; it != aLast; ++it )
helper->insertNode<TTLtraits>(d_iter, *it); {
m_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
...@@ -206,112 +206,107 @@ void Triangulation::createDelaunay(NodesContainer::iterator first, ...@@ -206,112 +206,107 @@ void Triangulation::createDelaunay(NodesContainer::iterator first,
// triangle "outside" the triangulation.) // triangle "outside" the triangulation.)
// Assumes rectangular domain // Assumes rectangular domain
helper->removeRectangularBoundary<TTLtraits>(dc); m_helper->RemoveRectangularBoundary<TTLtraits>( dc );
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::RemoveTriangle( EDGE_PTR& aEdge )
void Triangulation::removeTriangle(EdgePtr& edge) { {
EDGE_PTR e1 = getLeadingEdgeInTriangle( aEdge );
EdgePtr e1 = getLeadingEdgeInTriangle(edge);
#ifdef DEBUG_HE #ifdef DEBUG_HE
if (!e1) if( !e1 )
errorAndExit("Triangulation::removeTriangle: could not find leading edge"); errorAndExit( "Triangulation::removeTriangle: could not find leading aEdge" );
#endif #endif
removeLeadingEdgeFromList(e1); removeLeadingEdgeFromList( e1 );
// cout << "No leading edges = " << leadingEdges_.size() << endl; // cout << "No leading edges = " << leadingEdges_.size() << endl;
// Remove the triangle // Remove the triangle
EdgePtr e2(e1->getNextEdgeInFace()); EDGE_PTR e2( e1->GetNextEdgeInFace() );
EdgePtr e3(e2->getNextEdgeInFace()); EDGE_PTR e3( e2->GetNextEdgeInFace() );
e1->clear(); e1->Clear();
e2->clear(); e2->Clear();
e3->clear(); e3->Clear();
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::ReverseSplitTriangle( EDGE_PTR& aEdge )
void Triangulation::reverse_splitTriangle(EdgePtr& edge) { {
// Reverse operation of splitTriangle // Reverse operation of splitTriangle
EDGE_PTR e1( aEdge->GetNextEdgeInFace() );
EdgePtr e1(edge->getNextEdgeInFace()); EDGE_PTR le( getLeadingEdgeInTriangle( e1 ) );
EdgePtr le(getLeadingEdgeInTriangle(e1));
#ifdef DEBUG_HE #ifdef DEBUG_HE
if (!le) if (!le)
errorAndExit("Triangulation::removeTriangle: could not find leading edge"); errorAndExit("Triangulation::removeTriangle: could not find leading edge");
#endif #endif
removeLeadingEdgeFromList(le); removeLeadingEdgeFromList( le );
EdgePtr e2(e1->getNextEdgeInFace()->getTwinEdge()->getNextEdgeInFace()); EDGE_PTR e2( e1->GetNextEdgeInFace()->GetTwinEdge()->GetNextEdgeInFace() );
le = getLeadingEdgeInTriangle(e2); le = getLeadingEdgeInTriangle( e2 );
#ifdef DEBUG_HE #ifdef DEBUG_HE
if (!le) if (!le)
errorAndExit("Triangulation::removeTriangle: could not find leading edge"); errorAndExit("Triangulation::removeTriangle: could not find leading edge");
#endif #endif
removeLeadingEdgeFromList(le); removeLeadingEdgeFromList( le );
EdgePtr e3(edge->getTwinEdge()->getNextEdgeInFace()->getNextEdgeInFace()); EDGE_PTR e3( aEdge->GetTwinEdge()->GetNextEdgeInFace()->GetNextEdgeInFace() );
le = getLeadingEdgeInTriangle(e3); le = getLeadingEdgeInTriangle( e3 );
#ifdef DEBUG_HE #ifdef DEBUG_HE
if (!le) if (!le)
errorAndExit("Triangulation::removeTriangle: could not find leading edge"); errorAndExit("Triangulation::removeTriangle: could not find leading edge");
#endif #endif
removeLeadingEdgeFromList(le); removeLeadingEdgeFromList( le );
// The three triangles at the node have now been removed // The three triangles at the node have now been removed
// from the triangulation, but the arcs have not been deleted. // from the triangulation, but the arcs have not been deleted.
// Next delete the 6 half edges radiating from the node // Next delete the 6 half edges radiating from the node
// The node is maintained by handle and need not be deleted explicitly // The node is maintained by handle and need not be deleted explicitly
EdgePtr estar = edge; EDGE_PTR estar = aEdge;
EdgePtr enext = estar->getTwinEdge()->getNextEdgeInFace(); EDGE_PTR enext = estar->GetTwinEdge()->GetNextEdgeInFace();
estar->getTwinEdge()->clear(); estar->GetTwinEdge()->Clear();
estar->clear(); estar->Clear();
estar = enext; estar = enext;
enext = estar->getTwinEdge()->getNextEdgeInFace(); enext = estar->GetTwinEdge()->GetNextEdgeInFace();
estar->getTwinEdge()->clear(); estar->GetTwinEdge()->Clear();
estar->clear(); estar->Clear();
enext->getTwinEdge()->clear();
enext->clear();
enext->GetTwinEdge()->Clear();
enext->Clear();
// Create the new triangle // Create the new triangle
e1->setNextEdgeInFace(e2); e1->SetNextEdgeInFace( e2 );
e2->setNextEdgeInFace(e3); e2->SetNextEdgeInFace( e3 );
e3->setNextEdgeInFace(e1); e3->SetNextEdgeInFace( e1 );
addLeadingEdge(e1); addLeadingEdge( e1 );
} }
//-------------------------------------------------------------------------------------------------- DART TRIANGULATION::CreateDart()
Dart Triangulation::createDart() { {
// Return an arbitrary CCW dart // Return an arbitrary CCW dart
return Dart(*leadingEdges_.begin()); return DART( *m_leadingEdges.begin() );
} }
//-------------------------------------------------------------------------------------------------- bool TRIANGULATION::removeLeadingEdgeFromList( EDGE_PTR& aLeadingEdge )
bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) { {
// Remove the edge from the list of leading edges, // Remove the edge from the list of leading edges,
// but don't delete it. // but don't delete it.
// Also set flag for leading edge to false. // Also set flag for leading edge to false.
// Must search from start of list. Since edges are added to the // Must search from start of list. Since edges are added to the
// start of the list during triangulation, this operation will // start of the list during triangulation, this operation will
// normally be fast (when used in the triangulation algorithm) // normally be fast (when used in the triangulation algorithm)
list<EdgePtr>::iterator it; std::list<EDGE_PTR>::iterator it;
for (it = leadingEdges_.begin(); it != leadingEdges_.end(); ++it) { for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
{
EdgePtr edge = *it; EDGE_PTR edge = *it;
if (edge == leadingEdge) {
edge->setAsLeadingEdge(false); if( edge == aLeadingEdge )
it = leadingEdges_.erase(it); {
edge->SetAsLeadingEdge( false );
it = m_leadingEdges.erase( it );
return true; return true;
} }
...@@ -321,73 +316,75 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) { ...@@ -321,73 +316,75 @@ bool Triangulation::removeLeadingEdgeFromList(EdgePtr& leadingEdge) {
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::cleanAll()
void Triangulation::cleanAll() { {
BOOST_FOREACH(EdgePtr& edge, leadingEdges_) BOOST_FOREACH( EDGE_PTR& edge, m_leadingEdges )
edge->setNextEdgeInFace(EdgePtr()); edge->SetNextEdgeInFace( EDGE_PTR() );
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::swapEdge( DART& aDart )
void Triangulation::swapEdge(Dart& dart) { {
swapEdge(dart.getEdge()); SwapEdge( aDart.GetEdge() );
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::splitTriangle( DART& aDart, const NODE_PTR& aPoint )
void Triangulation::splitTriangle(Dart& dart, const NodePtr& point) { {
EdgePtr edge = splitTriangle(dart.getEdge(), point); EDGE_PTR edge = SplitTriangle( aDart.GetEdge(), aPoint );
dart.init(edge); aDart.Init( edge );
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::reverseSplitTriangle( DART& aDart )
void Triangulation::reverse_splitTriangle(Dart& dart) { {
reverse_splitTriangle(dart.getEdge()); ReverseSplitTriangle( aDart.GetEdge() );
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::removeBoundaryTriangle( DART& aDart )
void Triangulation::removeBoundaryTriangle(Dart& d) { {
removeTriangle(d.getEdge()); RemoveTriangle( aDart.GetEdge() );
} }
#ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::FlagNodes( bool aFlag ) const
// This is a "template" for accessing all nodes (but multiple tests) {
void Triangulation::flagNodes(bool flag) const { std::list<EDGE_PTR>::const_iterator it;
for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
list<EdgePtr>::const_iterator it; {
for (it = leadingEdges_.begin(); it != leadingEdges_.end(); ++it) { EDGE_PTR edge = *it;
EdgePtr edge = *it;
for( int i = 0; i < 3; ++i )
for (int i = 0; i < 3; ++i) { {
edge->getSourceNode()->SetFlag(flag); edge->GetSourceNode()->SetFlag( aFlag );
edge = edge->getNextEdgeInFace(); edge = edge->GetNextEdgeInFace();
} }
} }
} }
//-------------------------------------------------------------------------------------------------- std::list<NODE_PTR>* TRIANGULATION::GetNodes() const
list<NodePtr>* Triangulation::getNodes() const { {
FlagNodes( false );
flagNodes(false); std::list<NODE_PTR>* nodeList = new std::list<NODE_PTR>;
list<NodePtr>* nodeList = new list<NodePtr>; std::list<EDGE_PTR>::const_iterator it;
list<EdgePtr>::const_iterator it; for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
for (it = leadingEdges_.begin(); it != leadingEdges_.end(); ++it) { {
EdgePtr edge = *it; EDGE_PTR edge = *it;
for (int i = 0; i < 3; ++i) { for( int i = 0; i < 3; ++i )
const NodePtr& node = edge->getSourceNode(); {
const NODE_PTR& node = edge->GetSourceNode();
if (node->GetFlag() == false) { if( node->GetFlag() == false )
nodeList->push_back(node); {
node->SetFlag(true); nodeList->push_back( node );
node->SetFlag( true );
} }
edge = edge->getNextEdgeInFace(); edge = edge->GetNextEdgeInFace();
} }
} }
return nodeList; return nodeList;
...@@ -395,42 +392,38 @@ list<NodePtr>* Triangulation::getNodes() const { ...@@ -395,42 +392,38 @@ list<NodePtr>* Triangulation::getNodes() const {
#endif #endif
//-------------------------------------------------------------------------------------------------- std::list<EDGE_PTR>* TRIANGULATION::GetEdges( bool aSkipBoundaryEdges ) const
list<EdgePtr>* Triangulation::getEdges(bool skip_boundary_edges) const { {
// collect all arcs (one half edge for each arc) // collect all arcs (one half edge for each arc)
// (boundary edges are also collected). // (boundary edges are also collected).
std::list<EDGE_PTR>::const_iterator it;
list<EdgePtr>::const_iterator it; std::list<EDGE_PTR>* elist = new std::list<EDGE_PTR>;
list<EdgePtr>* elist = new list<EdgePtr>;
for (it = leadingEdges_.begin(); it != leadingEdges_.end(); ++it) { for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
EdgePtr edge = *it; {
for (int i = 0; i < 3; ++i) { EDGE_PTR edge = *it;
EdgePtr twinedge = edge->getTwinEdge(); for( int i = 0; i < 3; ++i )
{
EDGE_PTR twinedge = edge->GetTwinEdge();
// only one of the half-edges // only one of the half-edges
if ( (!twinedge && !skip_boundary_edges) || if( ( !twinedge && !aSkipBoundaryEdges )
(twinedge && ((size_t)edge.get() > (size_t)twinedge.get())) ) || ( twinedge && ( (size_t) edge.get() > (size_t) twinedge.get() ) ) )
elist->push_front(edge); elist->push_front( edge );
edge = edge->getNextEdgeInFace(); edge = edge->GetNextEdgeInFace();
} }
} }
return elist; return elist;
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::SplitTriangle( EDGE_PTR& aEdge, const NODE_PTR& aPoint )
EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) { {
// Add a node by just splitting a triangle into three triangles // Add a node by just splitting a triangle into three triangles
// Assumes the half edge is located in the triangle // Assumes the half aEdge is located in the triangle
// Returns a half edge with source node as the new node // Returns a half aEdge with source node as the new node
// double x, y, z;
// x = point.x();
// y = point.y();
// z = point.z();
// e#_n are new edges // e#_n are new edges
// e# are existing edges // e# are existing edges
...@@ -438,158 +431,149 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) { ...@@ -438,158 +431,149 @@ EdgePtr Triangulation::splitTriangle(EdgePtr& edge, const NodePtr& point) {
// e##_n are edges incident to the new node // e##_n are edges incident to the new node
// Add the node to the structure // Add the node to the structure
//NodePtr new_node(new Node(x,y,z)); //NODE_PTR new_node(new Node(x,y,z));
NodePtr n1(edge->getSourceNode()); NODE_PTR n1( aEdge->GetSourceNode() );
EdgePtr e1(edge); EDGE_PTR e1( aEdge );
EdgePtr e2(edge->getNextEdgeInFace()); EDGE_PTR e2( aEdge->GetNextEdgeInFace() );
NodePtr n2(e2->getSourceNode()); NODE_PTR n2( e2->GetSourceNode() );
EdgePtr e3(e2->getNextEdgeInFace()); EDGE_PTR e3( e2->GetNextEdgeInFace() );
NodePtr n3(e3->getSourceNode()); NODE_PTR n3( e3->GetSourceNode() );
EdgePtr e1_n = boost::make_shared<Edge>(); EDGE_PTR e1_n = boost::make_shared<EDGE>();
EdgePtr e11_n = boost::make_shared<Edge>(); EDGE_PTR e11_n = boost::make_shared<EDGE>();
EdgePtr e2_n = boost::make_shared<Edge>(); EDGE_PTR e2_n = boost::make_shared<EDGE>();
EdgePtr e22_n = boost::make_shared<Edge>(); EDGE_PTR e22_n = boost::make_shared<EDGE>();
EdgePtr e3_n = boost::make_shared<Edge>(); EDGE_PTR e3_n = boost::make_shared<EDGE>();
EdgePtr e33_n = boost::make_shared<Edge>(); EDGE_PTR e33_n = boost::make_shared<EDGE>();
e1_n->setSourceNode(n1); e1_n->SetSourceNode( n1 );
e11_n->setSourceNode(point); e11_n->SetSourceNode( aPoint );
e2_n->setSourceNode(n2); e2_n->SetSourceNode( n2 );
e22_n->setSourceNode(point); e22_n->SetSourceNode( aPoint );
e3_n->setSourceNode(n3); e3_n->SetSourceNode( n3 );
e33_n->setSourceNode(point); e33_n->SetSourceNode( aPoint );
e1_n->setTwinEdge(e11_n); e1_n->SetTwinEdge( e11_n );
e11_n->setTwinEdge(e1_n); e11_n->SetTwinEdge( e1_n );
e2_n->setTwinEdge(e22_n); e2_n->SetTwinEdge( e22_n );
e22_n->setTwinEdge(e2_n); e22_n->SetTwinEdge( e2_n );
e3_n->setTwinEdge(e33_n); e3_n->SetTwinEdge( e33_n );
e33_n->setTwinEdge(e3_n); e33_n->SetTwinEdge( e3_n );
e1_n->setNextEdgeInFace(e33_n); e1_n->SetNextEdgeInFace( e33_n );
e2_n->setNextEdgeInFace(e11_n); e2_n->SetNextEdgeInFace( e11_n );
e3_n->setNextEdgeInFace(e22_n); e3_n->SetNextEdgeInFace( e22_n );
e11_n->setNextEdgeInFace(e1); e11_n->SetNextEdgeInFace( e1 );
e22_n->setNextEdgeInFace(e2); e22_n->SetNextEdgeInFace( e2 );
e33_n->setNextEdgeInFace(e3); e33_n->SetNextEdgeInFace( e3 );
// and update old's next edge // and update old's next aEdge
e1->setNextEdgeInFace(e2_n); e1->SetNextEdgeInFace( e2_n );
e2->setNextEdgeInFace(e3_n); e2->SetNextEdgeInFace( e3_n );
e3->setNextEdgeInFace(e1_n); e3->SetNextEdgeInFace( e1_n );
// add the three new leading edges, // add the three new leading edges,
// Must remove the old leading edge from the list. // Must remove the old leading aEdge from the list.
// Use the field telling if an edge is a leading edge // Use the field telling if an aEdge is a leading aEdge
// NOTE: Must search in the list!!! // NOTE: Must search in the list!!!
if (e1->isLeadingEdge()) if( e1->IsLeadingEdge() )
removeLeadingEdgeFromList(e1); removeLeadingEdgeFromList( e1 );
else if (e2->isLeadingEdge()) else if( e2->IsLeadingEdge() )
removeLeadingEdgeFromList(e2); removeLeadingEdgeFromList( e2 );
else if(e3->isLeadingEdge()) else if( e3->IsLeadingEdge() )
removeLeadingEdgeFromList(e3); removeLeadingEdgeFromList( e3 );
else else
assert( false ); // one of the edges should be leading assert( false ); // one of the edges should be leading
addLeadingEdge(e1_n); addLeadingEdge( e1_n );
addLeadingEdge(e2_n); addLeadingEdge( e2_n );
addLeadingEdge(e3_n); addLeadingEdge( e3_n );
// Return a half edge incident to the new node (with the new node as source node) // Return a half aEdge incident to the new node (with the new node as source node)
return e11_n; return e11_n;
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::SwapEdge( EDGE_PTR& aDiagonal )
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
// functions in TriangulationHelper 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
EdgePtr eL(diagonal); EDGE_PTR eL( aDiagonal );
EdgePtr eR(eL->getTwinEdge()); EDGE_PTR eR( eL->GetTwinEdge() );
EdgePtr eL_1(eL->getNextEdgeInFace()); EDGE_PTR eL_1( eL->GetNextEdgeInFace() );
EdgePtr eL_2(eL_1->getNextEdgeInFace()); EDGE_PTR eL_2( eL_1->GetNextEdgeInFace() );
EdgePtr eR_1(eR->getNextEdgeInFace()); EDGE_PTR eR_1( eR->GetNextEdgeInFace() );
EdgePtr eR_2(eR_1->getNextEdgeInFace()); EDGE_PTR eR_2( eR_1->GetNextEdgeInFace() );
// avoid node to be dereferenced to zero and deleted // avoid node to be dereferenced to zero and deleted
NodePtr nR(eR_2->getSourceNode()); NODE_PTR nR( eR_2->GetSourceNode() );
NodePtr nL(eL_2->getSourceNode()); NODE_PTR nL( eL_2->GetSourceNode() );
eL->setSourceNode(nR); eL->SetSourceNode( nR );
eR->setSourceNode(nL); eR->SetSourceNode( nL );
// and now 6 1-sewings // and now 6 1-sewings
eL->setNextEdgeInFace(eL_2); eL->SetNextEdgeInFace( eL_2 );
eL_2->setNextEdgeInFace(eR_1); eL_2->SetNextEdgeInFace( eR_1 );
eR_1->setNextEdgeInFace(eL); eR_1->SetNextEdgeInFace( eL );
eR->setNextEdgeInFace(eR_2); eR->SetNextEdgeInFace( eR_2 );
eR_2->setNextEdgeInFace(eL_1); eR_2->SetNextEdgeInFace( eL_1 );
eL_1->setNextEdgeInFace(eR); eL_1->SetNextEdgeInFace( eR );
if (eL->isLeadingEdge()) if( eL->IsLeadingEdge() )
removeLeadingEdgeFromList(eL); removeLeadingEdgeFromList( eL );
else if (eL_1->isLeadingEdge()) else if( eL_1->IsLeadingEdge() )
removeLeadingEdgeFromList(eL_1); removeLeadingEdgeFromList( eL_1 );
else if (eL_2->isLeadingEdge()) else if( eL_2->IsLeadingEdge() )
removeLeadingEdgeFromList(eL_2); removeLeadingEdgeFromList( eL_2 );
if (eR->isLeadingEdge()) if( eR->IsLeadingEdge() )
removeLeadingEdgeFromList(eR); removeLeadingEdgeFromList( eR );
else if (eR_1->isLeadingEdge()) else if( eR_1->IsLeadingEdge() )
removeLeadingEdgeFromList(eR_1); removeLeadingEdgeFromList( eR_1 );
else if (eR_2->isLeadingEdge()) else if( eR_2->IsLeadingEdge() )
removeLeadingEdgeFromList(eR_2); removeLeadingEdgeFromList( eR_2 );
addLeadingEdge(eL); addLeadingEdge( eL );
addLeadingEdge(eR); addLeadingEdge( eR );
} }
////-------------------------------------------------------------------------- bool TRIANGULATION::CheckDelaunay() const
//static void printEdge(const Dart& dart, ostream& ofile) { {
//
// Dart d0 = dart;
// d0.alpha0();
//
// ofile << dart.x() << " " << dart.y() << endl;
// ofile << d0.x() << " " << d0.y() << endl;
//}
//--------------------------------------------------------------------------
bool Triangulation::checkDelaunay() const {
// ???? outputs !!!! // ???? outputs !!!!
// ofstream os("qweND.dat"); // ofstream os("qweND.dat");
const list<EdgePtr>& leadingEdges = getLeadingEdges(); const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
list<EdgePtr>::const_iterator it; std::list<EDGE_PTR>::const_iterator it;
bool ok = true; bool ok = true;
int noNotDelaunay = 0; int noNotDelaunay = 0;
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) { for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
EdgePtr edge = *it; {
EDGE_PTR edge = *it;
for (int i = 0; i < 3; ++i) { for( int i = 0; i < 3; ++i )
EdgePtr twinedge = edge->getTwinEdge(); {
EDGE_PTR twinedge = edge->GetTwinEdge();
// 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); {
if (helper->swapTestDelaunay<TTLtraits>(dart)) { DART dart( edge );
if( m_helper->SwapTestDelaunay<TTLtraits>( dart ) )
{
noNotDelaunay++; noNotDelaunay++;
//printEdge(dart,os); os << "\n"; //printEdge(dart,os); os << "\n";
...@@ -597,7 +581,8 @@ bool Triangulation::checkDelaunay() const { ...@@ -597,7 +581,8 @@ bool Triangulation::checkDelaunay() const {
//cout << "............. not Delaunay .... " << endl; //cout << "............. not Delaunay .... " << endl;
} }
} }
edge = edge->getNextEdgeInFace();
edge = edge->GetNextEdgeInFace();
} }
} }
...@@ -609,9 +594,8 @@ bool Triangulation::checkDelaunay() const { ...@@ -609,9 +594,8 @@ bool Triangulation::checkDelaunay() const {
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::OptimizeDelaunay()
void Triangulation::optimizeDelaunay() { {
// This function is also present in ttl where it is implemented // This function is also present in ttl where it is implemented
// generically. // generically.
// The implementation below is tailored for the half-edge data structure, // The implementation below is tailored for the half-edge data structure,
...@@ -619,114 +603,126 @@ void Triangulation::optimizeDelaunay() { ...@@ -619,114 +603,126 @@ void Triangulation::optimizeDelaunay() {
// Collect all interior edges (one half edge for each arc) // Collect all interior edges (one half edge for each arc)
bool skip_boundary_edges = true; bool skip_boundary_edges = true;
list<EdgePtr>* elist = getEdges(skip_boundary_edges); std::list<EDGE_PTR>* elist = GetEdges( skip_boundary_edges );
// Assumes that elist has only one half-edge for each arc. // Assumes that elist has only one half-edge for each arc.
bool cycling_check = true; bool cycling_check = true;
bool optimal = false; bool optimal = false;
list<EdgePtr>::const_iterator it; std::list<EDGE_PTR>::const_iterator it;
while(!optimal) {
while( !optimal )
{
optimal = true; optimal = true;
for (it = elist->begin(); it != elist->end(); ++it) {
EdgePtr edge = *it;
Dart dart(edge); for( it = elist->begin(); it != elist->end(); ++it )
{
EDGE_PTR edge = *it;
DART dart( edge );
// Constrained edges should not be swapped // Constrained edges should not be swapped
if (helper->swapTestDelaunay<TTLtraits>(dart, cycling_check)) { if( m_helper->SwapTestDelaunay<TTLtraits>( dart, cycling_check ) )
{
optimal = false; optimal = false;
swapEdge(edge); SwapEdge( edge );
} }
} }
} }
delete elist; delete elist;
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::GetInteriorNode() const
EdgePtr Triangulation::getInteriorNode() const { {
const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
std::list<EDGE_PTR>::const_iterator it;
const list<EdgePtr>& leadingEdges = getLeadingEdges(); for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
list<EdgePtr>::const_iterator it; {
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) { EDGE_PTR edge = *it;
EdgePtr edge = *it;
// multiple checks, but only until found // multiple checks, but only until found
for (int i = 0; i < 3; ++i) { for( int i = 0; i < 3; ++i )
if (edge->getTwinEdge()) { {
if( edge->GetTwinEdge() )
if (!helper->isBoundaryNode(Dart(edge))) {
if( !m_helper->IsBoundaryNode( DART( edge ) ) )
return edge; return edge;
} }
edge = edge->getNextEdgeInFace();
edge = edge->GetNextEdgeInFace();
} }
} }
return EdgePtr(); // no boundary nodes
return EDGE_PTR(); // no boundary nodes
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::GetBoundaryEdgeInTriangle( const EDGE_PTR& aEdge ) const
EdgePtr Triangulation::getBoundaryEdgeInTriangle(const EdgePtr& e) const { {
EdgePtr edge = e; EDGE_PTR edge = aEdge;
if (helper->isBoundaryEdge(Dart(edge))) if( m_helper->IsBoundaryEdge( DART( edge ) ) )
return edge; return edge;
edge = edge->getNextEdgeInFace(); edge = edge->GetNextEdgeInFace();
if (helper->isBoundaryEdge(Dart(edge))) if( m_helper->IsBoundaryEdge( DART( edge ) ) )
return edge; return edge;
edge = edge->getNextEdgeInFace(); edge = edge->GetNextEdgeInFace();
if (helper->isBoundaryEdge(Dart(edge))) if( m_helper->IsBoundaryEdge( DART( edge ) ) )
return edge; return edge;
return EdgePtr(); return EDGE_PTR();
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::GetBoundaryEdge() const
EdgePtr Triangulation::getBoundaryEdge() const { {
// Get an arbitrary (CCW) boundary edge // Get an arbitrary (CCW) boundary edge
// If the triangulation is closed, NULL is returned // If the triangulation is closed, NULL is returned
const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
std::list<EDGE_PTR>::const_iterator it;
EDGE_PTR edge;
const list<EdgePtr>& leadingEdges = getLeadingEdges(); for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
list<EdgePtr>::const_iterator it; {
EdgePtr edge; edge = GetBoundaryEdgeInTriangle( *it );
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) {
edge = getBoundaryEdgeInTriangle(*it);
if (edge) if( edge )
return edge; return edge;
} }
return EdgePtr(); return EDGE_PTR();
} }
//-------------------------------------------------------------------------------------------------- void TRIANGULATION::PrintEdges( std::ofstream& aOutput ) const
void Triangulation::printEdges(ofstream& os) const { {
// Print source node and target node for each edge face by face, // Print source node and target node for each edge face by face,
// but only one of the half-edges. // but only one of the half-edges.
const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
std::list<EDGE_PTR>::const_iterator it;
const list<EdgePtr>& leadingEdges = getLeadingEdges(); for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
list<EdgePtr>::const_iterator it; {
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) { EDGE_PTR edge = *it;
EdgePtr edge = *it;
for (int i = 0; i < 3; ++i) { for( int i = 0; i < 3; ++i )
EdgePtr twinedge = edge->getTwinEdge(); {
EDGE_PTR twinedge = edge->GetTwinEdge();
// Print only one edge (the highest value of the pointer) // Print only one edge (the highest value of the pointer)
if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { if( !twinedge || (size_t) edge.get() > (size_t) twinedge.get() )
{
// Print source node and target node // Print source node and target node
NodePtr node = edge->getSourceNode(); NODE_PTR node = edge->GetSourceNode();
os << node->GetX() << " " << node->GetY() << endl; aOutput << node->GetX() << " " << node->GetY() << std::endl;
node = edge->getTargetNode(); node = edge->GetTargetNode();
os << node->GetX() << " " << node->GetY() << endl; aOutput << node->GetX() << " " << node->GetY() << std::endl;
os << '\n'; // blank line aOutput << '\n'; // blank line
} }
edge = edge->getNextEdgeInFace();
edge = edge->GetNextEdgeInFace();
} }
} }
} }
...@@ -40,111 +40,152 @@ ...@@ -40,111 +40,152 @@
#ifndef _HALF_EDGE_DART_ #ifndef _HALF_EDGE_DART_
#define _HALF_EDGE_DART_ #define _HALF_EDGE_DART_
#include <ttl/halfedge/hetriang.h> #include <ttl/halfedge/hetriang.h>
namespace hed
namespace hed { {
/**
* \class Dart
//------------------------------------------------------------------------------------------------
// Dart class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Dart
* \brief \b %Dart class for the half-edge data structure. * \brief \b %Dart class for the half-edge data structure.
* *
* See \ref api for a detailed description of how the member functions * See \ref api for a detailed description of how the member functions
* should be implemented. * should be implemented.
*/ */
class DART
{
EDGE_PTR m_edge;
class Dart { /// Dart direction: true if dart is counterclockwise in face
bool m_dir;
EdgePtr edge_;
bool dir_; // true if dart is counterclockwise in face
public: public:
/// Default constructor /// Default constructor
Dart() { dir_ = true; } DART()
{
m_dir = true;
}
/// Constructor /// Constructor
Dart(const EdgePtr& edge, bool dir = true) { edge_ = edge; dir_ = dir; } DART( const EDGE_PTR& aEdge, bool aDir = true )
{
m_edge = aEdge;
m_dir = aDir;
}
/// Copy constructor /// Copy constructor
Dart(const Dart& dart) { edge_ = dart.edge_; dir_ = dart.dir_; } DART( const DART& aDart )
{
m_edge = aDart.m_edge;
m_dir = aDart.m_dir;
}
/// Destructor /// Destructor
~Dart() {} ~DART()
{
}
/// Assignment operator /// Assignment operator
Dart& operator = (const Dart& dart) { DART& operator=( const DART& aDart )
if (this == &dart) {
if( this == &aDart )
return *this; return *this;
edge_ = dart.edge_;
dir_ = dart.dir_; m_edge = aDart.m_edge;
m_dir = aDart.m_dir;
return *this; return *this;
} }
/// Comparing dart objects /// Comparing dart objects
bool operator==(const Dart& dart) const { bool operator==( const DART& aDart ) const
if (dart.edge_ == edge_ && dart.dir_ == dir_) {
return true; return ( aDart.m_edge == m_edge && aDart.m_dir == m_dir );
return false;
} }
/// Comparing dart objects /// Comparing dart objects
bool operator!=(const Dart& dart) const { bool operator!=( const DART& aDart ) const
return !(dart==*this); {
return !( aDart == *this );
} }
/// Maps the dart to a different node /// Maps the dart to a different node
Dart& alpha0() { dir_ = !dir_; return *this; } DART& Alpha0()
{
m_dir = !m_dir;
return *this;
}
/// Maps the dart to a different edge /// Maps the dart to a different edge
Dart& alpha1() { DART& Alpha1()
if (dir_) { {
edge_ = edge_->getNextEdgeInFace()->getNextEdgeInFace(); if( m_dir )
dir_ = false; {
m_edge = m_edge->GetNextEdgeInFace()->GetNextEdgeInFace();
m_dir = false;
} }
else { else
edge_ = edge_->getNextEdgeInFace(); {
dir_ = true; m_edge = m_edge->GetNextEdgeInFace();
m_dir = true;
} }
return *this; return *this;
} }
/// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary! /// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary!
Dart& alpha2() { DART& Alpha2()
if (edge_->getTwinEdge()) { {
edge_ = edge_->getTwinEdge(); if( m_edge->GetTwinEdge() )
dir_ = !dir_; {
m_edge = m_edge->GetTwinEdge();
m_dir = !m_dir;
} }
// else, the dart is at the boundary and should not be changed // else, the dart is at the boundary and should not be changed
return *this; return *this;
} }
// Utilities not required by TTL
// -----------------------------
/** @name Utilities not required by TTL */ /** @name Utilities not required by TTL */
//@{ //@{
void Init( const EDGE_PTR& aEdge, bool aDir = true )
{
m_edge = aEdge;
m_dir = aDir;
}
double X() const
{
return GetNode()->GetX();
}
void init(const EdgePtr& edge, bool dir = true) { edge_ = edge; dir_ = dir; } double Y() const
{
return GetNode()->GetY();
}
double x() const { return getNode()->GetX(); } // x-coordinate of source node bool IsCCW() const
double y() const { return getNode()->GetY(); } // y-coordinate of source node {
return m_dir;
}
bool isCounterClockWise() const { return dir_; } const NODE_PTR& GetNode() const
{
return m_dir ? m_edge->GetSourceNode() : m_edge->GetTargetNode();
}
const NodePtr& getNode() const { return dir_ ? edge_->getSourceNode() : edge_->getTargetNode(); } const NODE_PTR& GetOppositeNode() const
const NodePtr& getOppositeNode() const { return dir_ ? edge_->getTargetNode() : edge_->getSourceNode(); } {
EdgePtr& getEdge() { return edge_; } return m_dir ? m_edge->GetTargetNode() : m_edge->GetSourceNode();
}
//@} // End of Utilities not required by TTL EDGE_PTR& GetEdge()
{
return m_edge;
}
}; //@} // End of Utilities not required by TTL
};
}; // End of hed namespace } // End of hed namespace
#endif #endif
...@@ -40,19 +40,13 @@ ...@@ -40,19 +40,13 @@
#ifndef _HALF_EDGE_TRAITS_ #ifndef _HALF_EDGE_TRAITS_
#define _HALF_EDGE_TRAITS_ #define _HALF_EDGE_TRAITS_
#include <ttl/halfedge/hetriang.h> #include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hedart.h> #include <ttl/halfedge/hedart.h>
namespace hed
namespace hed { {
/**
* \struct TTLtraits
//------------------------------------------------------------------------------------------------
// Traits class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure. * \brief \b Traits class (static struct) for the half-edge data structure.
* *
* The member functions are those required by different function templates * The member functions are those required by different function templates
...@@ -64,112 +58,131 @@ namespace hed { ...@@ -64,112 +58,131 @@ namespace hed {
* half-edge data structure. * half-edge data structure.
* *
* \see \ref api * \see \ref api
*
*/ */
struct TTLtraits
struct TTLtraits { {
/**
/** 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.
*/ */
typedef double real_type; typedef double REAL_TYPE;
//----------------------------------------------------------------------------------------------
// ------------------------------- Geometric Predicates Group ---------------------------------
//----------------------------------------------------------------------------------------------
/** @name Geometric Predicates */ /** @name Geometric Predicates */
//@{ //@{
/**
//---------------------------------------------------------------------------------------------- * Scalar product between two 2D vectors represented as darts.\n
/** Scalar product between two 2D vectors represented as darts.\n
* *
* ttl_util::scalarProduct2d can be used. * ttl_util::scalarProduct2d can be used.
*/ */
static real_type scalarProduct2d(const Dart& v1, const Dart& v2) { static REAL_TYPE ScalarProduct2D( const DART& aV1, const DART& aV2 )
Dart v10 = v1; v10.alpha0(); {
Dart v20 = v2; v20.alpha0(); DART v10 = aV1;
return ttl_util::scalarProduct2d(v10.x()-v1.x(), v10.y()-v1.y(), v10.Alpha0();
v20.x()-v2.x(), v20.y()-v2.y());
}
DART v20 = aV2;
v20.Alpha0();
//---------------------------------------------------------------------------------------------- return ttl_util::ScalarProduct2D( v10.X() - aV1.X(), v10.Y() - aV1.Y(),
/** Scalar product between two 2D vectors. v20.X() - aV2.X(), v20.Y() - aV2.Y() );
}
/**
* Scalar product between two 2D vectors.
* The first vector is represented by a dart \e v, and the second * The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.\n * vector has direction from the source node of \e v to the point \e p.\n
* *
* ttl_util::scalarProduct2d can be used. * ttl_util::ScalarProduct2D can be used.
*/ */
static real_type scalarProduct2d(const Dart& v, const NodePtr& p) { static REAL_TYPE ScalarProduct2D( const DART& aV, const NODE_PTR& aP )
Dart d0 = v; d0.alpha0(); {
return ttl_util::scalarProduct2d(d0.x() - v.x(), d0.y() - v.y(), DART d0 = aV;
p->GetX() - v.x(), p->GetY() - v.y()); d0.Alpha0();
}
return ttl_util::ScalarProduct2D( d0.X() - aV.X(), d0.Y() - aV.Y(),
aP->GetX() - aV.X(), aP->GetY() - aV.Y() );
}
//---------------------------------------------------------------------------------------------- /**
/** Cross product between two vectors in the plane represented as darts. * Cross product between two vectors in the plane represented as darts.
* The z-component of the cross product is returned.\n * The z-component of the cross product is returned.\n
* *
* ttl_util::crossProduct2d can be used. * ttl_util::CrossProduct2D can be used.
*/ */
static real_type crossProduct2d(const Dart& v1, const Dart& v2) { static REAL_TYPE CrossProduct2D( const DART& aV1, const DART& aV2 )
Dart v10 = v1; v10.alpha0(); {
Dart v20 = v2; v20.alpha0(); DART v10 = aV1;
return ttl_util::crossProduct2d(v10.x()-v1.x(), v10.y()-v1.y(), v10.Alpha0();
v20.x()-v2.x(), v20.y()-v2.y());
}
DART v20 = aV2;
v20.Alpha0();
//---------------------------------------------------------------------------------------------- return ttl_util::CrossProduct2D( v10.X() - aV1.X(), v10.Y() - aV1.Y(),
/** Cross product between two vectors in the plane. v20.X() - aV2.X(), v20.Y() - aV2.Y() );
}
/**
* Cross product between two vectors in the plane.
* The first vector is represented by a dart \e v, and the second * The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p. * vector has direction from the source node of \e v to the point \e p.
* The z-component of the cross product is returned.\n * The z-component of the cross product is returned.\n
* *
* ttl_util::crossProduct2d can be used. * ttl_util::CrossProduct2d can be used.
*/ */
static real_type crossProduct2d(const Dart& v, const NodePtr& p) { static REAL_TYPE CrossProduct2D( const DART& aV, const NODE_PTR& aP )
Dart d0 = v; d0.alpha0(); {
return ttl_util::crossProduct2d(d0.x() - v.x(), d0.y() - v.y(), DART d0 = aV;
p->GetX() - v.x(), p->GetY() - v.y()); d0.Alpha0();
}
return ttl_util::CrossProduct2D( d0.X() - aV.X(), d0.Y() - aV.Y(),
aP->GetX() - aV.X(), aP->GetY() - aV.Y() );
}
//---------------------------------------------------------------------------------------------- /**
/** Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p * Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p
* be a point in the plane. Return a positive value if \e n1, \e n2, * be a point in the plane. Return a positive value if \e n1, \e n2,
* and \e p occur in counterclockwise order; a negative value if they occur * and \e p occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear. * in clockwise order; and zero if they are collinear.
*/ */
static real_type orient2d(const Dart& n1, const Dart& n2, const NodePtr& p) { static REAL_TYPE Orient2D( const DART& aN1, const DART& aN2, const NODE_PTR& aP )
real_type pa[2]; real_type pb[2]; real_type pc[2]; {
pa[0] = n1.x(); pa[1] = n1.y(); REAL_TYPE pa[2];
pb[0] = n2.x(); pb[1] = n2.y(); REAL_TYPE pb[2];
pc[0] = p->GetX(); pc[1] = p->GetY(); REAL_TYPE pc[2];
return ttl_util::orient2dfast(pa, pb, pc);
pa[0] = aN1.X();
pa[1] = aN1.Y();
pb[0] = aN2.X();
pb[1] = aN2.Y();
pc[0] = aP->GetX();
pc[1] = aP->GetY();
return ttl_util::Orient2DFast( pa, pb, pc );
} }
/**
//---------------------------------------------------------------------------------------------- * This is the same predicate as represented with the function above,
/** This is the same predicate as represented with the function above,
* but with a slighty different interface: * but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart * The last parameter is given as a dart where the source node of the dart
* represents a point in the plane. * represents a point in the plane.
* This function is required for constrained triangulation. * This function is required for constrained triangulation.
*/ */
static real_type orient2d(const Dart& n1, const Dart& n2, const Dart& p) { static REAL_TYPE Orient2D( const DART& aN1, const DART& aN2, const DART& aP )
real_type pa[2]; real_type pb[2]; real_type pc[2]; {
pa[0] = n1.x(); pa[1] = n1.y(); REAL_TYPE pa[2];
pb[0] = n2.x(); pb[1] = n2.y(); REAL_TYPE pb[2];
pc[0] = p.x(); pc[1] = p.y(); REAL_TYPE pc[2];
return ttl_util::orient2dfast(pa, pb, pc);
pa[0] = aN1.X();
pa[1] = aN1.Y();
pb[0] = aN2.X();
pb[1] = aN2.Y();
pc[0] = aP.X();
pc[1] = aP.Y();
return ttl_util::Orient2DFast( pa, pb, pc );
} }
//@} // End of Geometric Predicates Group //@} // End of Geometric Predicates Group
}; };
}; // End of hed namespace }; // End of hed namespace
......
...@@ -42,11 +42,9 @@ ...@@ -42,11 +42,9 @@
#ifndef _HE_TRIANG_H_ #ifndef _HE_TRIANG_H_
#define _HE_TRIANG_H_ #define _HE_TRIANG_H_
#define TTL_USE_NODE_ID // Each node gets it's own unique id #define TTL_USE_NODE_ID // Each node gets it's own unique id
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false) #define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
#include <list> #include <list>
#include <vector> #include <vector>
#include <iostream> #include <iostream>
...@@ -55,28 +53,26 @@ ...@@ -55,28 +53,26 @@
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
namespace ttl { namespace ttl
class TriangulationHelper; {
class TRIANGULATION_HELPER;
}; };
//-------------------------------------------------------------------------------------------------- /**
// The half-edge data structure * The half-edge data structure
//-------------------------------------------------------------------------------------------------- */
namespace hed
namespace hed { {
// Helper typedefs // Helper typedefs
class Node; class NODE;
class Edge; class EDGE;
typedef boost::shared_ptr<Node> NodePtr; typedef boost::shared_ptr<NODE> NODE_PTR;
typedef boost::shared_ptr<Edge> EdgePtr; typedef boost::shared_ptr<EDGE> EDGE_PTR;
typedef boost::weak_ptr<Edge> EdgeWeakPtr; typedef boost::weak_ptr<EDGE> EDGE_WEAK_PTR;
typedef std::vector<NodePtr> NodesContainer; typedef std::vector<NODE_PTR> NODES_CONTAINER;
//------------------------------------------------------------------------------------------------ /**
// Node class for data structures * \class NODE
//------------------------------------------------------------------------------------------------
/** \class Node
* \brief \b Node class for data structures (Inherits from HandleId) * \brief \b Node class for data structures (Inherits from HandleId)
* *
* \note * \note
...@@ -85,13 +81,12 @@ namespace hed { ...@@ -85,13 +81,12 @@ namespace hed {
* - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is * - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is
* required by the application, because they increase the memory usage for each Node object. * required by the application, because they increase the memory usage for each Node object.
*/ */
class NODE
class Node { {
protected: protected:
#ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG
/// TTL_USE_NODE_FLAG must be defined /// TTL_USE_NODE_FLAG must be defined
bool flag_; bool m_flag;
#endif #endif
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
...@@ -99,173 +94,245 @@ protected: ...@@ -99,173 +94,245 @@ protected:
static int id_count; static int id_count;
/// A unique id for each node (TTL_USE_NODE_ID must be defined) /// A unique id for each node (TTL_USE_NODE_ID must be defined)
int id_; int m_id;
#endif #endif
int x_, y_; /// Node coordinates
int m_x, m_y;
unsigned int refCount_; /// Reference count
unsigned int m_refCount;
public: public:
/// Constructor /// Constructor
Node( int x = 0, int y = 0 ) : NODE( int aX = 0, int aY = 0 ) :
#ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG
flag_( false ), m_flag( false ),
#endif #endif
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
id_( id_count++ ), m_id( id_count++ ),
#endif #endif
x_( x ), y_( y ), refCount_( 0 ) {} m_x( aX ), m_y( aY ), m_refCount( 0 )
{
}
/// Destructor /// Destructor
~Node() {} ~NODE() {}
/// Returns the x-coordinate /// Returns the x-coordinate
int GetX() const { return x_; } int GetX() const
{
return m_x;
}
/// Returns the y-coordinate /// Returns the y-coordinate
int GetY() const { return y_; } int GetY() const
{
return m_y;
}
#ifdef TTL_USE_NODE_ID #ifdef TTL_USE_NODE_ID
/// Returns the id (TTL_USE_NODE_ID must be defined) /// Returns the id (TTL_USE_NODE_ID must be defined)
int Id() const { return id_; } int Id() const
{
return m_id;
}
#endif #endif
#ifdef TTL_USE_NODE_FLAG #ifdef TTL_USE_NODE_FLAG
/// Sets the flag (TTL_USE_NODE_FLAG must be defined) /// Sets the flag (TTL_USE_NODE_FLAG must be defined)
void SetFlag(bool aFlag) { flag_ = aFlag; } void SetFlag( bool aFlag )
{
m_flag = aFlag;
}
/// Returns the flag (TTL_USE_NODE_FLAG must be defined) /// Returns the flag (TTL_USE_NODE_FLAG must be defined)
const bool& GetFlag() const { return flag_; } const bool& GetFlag() const
{
return m_flag;
}
#endif #endif
void IncRefCount() { refCount_++; } void IncRefCount()
void DecRefCount() { refCount_--; } {
unsigned int GetRefCount() const { return refCount_; } m_refCount++;
}; // End of class Node }
void DecRefCount()
{
m_refCount--;
}
unsigned int GetRefCount() const
{
return m_refCount;
}
};
//------------------------------------------------------------------------------------------------
// Edge class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Edge /**
* \class EDGE
* \brief \b %Edge class in the in the half-edge data structure. * \brief \b %Edge class in the in the half-edge data structure.
*/ */
class EDGE
class Edge { {
public: public:
/// Constructor /// Constructor
Edge() : weight_(0), isLeadingEdge_(false) {} EDGE() : m_weight( 0 ), m_isLeadingEdge( false )
{
}
/// Destructor /// Destructor
virtual ~Edge() {} virtual ~EDGE()
{
}
/// Sets the source node /// Sets the source node
void setSourceNode(const NodePtr& node) { sourceNode_ = node; } void SetSourceNode( const NODE_PTR& aNode )
{
m_sourceNode = aNode;
}
/// Sets the next edge in face /// Sets the next edge in face
void setNextEdgeInFace(const EdgePtr& edge) { nextEdgeInFace_ = edge; } void SetNextEdgeInFace( const EDGE_PTR& aEdge )
{
m_nextEdgeInFace = aEdge;
}
/// Sets the twin edge /// Sets the twin edge
void setTwinEdge(const EdgePtr& edge) { twinEdge_ = edge; } void SetTwinEdge( const EDGE_PTR& aEdge )
{
m_twinEdge = aEdge;
}
/// Sets the edge as a leading edge /// Sets the edge as a leading edge
void setAsLeadingEdge(bool val=true) { isLeadingEdge_ = val; } void SetAsLeadingEdge( bool aLeading = true )
{
m_isLeadingEdge = aLeading;
}
/// Checks if an edge is a leading edge /// Checks if an edge is a leading edge
bool isLeadingEdge() const { return isLeadingEdge_; } bool IsLeadingEdge() const
{
return m_isLeadingEdge;
}
/// Returns the twin edge /// Returns the twin edge
EdgePtr getTwinEdge() const { return twinEdge_.lock(); }; EDGE_PTR GetTwinEdge() const
{
return m_twinEdge.lock();
}
void clearTwinEdge() { twinEdge_.reset(); } void ClearTwinEdge()
{
m_twinEdge.reset();
}
/// Returns the next edge in face /// Returns the next edge in face
const EdgePtr& getNextEdgeInFace() const { return nextEdgeInFace_; } const EDGE_PTR& GetNextEdgeInFace() const
{
return m_nextEdgeInFace;
}
/// Retuns the source node /// Retuns the source node
const NodePtr& getSourceNode() const { return sourceNode_; } const NODE_PTR& GetSourceNode() const
{
return m_sourceNode;
}
/// Returns the target node /// Returns the target node
virtual const NodePtr& getTargetNode() const { return nextEdgeInFace_->getSourceNode(); } virtual const NODE_PTR& GetTargetNode() const
{
return m_nextEdgeInFace->GetSourceNode();
}
void setWeight( unsigned int weight ) { weight_ = weight; } void SetWeight( unsigned int weight )
{
m_weight = weight;
}
unsigned int getWeight() const { return weight_; } unsigned int GetWeight() const
{
return m_weight;
}
void clear() void Clear()
{ {
sourceNode_.reset(); m_sourceNode.reset();
nextEdgeInFace_.reset(); m_nextEdgeInFace.reset();
if( !twinEdge_.expired() ) if( !m_twinEdge.expired() )
{ {
twinEdge_.lock()->clearTwinEdge(); m_twinEdge.lock()->ClearTwinEdge();
twinEdge_.reset(); m_twinEdge.reset();
} }
} }
protected: protected:
NodePtr sourceNode_; NODE_PTR m_sourceNode;
EdgeWeakPtr twinEdge_; EDGE_WEAK_PTR m_twinEdge;
EdgePtr nextEdgeInFace_; EDGE_PTR m_nextEdgeInFace;
unsigned int weight_; unsigned int m_weight;
bool isLeadingEdge_; bool m_isLeadingEdge;
}; // End of class Edge };
/** \class EdgeMST /**
* \brief \b Specialization of %Edge class to be used for Minimum Spanning Tree algorithm. * \class EDGE_MST
* \brief \b Specialization of %EDGE class to be used for Minimum Spanning Tree algorithm.
*/ */
class EdgeMST : public Edge class EDGE_MST : public EDGE
{ {
private: private:
NodePtr target_; NODE_PTR m_target;
public: public:
EdgeMST( const NodePtr& source, const NodePtr& target, unsigned int weight = 0 ) : EDGE_MST( const NODE_PTR& aSource, const NODE_PTR& aTarget, unsigned int aWeight = 0 ) :
target_(target) m_target( aTarget )
{ sourceNode_ = source; weight_ = weight; } {
m_sourceNode = aSource;
m_weight = aWeight;
}
EdgeMST( const Edge& edge ) EDGE_MST( const EDGE& edge )
{ {
sourceNode_ = edge.getSourceNode(); m_sourceNode = edge.GetSourceNode();
target_ = edge.getTargetNode(); m_target = edge.GetTargetNode();
weight_ = edge.getWeight(); m_weight = edge.GetWeight();
} }
~EdgeMST() {}; ~EDGE_MST()
{
}
/// @copydoc Edge::setSourceNode() /// @copydoc Edge::setSourceNode()
virtual const NodePtr& getTargetNode() const { return target_; } virtual const NODE_PTR& GetTargetNode() const
}; {
return m_target;
}
//------------------------------------------------------------------------------------------------ };
class Dart; // Forward declaration (class in this namespace)
//------------------------------------------------------------------------------------------------ class DART; // Forward declaration (class in this namespace)
// Triangulation class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Triangulation /**
* \class TRIANGULATION
* \brief \b %Triangulation class for the half-edge data structure with adaption to TTL. * \brief \b %Triangulation class for the half-edge data structure with adaption to TTL.
*/ */
class TRIANGULATION
{
protected:
/// One half-edge for each arc
std::list<EDGE_PTR> m_leadingEdges;
class Triangulation { ttl::TRIANGULATION_HELPER* m_helper;
protected:
std::list<EdgePtr> leadingEdges_; // one half-edge for each arc
ttl::TriangulationHelper* helper;
void addLeadingEdge(EdgePtr& edge) { void addLeadingEdge( EDGE_PTR& aEdge )
edge->setAsLeadingEdge(); {
leadingEdges_.push_front( edge ); aEdge->SetAsLeadingEdge();
m_leadingEdges.push_front( aEdge );
} }
bool removeLeadingEdgeFromList(EdgePtr& leadingEdge); bool removeLeadingEdgeFromList( EDGE_PTR& aLeadingEdge );
void cleanAll(); void cleanAll();
...@@ -275,7 +342,7 @@ public: ...@@ -275,7 +342,7 @@ public:
* \image html swapEdge.gif * \image html swapEdge.gif
* </center> * </center>
* *
* \param dart * \param aDart
* Some of the functions require a dart as output. * Some of the functions require a dart as output.
* If this is required by the actual function, the dart should be delivered * 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) * back in a position as seen if it was glued to the edge when swapping (rotating)
...@@ -287,115 +354,118 @@ public: ...@@ -287,115 +354,118 @@ public:
* - Some functions in TTL require that \c swapEdge is implemented such that * - Some functions in TTL require that \c swapEdge is implemented such that
* darts outside the quadrilateral are not affected by the swap. * darts outside the quadrilateral are not affected by the swap.
*/ */
void swapEdge(Dart& dart); void swapEdge( DART& aDart );
/** Splits the triangle associated with \e dart in the actual data structure into /**
* Splits the triangle associated with \e dart in the actual data structure into
* three new triangles joining at \e point. * three new triangles joining at \e point.
* *
* <center> * <center>
* \image html splitTriangle.gif * \image html splitTriangle.gif
* </center> * </center>
* *
* \param dart * \param aDart
* Output: A CCW dart incident with the new node; see the figure. * Output: A CCW dart incident with the new node; see the figure.
*/ */
void splitTriangle(Dart& dart, const NodePtr& point); void splitTriangle( DART& aDart, const NODE_PTR& aPoint );
/** The reverse operation of TTLtraits::splitTriangle. /**
* The reverse operation of TTLtraits::splitTriangle.
* This function is only required for functions that involve * This function is only required for functions that involve
* removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode. * removal of interior nodes; see for example TrinagulationHelper::RemoveInteriorNode.
* *
* <center> * <center>
* \image html reverse_splitTriangle.gif * \image html reverse_splitTriangle.gif
* </center> * </center>
*/ */
void reverse_splitTriangle(Dart& dart); void reverseSplitTriangle( DART& aDart );
/** Removes a triangle with an edge at the boundary of the triangulation /**
* Removes a triangle with an edge at the boundary of the triangulation
* in the actual data structure * in the actual data structure
*/ */
void removeBoundaryTriangle(Dart& d); void removeBoundaryTriangle( DART& aDart );
public: public:
/// Default constructor /// Default constructor
Triangulation(); TRIANGULATION();
/// Copy constructor /// Copy constructor
Triangulation(const Triangulation& tr); TRIANGULATION( const TRIANGULATION& aTriangulation );
/// Destructor /// Destructor
~Triangulation(); ~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( NODES_CONTAINER::iterator aFirst, NODES_CONTAINER::iterator aLast );
NodesContainer::iterator last);
/// Creates an initial Delaunay triangulation from two enclosing triangles /// Creates an initial Delaunay triangulation from two enclosing triangles
// When using rectangular boundary - loop through all points and expand. // When using rectangular boundary - loop through all points and expand.
// (Called from createDelaunay(...) when starting) // (Called from createDelaunay(...) when starting)
EdgePtr initTwoEnclosingTriangles(NodesContainer::iterator first, EDGE_PTR InitTwoEnclosingTriangles( NODES_CONTAINER::iterator aFirst,
NodesContainer::iterator last); NODES_CONTAINER::iterator aLast );
// These two functions are required by TTL for Delaunay triangulation // These two functions are required by TTL for Delaunay triangulation
/// Swaps the edge associated with diagonal /// Swaps the edge associated with diagonal
void swapEdge(EdgePtr& diagonal); void SwapEdge( EDGE_PTR& aDiagonal );
/// Splits the triangle associated with edge into three new triangles joining at point /// Splits the triangle associated with edge into three new triangles joining at point
EdgePtr splitTriangle(EdgePtr& edge, const NodePtr& point); EDGE_PTR SplitTriangle( EDGE_PTR& aEdge, const NODE_PTR& aPoint );
// Functions required by TTL for removing nodes in a Delaunay triangulation // Functions required by TTL for removing nodes in a Delaunay triangulation
/// Removes the boundary triangle associated with edge /// Removes the boundary triangle associated with edge
void removeTriangle(EdgePtr& edge); // boundary triangle required void RemoveTriangle( EDGE_PTR& aEdge ); // boundary triangle required
/// The reverse operation of removeTriangle /// The reverse operation of removeTriangle
void reverse_splitTriangle(EdgePtr& edge); void ReverseSplitTriangle( EDGE_PTR& aEdge );
/// Creates an arbitrary CCW dart /// Creates an arbitrary CCW dart
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 std::list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; } const std::list<EDGE_PTR>& GetLeadingEdges() const
{
return m_leadingEdges;
}
/// Returns the number of triangles /// Returns the number of triangles
int noTriangles() const { return (int)leadingEdges_.size(); } int NoTriangles() const
{
return (int) m_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)
std::list<EdgePtr>* getEdges(bool skip_boundary_edges = false) const; std::list<EDGE_PTR>* GetEdges( bool aSkipBoundaryEdges = 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 aFlag ) 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.
std::list<NodePtr>* getNodes() const; std::list<NODE_PTR>* 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)
void optimizeDelaunay(); void OptimizeDelaunay();
/// Checks if the triangulation is Delaunay /// Checks if the triangulation is Delaunay
bool checkDelaunay() const; bool CheckDelaunay() const;
/// 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; EDGE_PTR GetInteriorNode() const;
EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) const; EDGE_PTR GetBoundaryEdgeInTriangle( const EDGE_PTR& aEdge ) const;
/// Returns an arbitrary boundary edge /// Returns an arbitrary boundary edge
EdgePtr getBoundaryEdge() const; EDGE_PTR 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& aOutput ) const;
friend class ttl::TriangulationHelper;
}; // End of class Triangulation
friend class ttl::TRIANGULATION_HELPER;
};
}; // End of hed namespace }; // End of hed namespace
#endif #endif
...@@ -40,19 +40,18 @@ ...@@ -40,19 +40,18 @@
#ifndef _TTL_H_ #ifndef _TTL_H_
#define _TTL_H_ #define _TTL_H_
#include <list> #include <list>
#include <iterator> #include <iterator>
// Debugging // Debugging
#ifdef DEBUG_TTL #ifdef DEBUG_TTL
static void errorAndExit(char* message) { static void errorAndExit( char* aMessage )
cout << "\n!!! ERROR: " << message << " !!!\n" << endl; {
cout << "\n!!! ERROR: " << aMessage << " !!!\n" << endl;
exit(-1); exit(-1);
} }
#endif #endif
// Next on TOPOLOGY: // Next on TOPOLOGY:
// - get triangle strips // - get triangle strips
// - weighted graph, algorithms using a weight (real) for each edge, // - weighted graph, algorithms using a weight (real) for each edge,
...@@ -63,8 +62,8 @@ ...@@ -63,8 +62,8 @@
// - analyze in detail locateFace: e.g. detect 0-orbit in case of infinite loop // - analyze in detail locateFace: e.g. detect 0-orbit in case of infinite loop
// around a node etc. // around a node etc.
/**
/** \brief Main interface to TTL * \brief Main interface to TTL
* *
* This namespace contains the basic generic algorithms for the TTL, * This namespace contains the basic generic algorithms for the TTL,
* the Triangulation Template Library.\n * the Triangulation Template Library.\n
...@@ -77,21 +76,21 @@ ...@@ -77,21 +76,21 @@
* - Misc. queries for extracting information for visualisation systems etc. * - Misc. queries for extracting information for visualisation systems etc.
* *
* \par General requirements and assumptions: * \par General requirements and assumptions:
* - \e DartType and \e TraitsType should be implemented in accordance with the description * - \e DART_TYPE and \e TRAITS_TYPE should be implemented in accordance with the description
* in \ref api. * in \ref api.
* - A \b "Requires:" section in the documentation of a function template * - A \b "Requires:" section in the documentation of a function template
* shows which functionality is required in \e TraitsType to * shows which functionality is required in \e TRAITS_TYPE to
* support that specific function.\n * support that specific function.\n
* Functionalty required in \e DartType is the same (almost) for all * Functionalty required in \e DART_TYPE is the same (almost) for all
* function templates; see \ref api and the example referred to. * function templates; see \ref api and the example referred to.
* - When a reference to a \e dart object is passed to a function in TTL, * - When a reference to a \e dart object is passed to a function in TTL,
* it is assumed that it is oriented \e counterclockwise (CCW) in a triangle * it is assumed that it is oriented \e counterclockwise (CCW) in a triangle
* unless it is explicitly mentioned that it can also be \e clockwise (CW). * unless it is explicitly mentioned that it can also be \e clockwise (CW).
* The same applies for a dart that is passed from a function in TTL to * The same applies for a dart that is passed from a function in TTL to
* the users TraitsType class (or struct). * the users TRAITS_TYPE class (or struct).
* - When an edge (represented with a dart) is swapped, it is assumed that darts * - When an edge (represented with a dart) is swapped, it is assumed that darts
* outside the quadrilateral where the edge is a diagonal are not affected by * outside the quadrilateral where the edge is a diagonal are not affected by
* the swap. Thus, \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" * the swap. Thus, \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge"
* must be implemented in accordance with this rule. * must be implemented in accordance with this rule.
* *
* \par Glossary: * \par Glossary:
...@@ -111,152 +110,146 @@ ...@@ -111,152 +110,146 @@
*/ */
namespace ttl { namespace ttl
{
class TriangulationHelper class TRIANGULATION_HELPER
{ {
#ifndef DOXYGEN_SHOULD_SKIP_THIS #ifndef DOXYGEN_SHOULD_SKIP_THIS
public: public:
TriangulationHelper(hed::Triangulation& triang) : triangulation(triang) TRIANGULATION_HELPER( hed::TRIANGULATION& aTriang ) :
m_triangulation( aTriang )
{ {
} }
// Delaunay Triangulation // Delaunay Triangulation
// ---------------------- template <class TRAITS_TYPE, class DART_TYPE, class POINT_TYPE>
template<class TraitsType, class DartType, class PointType> bool InsertNode( DART_TYPE& aDart, POINT_TYPE& aPoint );
bool insertNode(DartType& dart, PointType& point);
template<class TraitsType, class DartType>
void removeRectangularBoundary(DartType& dart);
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void removeNode(DartType& dart); void RemoveRectangularBoundary( DART_TYPE& aDart );
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void removeBoundaryNode(DartType& dart); void RemoveNode( DART_TYPE& aDart );
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void removeInteriorNode(DartType& dart); void RemoveBoundaryNode( DART_TYPE& aDart );
template <class TRAITS_TYPE, class DART_TYPE>
void RemoveInteriorNode( DART_TYPE& aDart );
// Topological and Geometric Queries // Topological and Geometric Queries
// --------------------------------- // ---------------------------------
template<class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
static bool locateFaceSimplest(const PointType& point, DartType& dart); static bool LocateFaceSimplest( const POINT_TYPE& aPoint, DART_TYPE& aDart );
template<class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
static bool locateTriangle(const PointType& point, DartType& dart); static bool LocateTriangle( const POINT_TYPE& aPoint, DART_TYPE& aDart );
template<class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
static bool inTriangleSimplest(const PointType& point, const DartType& dart); static bool InTriangleSimplest( const POINT_TYPE& aPoint, const DART_TYPE& aDart );
template<class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
static bool inTriangle(const PointType& point, const DartType& dart); static bool InTriangle( const POINT_TYPE& aPoint, const DART_TYPE& aDart );
template<class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
static void getBoundary(const DartType& dart, DartListType& boundary); static void GetBoundary( const DART_TYPE& aDart, DART_LIST_TYPE& aBoundary );
template<class DartType> template <class DART_TYPE>
static bool isBoundaryEdge(const DartType& dart); static bool IsBoundaryEdge( const DART_TYPE& aDart );
template<class DartType> template <class DART_TYPE>
static bool isBoundaryFace(const DartType& dart); static bool IsBoundaryFace( const DART_TYPE& aDart );
template<class DartType> template <class DART_TYPE>
static bool isBoundaryNode(const DartType& dart); static bool IsBoundaryNode( const DART_TYPE& aDart );
template<class DartType> template <class DART_TYPE>
static int getDegreeOfNode(const DartType& dart); static int GetDegreeOfNode( const DART_TYPE& aDart );
template<class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
static void get_0_orbit_interior(const DartType& dart, DartListType& orbit); static void Get0OrbitInterior( const DART_TYPE& aDart, DART_LIST_TYPE& aOrbit );
template<class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
static void get_0_orbit_boundary(const DartType& dart, DartListType& orbit); static void Get0OrbitBoundary( const DART_TYPE& aDart, DART_LIST_TYPE& aOrbit );
template<class DartType> template <class DART_TYPE>
static bool same_0_orbit(const DartType& d1, const DartType& d2); static bool Same0Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 );
template<class DartType> template <class DART_TYPE>
static bool same_1_orbit(const DartType& d1, const DartType& d2); static bool Same1Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 );
template<class DartType> template <class DART_TYPE>
static bool same_2_orbit(const DartType& d1, const DartType& d2); static bool Same2Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 );
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
static bool swappableEdge(const DartType& dart, bool allowDegeneracy = false); static bool SwappableEdge( const DART_TYPE& aDart, bool aAllowDegeneracy = false );
template<class DartType> template <class DART_TYPE>
static void positionAtNextBoundaryEdge(DartType& dart); static void PositionAtNextBoundaryEdge( DART_TYPE& aDart );
template<class TraitsType, class DartType>
static bool convexBoundary(const DartType& dart);
template <class TRAITS_TYPE, class DART_TYPE>
static bool ConvexBoundary( const DART_TYPE& aDart );
// Utilities for Delaunay Triangulation // Utilities for Delaunay Triangulation
// ------------------------------------ // ------------------------------------
template<class TraitsType, class DartType, class DartListType> template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
void optimizeDelaunay(DartListType& elist); void OptimizeDelaunay( DART_LIST_TYPE& aElist );
template <class TraitsType, class DartType, class DartListType>
void optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end);
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
bool swapTestDelaunay(const DartType& dart, bool cycling_check = false) const; void OptimizeDelaunay( DART_LIST_TYPE& aElist, const typename DART_LIST_TYPE::iterator aEnd );
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void recSwapDelaunay(DartType& diagonal); bool SwapTestDelaunay( const DART_TYPE& aDart, bool aCyclingCheck = false ) const;
template<class TraitsType, class DartType, class ListType> template <class TRAITS_TYPE, class DART_TYPE>
void swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges); void RecSwapDelaunay( DART_TYPE& aDiagonal );
template<class TraitsType, class DartType, class ListType> template <class TRAITS_TYPE, class DART_TYPE, class LIST_TYPE>
void swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges); void SwapEdgesAwayFromInteriorNode( DART_TYPE& aDart, LIST_TYPE& aSwappedEdges );
template<class TraitsType, class DartType, class DartListType> template <class TRAITS_TYPE, class DART_TYPE, class LIST_TYPE>
void swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist); void SwapEdgesAwayFromBoundaryNode( DART_TYPE& aDart, LIST_TYPE& aSwappedEdges );
template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
void SwapEdgeInList( const typename DART_LIST_TYPE::iterator& aIt, DART_LIST_TYPE& aElist );
// Constrained Triangulation // Constrained Triangulation
// ------------------------- // -------------------------
template<class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
static DartType insertConstraint(DartType& dstart, DartType& dend, bool optimize_delaunay); static DART_TYPE InsertConstraint( DART_TYPE& aDStart, DART_TYPE& aDEnd, bool aOptimizeDelaunay );
private: private:
hed::Triangulation& triangulation; hed::TRIANGULATION& m_triangulation;
template <class TraitsType, class ForwardIterator, class DartType> template <class TRAITS_TYPE, class FORWARD_ITERATOR, class DART_TYPE>
void insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart); void insertNodes( FORWARD_ITERATOR aFirst, FORWARD_ITERATOR aLast, DART_TYPE& aDart );
template <class TopologyElementType, class DartType> template <class TOPOLOGY_ELEMENT_TYPE, class DART_TYPE>
static bool isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart); static bool isMemberOfFace( const TOPOLOGY_ELEMENT_TYPE& aTopologyElement, const DART_TYPE& aDart );
template <class TraitsType, class NodeType, class DartType> template <class TRAITS_TYPE, class NODE_TYPE, class DART_TYPE>
static bool locateFaceWithNode(const NodeType& node, DartType& dart_iter); static bool locateFaceWithNode( const NODE_TYPE& aNode, DART_TYPE& aDartIter );
template <class DartType> template <class DART_TYPE>
static void getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3); static void getAdjacentTriangles( const DART_TYPE& aDart, DART_TYPE& aT1, DART_TYPE& aT2,
DART_TYPE& aT3 );
template <class DartType> template <class DART_TYPE>
static void getNeighborNodes(const DartType& dart, std::list<DartType>& node_list, bool& boundary); static void getNeighborNodes( const DART_TYPE& aDart, std::list<DART_TYPE>& aNodeList,
bool& aBoundary );
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
static bool degenerateTriangle(const DartType& dart); static bool degenerateTriangle( const DART_TYPE& aDart );
}; };
#endif // DOXYGEN_SHOULD_SKIP_THIS #endif // DOXYGEN_SHOULD_SKIP_THIS
//------------------------------------------------------------------------------------------------
// ------------------------------- Delaunay Triangulation Group ---------------------------------
//------------------------------------------------------------------------------------------------
/** @name Delaunay Triangulation */ /** @name Delaunay Triangulation */
//@{ //@{
/**
//------------------------------------------------------------------------------------------------ * Inserts a new node in an existing Delaunay triangulation and
/** Inserts a new node in an existing Delaunay triangulation and
* swaps edges to obtain a new Delaunay triangulation. * swaps edges to obtain a new Delaunay triangulation.
* This is the basic function for incremental Delaunay triangulation. * This is the basic function for incremental Delaunay triangulation.
* When starting from a set of points, an initial Delaunay triangulation * When starting from a set of points, an initial Delaunay triangulation
...@@ -270,11 +263,11 @@ private: ...@@ -270,11 +263,11 @@ private:
* Note that this incremetal scheme will run much faster if the points * Note that this incremetal scheme will run much faster if the points
* have been sorted lexicographically on \e x and \e y. * have been sorted lexicographically on \e x and \e y.
* *
* \param dart * \param aDart
* An arbitrary CCW dart in the tringulation.\n * An arbitrary CCW dart in the tringulation.\n
* Output: A CCW dart incident to the new node. * Output: A CCW dart incident to the new node.
* *
* \param point * \param aPoint
* A point (node) to be inserted in the triangulation. * A point (node) to be inserted in the triangulation.
* *
* \retval bool * \retval bool
...@@ -283,11 +276,11 @@ private: ...@@ -283,11 +276,11 @@ private:
* \c false is returned. * \c false is returned.
* *
* \require * \require
* - \ref hed::TTLtraits::splitTriangle "TraitsType::splitTriangle" (DartType&, const PointType&) * - \ref hed::TTLtraits::splitTriangle "TRAITS_TYPE::splitTriangle" (DART_TYPE&, const POINT_TYPE&)
* *
* \using * \using
* - locateTriangle * - locateTriangle
* - 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.
...@@ -295,11 +288,13 @@ private: ...@@ -295,11 +288,13 @@ private:
* \see * \see
* removeRectangularBoundary * removeRectangularBoundary
*/ */
template <class TraitsType, class DartType, class PointType> template <class TRAITS_TYPE, class DART_TYPE, class POINT_TYPE>
bool TriangulationHelper::insertNode(DartType& dart, PointType& point) { bool TRIANGULATION_HELPER::InsertNode( DART_TYPE& aDart, POINT_TYPE& aPoint )
{
bool found = LocateTriangle<TRAITS_TYPE>( aPoint, aDart );
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";
#endif #endif
...@@ -307,63 +302,67 @@ private: ...@@ -307,63 +302,67 @@ private:
} }
// ??? 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
triangulation.splitTriangle(dart, point); m_triangulation.splitTriangle( aDart, aPoint );
DartType d1 = dart; DART_TYPE d1 = aDart;
d1.alpha2().alpha1().alpha2().alpha0().alpha1(); d1.Alpha2().Alpha1().Alpha2().Alpha0().Alpha1();
DartType d2 = dart; DART_TYPE d2 = aDart;
d2.alpha1().alpha0().alpha1(); d2.Alpha1().Alpha0().Alpha1();
// Preserve a dart as output incident to the node and CCW // Preserve a dart as output incident to the node and CCW
DartType d3 = dart; DART_TYPE d3 = aDart;
d3.alpha2(); d3.Alpha2();
dart = d3; // and see below aDart = d3; // and see below
//DartType dsav = d3; //DART_TYPE dsav = d3;
d3.alpha0().alpha1(); d3.Alpha0().Alpha1();
//if (!TraitsType::fixedEdge(d1) && !isBoundaryEdge(d1)) { //if (!TRAITS_TYPE::fixedEdge(d1) && !IsBoundaryEdge(d1)) {
if (!isBoundaryEdge(d1)) { if( !IsBoundaryEdge( d1 ) )
d1.alpha2(); {
recSwapDelaunay<TraitsType>(d1); d1.Alpha2();
RecSwapDelaunay<TRAITS_TYPE>( d1 );
} }
//if (!TraitsType::fixedEdge(d2) && !isBoundaryEdge(d2)) { //if (!TRAITS_TYPE::fixedEdge(d2) && !IsBoundaryEdge(d2)) {
if (!isBoundaryEdge(d2)) { if( !IsBoundaryEdge( d2 ) )
d2.alpha2(); {
recSwapDelaunay<TraitsType>(d2); d2.Alpha2();
RecSwapDelaunay<TRAITS_TYPE>( d2 );
} }
// 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(); aDart.Alpha2();
//if (!TraitsType::fixedEdge(d3) && !isBoundaryEdge(d3)) { //if (!TRAITS_TYPE::fixedEdge(d3) && !IsBoundaryEdge(d3)) {
if (!isBoundaryEdge(d3)) { if( !IsBoundaryEdge( d3 ) )
d3.alpha2(); {
recSwapDelaunay<TraitsType>(d3); d3.Alpha2();
RecSwapDelaunay<TRAITS_TYPE>( d3 );
} }
return true; return true;
} }
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------ // Private/Hidden function (might change later)
// Private/Hidden function (might change later) template <class TRAITS_TYPE, class FORWARD_ITERATOR, class DART_TYPE>
template <class TraitsType, class ForwardIterator, class DartType> void TRIANGULATION_HELPER::insertNodes( FORWARD_ITERATOR aFirst, FORWARD_ITERATOR aLast,
void TriangulationHelper::insertNodes(ForwardIterator first, ForwardIterator last, DartType& dart) { DART_TYPE& aDart )
{
// 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.
ForwardIterator it; FORWARD_ITERATOR it;
for (it = first; it != last; ++it) { for( it = aFirst; it != aLast; ++it )
insertNode<TraitsType>(dart, **it); {
} InsertNode<TRAITS_TYPE>( aDart, **it );
} }
}
//------------------------------------------------------------------------------------------------ /** Removes the rectangular boundary of a triangulation as a final step of an
/** Removes the rectangular boundary of a triangulation as a final step of an
* incremental Delaunay triangulation. * incremental Delaunay triangulation.
* The four nodes at the corners will be removed and the resulting triangulation * The four nodes at the corners will be removed and the resulting triangulation
* will have a convex boundary and be Delaunay. * will have a convex boundary and be Delaunay.
...@@ -373,129 +372,129 @@ private: ...@@ -373,129 +372,129 @@ private:
* Output: A CCW dart at the new boundary * Output: A CCW dart at the new boundary
* *
* \using * \using
* - removeBoundaryNode * - RemoveBoundaryNode
* *
* \note * \note
* - This function requires that the boundary of the triangulation is * - This function requires that the boundary of the m_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 TRAITS_TYPE, class DART_TYPE>
void TriangulationHelper::removeRectangularBoundary(DartType& dart) { void TRIANGULATION_HELPER::RemoveRectangularBoundary( DART_TYPE& aDart )
{
DartType d_next = dart; DART_TYPE d_next = aDart;
DartType d_iter; DART_TYPE d_iter;
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();
positionAtNextBoundaryEdge(d_next); PositionAtNextBoundaryEdge( d_next );
removeBoundaryNode<TraitsType>(d_iter); RemoveBoundaryNode<TRAITS_TYPE>( d_iter );
} }
dart = d_next; // Return a dart at the new boundary aDart = d_next; // Return a dart at the new boundary
} }
/** Removes the node associated with \e dart and
//------------------------------------------------------------------------------------------------
/** Removes the node associated with \e dart and
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - removeBoundaryNode if \e dart represents a node at the boundary * - RemoveBoundaryNode if \e dart represents a node at the boundary
* - 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 TRAITS_TYPE, class DART_TYPE>
void TriangulationHelper::removeNode(DartType& dart) { void TRIANGULATION_HELPER::RemoveNode( DART_TYPE& aDart )
{
if (isBoundaryNode(dart)) if( isBoundaryNode( aDart ) )
removeBoundaryNode<TraitsType>(dart); RemoveBoundaryNode<TRAITS_TYPE>( aDart );
else else
removeInteriorNode<TraitsType>(dart); RemoveInteriorNode<TRAITS_TYPE>( aDart );
} }
/** Removes the boundary node associated with \e dart and
//------------------------------------------------------------------------------------------------
/** Removes the boundary node associated with \e dart and
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - swapEdgesAwayFromBoundaryNode * - SwapEdgesAwayFromBoundaryNode
* - optimizeDelaunay * - OptimizeDelaunay
* *
* \require * \require
* - \ref hed::TTLtraits::removeBoundaryTriangle "TraitsType::removeBoundaryTriangle" (Dart&) * - \ref hed::TTLtraits::removeBoundaryTriangle "TRAITS_TYPE::removeBoundaryTriangle" (Dart&)
*/ */
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void TriangulationHelper::removeBoundaryNode(DartType& dart) { void TRIANGULATION_HELPER::RemoveBoundaryNode( DART_TYPE& aDart )
{
// ... and update Delaunay // ... and update Delaunay
// - CCW dart must be given (for remove) // - CCW dart must be given (for remove)
// - No dart is delivered back now (but this is possible if // - No dart is delivered back now (but this is possible if
// 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 m_triangulation.
// Position at boundary edge and CCW // Position at boundary edge and CCW
if (!isBoundaryEdge(dart)) { if( !IsBoundaryEdge( aDart ) )
dart.alpha1(); // ensures that next function delivers back a CCW dart (if the given dart is CCW) {
positionAtNextBoundaryEdge(dart); aDart.Alpha1(); // ensures that next function delivers back a CCW dart (if the given dart is CCW)
PositionAtNextBoundaryEdge( aDart );
} }
std::list<DartType> swapped_edges; std::list<DART_TYPE> swapped_edges;
swapEdgesAwayFromBoundaryNode<TraitsType>(dart, swapped_edges); SwapEdgesAwayFromBoundaryNode<TRAITS_TYPE>( aDart, 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.
DartType d_iter = dart; DART_TYPE d_iter = aDart;
DartType dnext = dart; DART_TYPE dnext = aDart;
bool bend = false; bool bend = false;
while (bend == false) { while( bend == false )
dnext.alpha1().alpha2(); {
if (isBoundaryEdge(dnext)) dnext.Alpha1().Alpha2();
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
DartType n_bedge = d_iter; DART_TYPE n_bedge = d_iter;
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 std::list<DartType>::iterator it; typename std::list<DART_TYPE>::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
triangulation.removeBoundaryTriangle(d_iter); m_triangulation.removeBoundaryTriangle( d_iter );
d_iter = dnext; d_iter = dnext;
} }
// Optimize Delaunay // Optimize Delaunay
typedef std::list<DartType> DartListType; typedef std::list<DART_TYPE> DART_LIST_TYPE;
optimizeDelaunay<TraitsType, DartType, DartListType>(swapped_edges); OptimizeDelaunay<TRAITS_TYPE, DART_TYPE, DART_LIST_TYPE>( swapped_edges );
} }
//------------------------------------------------------------------------------------------------ /** Removes the interior node associated with \e dart and
/** Removes the interior node associated with \e dart and
* updates the triangulation to be Delaunay. * updates the triangulation to be Delaunay.
* *
* \using * \using
* - swapEdgesAwayFromInteriorNode * - SwapEdgesAwayFromInteriorNode
* - optimizeDelaunay * - OptimizeDelaunay
* *
* \require * \require
* - \ref hed::TTLtraits::reverse_splitTriangle "TraitsType::reverse_splitTriangle" (Dart&) * - \ref hed::TTLtraits::reverse_splitTriangle "TRAITS_TYPE::reverse_splitTriangle" (Dart&)
* *
* \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 TRAITS_TYPE, class DART_TYPE>
void TriangulationHelper::removeInteriorNode(DartType& dart) { void TRIANGULATION_HELPER::RemoveInteriorNode( DART_TYPE& aDart )
{
// ... 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
// Assumes: // Assumes:
...@@ -505,18 +504,18 @@ private: ...@@ -505,18 +504,18 @@ private:
// 1) Swaps edges away from the node until degree=3 (generic) // 1) Swaps edges away from the node until degree=3 (generic)
// 2) Removes the remaining 3 triangles and creates a new to fill the hole // 2) Removes the remaining 3 triangles and creates a new to fill the hole
// unsplitTriangle which is required // unsplitTriangle which is required
// 3) Runs LOP on the platelet to obtain a Delaunay triangulation // 3) Runs LOP on the platelet to obtain a Delaunay m_triangulation
// (No dart is delivered as output) // (No dart is delivered as output)
// Assumes dart is counterclockwise // Assumes dart is counterclockwise
std::list<DartType> swapped_edges; std::list<DART_TYPE> swapped_edges;
swapEdgesAwayFromInteriorNode<TraitsType>(dart, swapped_edges); SwapEdgesAwayFromInteriorNode<TRAITS_TYPE>( aDart, 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:: // TRAITS_TYPE::
triangulation.reverse_splitTriangle(dart); m_triangulation.reverseSplitTriangle( aDart );
// ???? 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
...@@ -529,75 +528,72 @@ private: ...@@ -529,75 +528,72 @@ private:
// 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
optimizeDelaunay<TraitsType, DartType>(swapped_edges); OptimizeDelaunay<TRAITS_TYPE, DART_TYPE>( swapped_edges );
} }
//@} // End of Delaunay Triangulation Group
//------------------------------------------------------------------------------------------------ //@} // End of Delaunay Triangulation Group
// -------------------------- Topological and Geometric Queries Group ---------------------------
//------------------------------------------------------------------------------------------------
/** @name Topological and Geometric Queries */
//@{
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
template <class TopologyElementType, class DartType>
bool TriangulationHelper::isMemberOfFace(const TopologyElementType& topologyElement, const DartType& dart) {
/** @name Topological and Geometric Queries */
//@{
//------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later)
template <class TOPOLOGY_ELEMENT_TYPE, class DART_TYPE>
bool TRIANGULATION_HELPER::isMemberOfFace( const TOPOLOGY_ELEMENT_TYPE& aTopologyElement,
const DART_TYPE& aDart )
{
// 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:
// - DartType::isMember(TopologyElementType) // - DART_TYPE::isMember(TOPOLOGY_ELEMENT_TYPE)
DartType dart_iter = dart; DART_TYPE dart_iter = aDart;
do {
if (dart_iter.isMember(topologyElement))
return true;
dart_iter.alpha0().alpha1();
} while (dart_iter != dart);
return false; do
{
if( dart_iter.isMember( aTopologyElement ) )
return true;
dart_iter.Alpha0().Alpha1();
} }
while( dart_iter != aDart );
return false;
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class TraitsType, class NodeType, class DartType> template <class TRAITS_TYPE, class NODE_TYPE, class DART_TYPE>
bool TriangulationHelper::locateFaceWithNode(const NodeType& node, DartType& dart_iter) { bool TRIANGULATION_HELPER::locateFaceWithNode( const NODE_TYPE& aNode, DART_TYPE& aDartIter )
{
// 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) // - TRAITS_TYPE::Orient2D(DART_TYPE, DART_TYPE, NODE_TYPE)
// - DartType::isMember(NodeType) // - DART_TYPE::isMember(NODE_TYPE)
// - Note that if false is returned, the node might still be in the // - Note that if false is returned, the node might still be in the
// topology structure. Application programmer // topology structure. Application programmer
// should check all if by hypothesis the node is in the topology structure; // should check all if by hypothesis the node is in the topology structure;
// see doc. on locateTriangle. // see doc. on LocateTriangle.
bool status = locateFaceSimplest<TraitsType>(node, dart_iter); bool status = LocateFaceSimplest<TRAITS_TYPE>( aNode, aDartIter );
if (status == false)
if( status == false )
return status; return status;
// True was returned from locateFaceSimplest, but if the located triangle is // True was returned from LocateFaceSimplest, but if the located triangle is
// degenerate and the node is on the extension of the edges, // degenerate and the node is on the extension of the edges,
// the node might still be inside. Check if node is a member and return false // the node might still be inside. Check if node is a member and return false
// if not. (Still the node might be in the topology structure, see doc. above // if not. (Still the node might be in the topology structure, see doc. above
// and in locateTriangle(const PointType& point, DartType& dart_iter) // and in locateTriangle(const POINT_TYPE& point, DART_TYPE& dart_iter)
return isMemberOfFace(node, dart_iter);
}
return isMemberOfFace( aNode, aDartIter );
}
//------------------------------------------------------------------------------------------------ /** Locates the face containing a given point.
/** Locates the face containing a given point.
* It is assumed that the tessellation (e.g. a triangulation) is \e regular in the sense that * It is assumed that the tessellation (e.g. a triangulation) is \e regular in the sense that
* there are no holes, the boundary is convex and there are no degenerate faces. * there are no holes, the boundary is convex and there are no degenerate faces.
* *
* \param point * \param aPoint
* A point to be located * A point to be located
* *
* \param dart * \param aDart
* An arbitrary CCW dart in the triangulation\n * An arbitrary CCW dart in the triangulation\n
* Output: A CCW dart in the located face * Output: A CCW dart in the located face
* *
...@@ -605,17 +601,18 @@ private: ...@@ -605,17 +601,18 @@ private:
* \c true if a face is found; \c false if not. * \c true if a face is found; \c false if not.
* *
* \require * \require
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&) * - \ref hed::TTLtraits::Orient2D "TRAITS_TYPE::Orient2D" (DART_TYPE&, DART_TYPE&, POINT_TYPE&)
* *
* \note * \note
* - If \c false is returned, \e point may still be inside a face if the tessellation is not * - If \c false is returned, \e point may still be inside a face if the tessellation is not
* \e regular as explained above. * \e regular as explained above.
* *
* \see * \see
* locateTriangle * LocateTriangle
*/ */
template <class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
bool TriangulationHelper::locateFaceSimplest(const PointType& point, DartType& dart) { bool TRIANGULATION_HELPER::LocateFaceSimplest( const POINT_TYPE& aPoint, DART_TYPE& aDart )
{
// 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
...@@ -623,43 +620,47 @@ private: ...@@ -623,43 +620,47 @@ private:
// convex faces (works for general convex faces) // convex faces (works for general convex faces)
// Not specialized for triangles, but ok? // Not specialized for triangles, but ok?
// //
// TraitsType::orint2d(PointType) is the half open half-plane defined // TRAITS_TYPE::orint2d(POINT_TYPE) is the half open half-plane defined
// by the dart: // by the dart:
// n1 = dart.node() // n1 = dart.node()
// n2 = dart.alpha0().node // n2 = dart.Alpha0().node
// Only the following gives true: // Only the following gives true:
// ((n2->x()-n1->x())*(point.y()-n1->y()) >= (point.x()-n1->x())*(n2->y()-n1->y())) // ((n2->x()-n1->x())*(point.y()-n1->y()) >= (point.x()-n1->x())*(n2->y()-n1->y()))
DartType dart_start; DART_TYPE dart_start;
dart_start = dart; dart_start = aDart;
DartType dart_prev; DART_TYPE dart_prev;
DartType d0; DART_TYPE d0;
for (;;) { for( ;; )
d0 = dart; {
d0.alpha0(); d0 = aDart;
if (TraitsType::orient2d(dart, d0, point) >= 0) { d0.Alpha0();
dart.alpha0().alpha1();
if (dart == dart_start) if( TRAITS_TYPE::Orient2D( aDart, d0, aPoint ) >= 0 )
{
aDart.Alpha0().Alpha1();
if( aDart == dart_start )
return true; // left to all edges in face return true; // left to all edges in face
} }
else { else
dart_prev = dart; {
dart.alpha2(); dart_prev = aDart;
if (dart == dart_prev) aDart.Alpha2();
if( aDart == dart_prev )
return false; // iteration to outside boundary return false; // iteration to outside boundary
dart_start = dart; dart_start = aDart;
dart_start.alpha0(); dart_start.Alpha0();
dart.alpha1(); // avoid twice on same edge and ccw in next aDart.Alpha1(); // avoid twice on same edge and ccw in next
}
} }
} }
}
//------------------------------------------------------------------------------------------------ /** Locates the triangle containing a given point.
/** Locates the triangle containing a given point.
* It is assumed that the triangulation is \e regular in the sense that there * It is assumed that the triangulation is \e regular in the sense that there
* are no holes and the boundary is convex. * are no holes and the boundary is convex.
* This function deals with degeneracy to some extent, but round-off errors may still * This function deals with degeneracy to some extent, but round-off errors may still
...@@ -674,15 +675,16 @@ private: ...@@ -674,15 +675,16 @@ private:
* *
* \retval bool * \retval bool
* \c true if a triangle is found; \c false if not.\n * \c true if a triangle is found; \c false if not.\n
* If \e point is outside the triangulation, in which case \c false is returned, * If \e point is outside the m_triangulation, in which case \c false is returned,
* 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 m_triangulation.
* *
* \using * \using
* - locateFaceSimplest * - LocateFaceSimplest
* - inTriangle * - InTriangle
*/ */
template <class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
bool TriangulationHelper::locateTriangle(const PointType& point, DartType& dart) { bool TRIANGULATION_HELPER::LocateTriangle( const POINT_TYPE& aPoint, DART_TYPE& aDart )
{
// 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
...@@ -690,7 +692,7 @@ private: ...@@ -690,7 +692,7 @@ private:
// Thus, if false is returned, the point might still be inside a triangle in // Thus, if false is returned, the point might still be inside a triangle in
// the triangulation. But this will probably only occur in the following cases: // the triangulation. But this will probably only occur in the following cases:
// i) There are holes in the triangulation which causes the procedure to stop. // i) There are holes in the triangulation which causes the procedure to stop.
// ii) The boundary of the triangulation is not convex. // ii) The boundary of the m_triangulation is not convex.
// ii) There might be degenerate triangles interior to the triangulation, or on the // ii) There might be degenerate triangles interior to the triangulation, or on the
// the boundary, which in some cases might cause the procedure to stop there due // the boundary, which in some cases might cause the procedure to stop there due
// to the logic of the algorithm. // to the logic of the algorithm.
...@@ -700,14 +702,14 @@ private: ...@@ -700,14 +702,14 @@ private:
// in the triangulation and and false is returned, then all triangles in the // in the triangulation and and false is returned, then all triangles in the
// triangulation should be checked by the application. This can be done using // triangulation should be checked by the application. This can be done using
// the function: // the function:
// bool inTriangle(const PointType& point, const DartType& dart). // bool inTriangle(const POINT_TYPE& point, const DART_TYPE& dart).
// Assumes: // Assumes:
// - crossProduct2d, scalarProduct2d etc., see functions called // - CrossProduct2D, ScalarProduct2D etc., see functions called
bool status = LocateFaceSimplest<TRAITS_TYPE>( aPoint, aDart );
bool status = locateFaceSimplest<TraitsType>(point, dart); if( status == false )
if (status == false)
return status; return status;
// There may be degeneracy, i.e., the point might be outside the triangle // There may be degeneracy, i.e., the point might be outside the triangle
...@@ -716,460 +718,453 @@ private: ...@@ -716,460 +718,453 @@ private:
// The next call returns true if inside a non-degenerate or a degenerate triangle, // The next call returns true if inside a non-degenerate or a degenerate triangle,
// but false if the point coincides with the "supernode" in the case where all // but false if the point coincides with the "supernode" in the case where all
// edges are degenerate. // edges are degenerate.
return inTriangle<TraitsType>(point, dart); return InTriangle<TRAITS_TYPE>( aPoint, aDart );
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
/** Checks if \e point is inside the triangle associated with \e dart. /** Checks if \e point is inside the triangle associated with \e dart.
* A fast and simple function that does not deal with degeneracy. * A fast and simple function that does not deal with degeneracy.
* *
* \param dart * \param aDart
* A CCW dart in the triangle * A CCW dart in the triangle
* *
* \require * \require
* - \ref hed::TTLtraits::orient2d "TraitsType::orient2d" (DartType&, DartType&, PointType&) * - \ref hed::TTLtraits::Orient2D "TRAITS_TYPE::Orient2D" (DART_TYPE&, DART_TYPE&, POINT_TYPE&)
* *
* \see * \see
* inTriangle for a more robust function * InTriangle for a more robust function
*/ */
template <class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
bool TriangulationHelper::inTriangleSimplest(const PointType& point, const DartType& dart) { bool TRIANGULATION_HELPER::InTriangleSimplest( const POINT_TYPE& aPoint, const DART_TYPE& aDart )
{
// 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
// edges of a degenerate triangle // edges of a degenerate triangle
DartType d_iter = dart; DART_TYPE d_iter = aDart;
DartType d0 = d_iter; DART_TYPE d0 = d_iter;
d0.alpha0(); d0.Alpha0();
if (!TraitsType::orient2d(d_iter, d0, point) >= 0)
if( !TRAITS_TYPE::Orient2D( d_iter, d0, aPoint ) >= 0 )
return false; return false;
d_iter.alpha0().alpha1(); d_iter.Alpha0().Alpha1();
d0 = d_iter; d0 = d_iter;
d0.alpha0(); d0.Alpha0();
if (!TraitsType::orient2d(d_iter, d0, point) >= 0)
if( !TRAITS_TYPE::Orient2D( d_iter, d0, aPoint ) >= 0 )
return false; return false;
d_iter.alpha0().alpha1(); d_iter.Alpha0().Alpha1();
d0 = d_iter; d0 = d_iter;
d0.alpha0(); d0.Alpha0();
if (!TraitsType::orient2d(d_iter, d0, point) >= 0)
if( !TRAITS_TYPE::Orient2D( d_iter, d0, aPoint ) >= 0 )
return false; return false;
return true; return true;
} }
/** Checks if \e point is inside the triangle associated with \e dart.
//------------------------------------------------------------------------------------------------
/** Checks if \e point is inside the triangle associated with \e dart.
* This function deals with degeneracy to some extent, but round-off errors may still * This function deals with degeneracy to some extent, but round-off errors may still
* lead to wrong result if the triangle is degenerate. * lead to wrong result if the triangle is degenerate.
* *
* \param dart * \param aDart
* A CCW dart in the triangle * A CCW dart in the triangle
* *
* \require * \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (DartType&, PointType&) * - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (DART_TYPE&, POINT_TYPE&)
* - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, PointType&) * - \ref hed::TTLtraits::ScalarProduct2D "TRAITS_TYPE::ScalarProduct2D" (DART_TYPE&, POINT_TYPE&)
* *
* \see * \see
* inTriangleSimplest * InTriangleSimplest
*/ */
template <class TraitsType, class PointType, class DartType> template <class TRAITS_TYPE, class POINT_TYPE, class DART_TYPE>
bool TriangulationHelper::inTriangle(const PointType& point, const DartType& dart) { bool TRIANGULATION_HELPER::InTriangle( const POINT_TYPE& aPoint, const DART_TYPE& aDart )
{
// 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
// notInE1 && notInE1.neghbour ? // notInE1 && notInE1.neghbour ?
// Returns true if inside (but not necessarily strictly inside) // Returns true if inside (but not necessarily strictly inside)
// Works for degenerate triangles, but not when all edges are degenerate, // Works for degenerate triangles, but not when all edges are degenerate,
// and the point coincides with all nodes; // and the aPoint coincides with all nodes;
// then false is always returned. // then false is always returned.
typedef typename TraitsType::real_type real_type; typedef typename TRAITS_TYPE::REAL_TYPE REAL_TYPE;
DartType dart_iter = dart; DART_TYPE dart_iter = aDart;
real_type cr1 = TraitsType::crossProduct2d(dart_iter, point); REAL_TYPE cr1 = TRAITS_TYPE::CrossProduct2D( dart_iter, aPoint );
if (cr1 < 0) if( cr1 < 0 )
return false; return false;
dart_iter.alpha0().alpha1(); dart_iter.Alpha0().Alpha1();
real_type cr2 = TraitsType::crossProduct2d(dart_iter, point); REAL_TYPE cr2 = TRAITS_TYPE::CrossProduct2D( dart_iter, aPoint );
if (cr2 < 0) if( cr2 < 0 )
return false; return false;
dart_iter.alpha0().alpha1(); dart_iter.Alpha0().Alpha1();
real_type cr3 = TraitsType::crossProduct2d(dart_iter, point); REAL_TYPE cr3 = TRAITS_TYPE::CrossProduct2D( dart_iter, aPoint );
if (cr3 < 0) if( cr3 < 0 )
return false; return false;
// All cross products are >= 0 // All cross products are >= 0
// Check for degeneracy // Check for degeneracy
if( cr1 != 0 || cr2 != 0 || cr3 != 0 )
if (cr1 != 0 || cr2 != 0 || cr3 != 0)
return true; // inside non-degenerate face return true; // inside non-degenerate face
// All cross-products are zero, i.e. degenerate triangle, check if inside // All cross-products are zero, i.e. degenerate triangle, check if inside
// Strategy: d.scalarProduct2d >= 0 && alpha0(d).d.scalarProduct2d >= 0 for one of // Strategy: d.ScalarProduct2D >= 0 && alpha0(d).d.ScalarProduct2D >= 0 for one of
// the edges. But if all edges are degenerate and the point is on (all) the nodes, // the edges. But if all edges are degenerate and the aPoint is on (all) the nodes,
// then "false is returned". // then "false is returned".
DartType dart_tmp = dart_iter; DART_TYPE dart_tmp = dart_iter;
real_type sc1 = TraitsType::scalarProduct2d(dart_tmp,point); REAL_TYPE sc1 = TRAITS_TYPE::ScalarProduct2D( dart_tmp, aPoint );
real_type sc2 = TraitsType::scalarProduct2d(dart_tmp.alpha0(), point); REAL_TYPE sc2 = TRAITS_TYPE::ScalarProduct2D( dart_tmp.Alpha0(), aPoint );
if (sc1 >= 0 && sc2 >= 0) { if( sc1 >= 0 && sc2 >= 0 )
{
// test for degenerate edge // test for degenerate edge
if (sc1 != 0 || sc2 != 0) if( sc1 != 0 || sc2 != 0 )
return true; // interior to this edge or on a node (but see comment above) return true; // interior to this edge or on a node (but see comment above)
} }
dart_tmp = dart_iter.alpha0().alpha1(); dart_tmp = dart_iter.Alpha0().Alpha1();
sc1 = TraitsType::scalarProduct2d(dart_tmp,point); sc1 = TRAITS_TYPE::ScalarProduct2D( dart_tmp, aPoint );
sc2 = TraitsType::scalarProduct2d(dart_tmp.alpha0(),point); sc2 = TRAITS_TYPE::ScalarProduct2D( dart_tmp.Alpha0(), aPoint );
if (sc1 >= 0 && sc2 >= 0) {
if( sc1 >= 0 && sc2 >= 0 )
{
// test for degenerate edge // test for degenerate edge
if (sc1 != 0 || sc2 != 0) if( sc1 != 0 || sc2 != 0 )
return true; // interior to this edge or on a node (but see comment above) return true; // interior to this edge or on a node (but see comment above)
} }
dart_tmp = dart_iter.alpha1(); dart_tmp = dart_iter.Alpha1();
sc1 = TraitsType::scalarProduct2d(dart_tmp,point); sc1 = TRAITS_TYPE::ScalarProduct2D( dart_tmp, aPoint );
sc2 = TraitsType::scalarProduct2d(dart_tmp.alpha0(),point); sc2 = TRAITS_TYPE::ScalarProduct2D( dart_tmp.Alpha0(), aPoint );
if (sc1 >= 0 && sc2 >= 0) {
if( sc1 >= 0 && sc2 >= 0 )
{
// test for degenerate edge // test for degenerate edge
if (sc1 != 0 || sc2 != 0) if( sc1 != 0 || sc2 != 0 )
return true; // interior to this edge or on a node (but see comment above) return true; // interior to this edge or on a node (but see comment above)
} }
// Not on any of the edges of the degenerate triangle. // Not on any of the edges of the degenerate triangle.
// The only possibility for the point to be "inside" is that all edges are degenerate // The only possibility for the aPoint to be "inside" is that all edges are degenerate
// and the point coincide with all nodes. So false is returned in this case. // and the point coincide with all nodes. So false is returned in this case.
return false; return false;
} }
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Private/Hidden function (might change later) // Private/Hidden function (might change later)
template <class DartType> template <class DART_TYPE>
void TriangulationHelper::getAdjacentTriangles(const DartType& dart, DartType& t1, DartType& t2, DartType& t3) { void TRIANGULATION_HELPER::getAdjacentTriangles( const DART_TYPE& aDart, DART_TYPE& aT1,
DART_TYPE& aT2, DART_TYPE& aT3 )
{
DartType dart_iter = dart; DART_TYPE dart_iter = aDart;
// add first // add first
if (dart_iter.alpha2() != dart) { if( dart_iter.Alpha2() != aDart )
t1 = dart_iter; {
dart_iter = dart; aT1 = dart_iter;
dart_iter = aDart;
} }
// add second // add second
dart_iter.alpha0(); dart_iter.Alpha0();
dart_iter.alpha1(); dart_iter.Alpha1();
DartType dart_prev = dart_iter; DART_TYPE dart_prev = dart_iter;
if ((dart_iter.alpha2()) != dart_prev) {
t2 = dart_iter; if( ( dart_iter.Alpha2() ) != dart_prev )
{
aT2 = dart_iter;
dart_iter = dart_prev; dart_iter = dart_prev;
} }
// add third // add third
dart_iter.alpha0(); dart_iter.Alpha0();
dart_iter.alpha1(); dart_iter.Alpha1();
dart_prev = dart_iter; dart_prev = dart_iter;
if ((dart_iter.alpha2()) != dart_prev)
t3 = dart_iter;
}
if( ( dart_iter.Alpha2() ) != dart_prev )
aT3 = dart_iter;
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
/** Gets the boundary as sequence of darts, where the edges associated with the darts are boundary /** Gets the boundary as sequence of darts, where the edges associated with the darts are boundary
* edges, given a dart with an associating edge at the boundary of a topology structure. * edges, given a dart with an associating edge at the boundary of a topology structure.
* The first dart in the sequence will be the given one, and the others will have the same * The first dart in the sequence will be the given one, and the others will have the same
* orientation (CCW or CW) as the first. * orientation (CCW or CW) as the first.
* Assumes that the given dart is at the boundary. * Assumes that the given dart is at the boundary.
* *
* \param dart * \param aDart
* A dart at the boundary (CCW or CW) * A dart at the boundary (CCW or CW)
* *
* \param boundary * \param aBoundary
* A sequence of darts, where the associated edges are the boundary edges * A sequence of darts, where the associated edges are the boundary edges
* *
* \require * \require
* - DartListType::push_back (DartType&) * - DART_LIST_TYPE::push_back (DART_TYPE&)
*/ */
template <class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
void TriangulationHelper::getBoundary(const DartType& dart, DartListType& boundary) { void TRIANGULATION_HELPER::GetBoundary( const DART_TYPE& aDart, DART_LIST_TYPE& aBoundary )
{
// assumes the given dart is at the boundary (by edge) // assumes the given dart is at the boundary (by edge)
DartType dart_iter(dart); DART_TYPE dart_iter( aDart );
boundary.push_back(dart_iter); // Given dart as first element aBoundary.push_back( dart_iter ); // Given dart as first element
dart_iter.alpha0(); dart_iter.Alpha0();
positionAtNextBoundaryEdge(dart_iter); PositionAtNextBoundaryEdge( dart_iter );
while (dart_iter != dart) { while( dart_iter != aDart )
boundary.push_back(dart_iter); {
dart_iter.alpha0(); aBoundary.push_back( dart_iter );
positionAtNextBoundaryEdge(dart_iter); dart_iter.Alpha0();
} PositionAtNextBoundaryEdge( dart_iter );
} }
}
/** Checks if the edge associated with \e dart is at
//------------------------------------------------------------------------------------------------ * the boundary of the m_triangulation.
/*
// Asumes a fixed point (a boundary edge) is given
//
template <class DartType>
class boundary_1_Iterator { // i.e. "circulator"
DartType current_;
public:
boundaryEdgeIterator(const DartType& dart) {current_ = dart;}
DartType& operator * () const {return current_;}
void operator ++ () {current_.alpha0(); positionAtNextBoundaryEdge(current_);}
};
*/
//------------------------------------------------------------------------------------------------
/** Checks if the edge associated with \e dart is at
* the boundary of the triangulation.
* *
* \par Implements: * \par Implements:
* \code * \code
* DartType dart_iter = dart; * DART_TYPE dart_iter = dart;
* if (dart_iter.alpha2() == dart) * if (dart_iter.Alpha2() == dart)
* return true; * return true;
* else * else
* return false; * return false;
* \endcode * \endcode
*/ */
template <class DartType> template <class DART_TYPE>
bool TriangulationHelper::isBoundaryEdge(const DartType& dart) { bool TRIANGULATION_HELPER::IsBoundaryEdge( const DART_TYPE& aDart )
{
DART_TYPE dart_iter = aDart;
DartType dart_iter = dart; if( dart_iter.Alpha2() == aDart )
if (dart_iter.alpha2() == dart)
return true; return true;
else else
return false; return false;
} }
/** Checks if the face associated with \e dart is at
//------------------------------------------------------------------------------------------------ * the boundary of the m_triangulation.
/** Checks if the face associated with \e dart is at
* the boundary of the triangulation.
*/ */
template <class DartType> template <class DART_TYPE>
bool TriangulationHelper::isBoundaryFace(const DartType& dart) { bool TRIANGULATION_HELPER::IsBoundaryFace( const DART_TYPE& aDart )
{
// Strategy: boundary if alpha2(d)=d // Strategy: boundary if alpha2(d)=d
DartType dart_iter(dart); DART_TYPE dart_iter( aDart );
DartType dart_prev; DART_TYPE dart_prev;
do { do
{
dart_prev = dart_iter; dart_prev = dart_iter;
if (dart_iter.alpha2() == dart_prev) if( dart_iter.Alpha2() == dart_prev )
return true; return true;
else else
dart_iter = dart_prev; // back again dart_iter = dart_prev; // back again
dart_iter.alpha0(); dart_iter.Alpha0();
dart_iter.alpha1(); dart_iter.Alpha1();
} while (dart_iter != dart); } while( dart_iter != aDart );
return false; return false;
} }
//------------------------------------------------------------------------------------------------ /** Checks if the node associated with \e dart is at
/** Checks if the node associated with \e dart is at * the boundary of the m_triangulation.
* the boundary of the triangulation.
*/ */
template <class DartType> template <class DART_TYPE>
bool TriangulationHelper::isBoundaryNode(const DartType& dart) { bool TRIANGULATION_HELPER::IsBoundaryNode( const DART_TYPE& aDart )
{
// Strategy: boundary if alpha2(d)=d // Strategy: boundary if alpha2(d)=d
DartType dart_iter(dart); DART_TYPE dart_iter( aDart );
DartType dart_prev; DART_TYPE dart_prev;
// If input dart is reached again, then internal node // If input dart is reached again, then internal node
// If alpha2(d)=d, then boundary // If alpha2(d)=d, then boundary
do { do
dart_iter.alpha1(); {
dart_iter.Alpha1();
dart_prev = dart_iter; dart_prev = dart_iter;
dart_iter.alpha2(); dart_iter.Alpha2();
if (dart_iter == dart_prev) if( dart_iter == dart_prev )
return true; return true;
} while (dart_iter != dart); } while( dart_iter != aDart );
return false; return false;
} }
/** Returns the degree of the node associated with \e dart.
//------------------------------------------------------------------------------------------------
/** Returns the degree of the node associated with \e dart.
* *
* \par Definition: * \par Definition:
* The \e degree (or valency) of a node \e V in a triangulation, * The \e degree (or valency) of a node \e V in a m_triangulation,
* is defined as the number of edges incident with \e V, i.e., * is defined as the number of edges incident with \e V, i.e.,
* 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 DART_TYPE>
int TriangulationHelper::getDegreeOfNode(const DartType& dart) { int TRIANGULATION_HELPER::GetDegreeOfNode( const DART_TYPE& aDart )
{
DartType dart_iter(dart); DART_TYPE dart_iter( aDart );
DartType dart_prev; DART_TYPE dart_prev;
// If input dart is reached again, then interior node // If input dart is reached again, then interior node
// If alpha2(d)=d, then boundary // If alpha2(d)=d, then boundary
int degree = 0; int degree = 0;
bool boundaryVisited = false; bool boundaryVisited = false;
do { do
dart_iter.alpha1(); {
dart_iter.Alpha1();
degree++; degree++;
dart_prev = dart_iter; dart_prev = dart_iter;
dart_iter.alpha2(); dart_iter.Alpha2();
if (dart_iter == dart_prev) { if( dart_iter == dart_prev )
if (!boundaryVisited) { {
if( !boundaryVisited )
{
boundaryVisited = true; boundaryVisited = true;
// boundary is reached first time, count in the reversed direction // boundary is reached first time, count in the reversed direction
degree++; // count the start since it is not done above degree++; // count the start since it is not done above
dart_iter = dart; dart_iter = aDart;
dart_iter.alpha2(); dart_iter.Alpha2();
} } else
else
return degree; return degree;
} }
} while (dart_iter != dart); } while( dart_iter != aDart );
return degree; return degree;
} }
// Modification of GetDegreeOfNode:
// Strategy, reverse the list and start in the other direction if the boundary
// is reached. NB. copying of darts but ok., or we could have collected pointers,
// but the memory management.
//------------------------------------------------------------------------------------------------ // NOTE: not symmetry if we choose to collect opposite edges
// Modification of getDegreeOfNode: // now we collect darts with radiating edges
// Strategy, reverse the list and start in the other direction if the boundary
// is reached. NB. copying of darts but ok., or we could have collected pointers,
// but the memory management.
// NOTE: not symmetry if we choose to collect opposite edges
// now we collect darts with radiating edges
// Remember that we must also copy the node, but ok with push_back // Remember that we must also copy the node, but ok with push_back
// The size of the list will be the degree of the node // The size of the list will be the degree of the node
// No CW/CCW since topology only // No CW/CCW since topology only
// Each dart consists of an incident edge and an adjacent node.
// But note that this is only how we interpret the dart in this implementation.
// Given this list, how can we find the opposite edges:
// We can perform alpha1 on each, but for boundary nodes we will get one edge twice.
// But this is will always be the last dart!
// The darts in the list are in sequence and starts with the alpha0(dart)
// alpha0, alpha1 and alpha2
// Each dart consists of an incident edge and an adjacent node. // Private/Hidden function
// But note that this is only how we interpret the dart in this implementation. template <class DART_TYPE>
// Given this list, how can we find the opposite edges: void TRIANGULATION_HELPER::getNeighborNodes( const DART_TYPE& aDart,
// We can perform alpha1 on each, but for boundary nodes we will get one edge twice. std::list<DART_TYPE>& aNodeList, bool& aBoundary )
// But this is will always be the last dart! {
// The darts in the list are in sequence and starts with the alpha0(dart) DART_TYPE dart_iter( aDart );
// alpha0, alpha1 and alpha2 dart_iter.Alpha0(); // position the dart at an opposite node
// Private/Hidden function
template <class DartType>
void TriangulationHelper::getNeighborNodes(const DartType& dart,
std::list<DartType>& node_list, bool& boundary) {
DartType dart_iter(dart);
dart_iter.alpha0(); // position the dart at an opposite node
DartType dart_prev = dart_iter;
DART_TYPE dart_prev = dart_iter;
bool start_at_boundary = false; bool start_at_boundary = false;
dart_iter.alpha2(); dart_iter.Alpha2();
if (dart_iter == dart_prev)
if( dart_iter == dart_prev )
start_at_boundary = true; start_at_boundary = true;
else else
dart_iter = dart_prev; // back again dart_iter = dart_prev; // back again
DartType dart_start = dart_iter; DART_TYPE dart_start = dart_iter;
do { do
node_list.push_back(dart_iter); {
dart_iter.alpha1(); aNodeList.push_back( dart_iter );
dart_iter.alpha0(); dart_iter.Alpha1();
dart_iter.alpha1(); dart_iter.Alpha0();
dart_iter.Alpha1();
dart_prev = dart_iter; dart_prev = dart_iter;
dart_iter.alpha2(); dart_iter.Alpha2();
if (dart_iter == dart_prev) {
if( dart_iter == dart_prev )
{
// boundary reached // boundary reached
boundary = true; aBoundary = true;
if (start_at_boundary == true) {
if( start_at_boundary == true )
{
// add the dart which now is positioned at the opposite boundary // add the dart which now is positioned at the opposite boundary
node_list.push_back(dart_iter); aNodeList.push_back( dart_iter );
return; return;
} }
else { else
{
// call the function again such that we start at the boundary // call the function again such that we start at the boundary
// first clear the list and reposition to the initial node // first clear the list and reposition to the initial node
dart_iter.alpha0(); dart_iter.Alpha0();
node_list.clear(); aNodeList.clear();
getNeighborNodes(dart_iter, node_list, boundary); getNeighborNodes( dart_iter, aNodeList, aBoundary );
return; // after one recursive step return; // after one recursive step
} }
} }
} while (dart_iter != dart_start);
boundary = false;
} }
while( dart_iter != dart_start );
aBoundary = false;
}
//------------------------------------------------------------------------------------------------ /** Gets the 0-orbit around an interior node.
/** Gets the 0-orbit around an interior node.
* *
* \param dart * \param aDart
* A dart (CCW or CW) positioned at an \e interior node. * A dart (CCW or CW) positioned at an \e interior node.
* *
* \retval orbit * \retval aOrbit
* Sequence of darts with one orbit for each arc. All the darts have the same * Sequence of darts with one orbit for each arc. All the darts have the same
* orientation (CCW or CW) as \e dart, and \e dart is the first element * orientation (CCW or CW) as \e dart, and \e dart is the first element
* in the sequence. * in the sequence.
* *
* \require * \require
* - DartListType::push_back (DartType&) * - DART_LIST_TYPE::push_back (DART_TYPE&)
* *
* \see * \see
* get_0_orbit_boundary * Get0OrbitBoundary
*/ */
template <class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
void TriangulationHelper::get_0_orbit_interior(const DartType& dart, DartListType& orbit) { void TRIANGULATION_HELPER::Get0OrbitInterior( const DART_TYPE& aDart, DART_LIST_TYPE& aOrbit )
{
DartType d_iter = dart; DART_TYPE d_iter = aDart;
orbit.push_back(d_iter); aOrbit.push_back( d_iter );
d_iter.alpha1().alpha2(); d_iter.Alpha1().Alpha2();
while (d_iter != dart) { while( d_iter != aDart )
orbit.push_back(d_iter); {
d_iter.alpha1().alpha2(); aOrbit.push_back( d_iter );
} d_iter.Alpha1().Alpha2();
} }
}
/** Gets the 0-orbit around a node at the boundary
//------------------------------------------------------------------------------------------------
/** Gets the 0-orbit around a node at the boundary
* *
* \param dart * \param aDart
* A dart (CCW or CW) positioned at a \e boundary \e node and at a \e boundary \e edge. * A dart (CCW or CW) positioned at a \e boundary \e node and at a \e boundary \e edge.
* *
* \retval orbit * \retval orbit
...@@ -1178,32 +1173,33 @@ private: ...@@ -1178,32 +1173,33 @@ private:
* in the sequence. * in the sequence.
* *
* \require * \require
* - DartListType::push_back (DartType&) * - DART_LIST_TYPE::push_back (DART_TYPE&)
* *
* \note * \note
* - 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
* get_0_orbit_interior * Get0OrbitInterior
*/ */
template <class DartType, class DartListType> template <class DART_TYPE, class DART_LIST_TYPE>
void TriangulationHelper::get_0_orbit_boundary(const DartType& dart, DartListType& orbit) { void TRIANGULATION_HELPER::Get0OrbitBoundary( const DART_TYPE& aDart, DART_LIST_TYPE& aOrbit )
{
DartType dart_prev; DART_TYPE dart_prev;
DartType d_iter = dart; DART_TYPE d_iter = aDart;
do {
orbit.push_back(d_iter);
d_iter.alpha1();
dart_prev = d_iter;
d_iter.alpha2();
} while (d_iter != dart_prev);
orbit.push_back(d_iter); // the last one with opposite orientation do
{
aOrbit.push_back( d_iter );
d_iter.Alpha1();
dart_prev = d_iter;
d_iter.Alpha2();
} }
while( d_iter != dart_prev );
aOrbit.push_back( d_iter ); // the last one with opposite orientation
}
//------------------------------------------------------------------------------------------------ /** Checks if the two darts belong to the same 0-orbit, i.e.,
/** Checks if the two darts belong to the same 0-orbit, i.e.,
* if they share a node. * if they share a node.
* \e d1 and/or \e d2 can be CCW or CW. * \e d1 and/or \e d2 can be CCW or CW.
* *
...@@ -1213,141 +1209,140 @@ private: ...@@ -1213,141 +1209,140 @@ private:
* node and a faster version is needed, the user should implement his/her * node and a faster version is needed, the user should implement his/her
* own version.) * own version.)
*/ */
template <class DartType> template <class DART_TYPE>
bool TriangulationHelper::same_0_orbit(const DartType& d1, const DartType& d2) { bool TRIANGULATION_HELPER::Same0Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 )
{
// Two copies of the same dart // Two copies of the same dart
DartType d_iter = d2; DART_TYPE d_iter = aD2;
DartType d_end = d2; DART_TYPE d_end = aD2;
if (isBoundaryNode(d_iter)) { if( isBoundaryNode( d_iter ) )
{
// position at both boundary edges // position at both boundary edges
positionAtNextBoundaryEdge(d_iter); PositionAtNextBoundaryEdge( d_iter );
d_end.alpha1(); d_end.Alpha1();
positionAtNextBoundaryEdge(d_end); PositionAtNextBoundaryEdge( d_end );
} }
for (;;) { for( ;; )
if (d_iter == d1) {
if( d_iter == aD1 )
return true; return true;
d_iter.alpha1();
if (d_iter == d1) d_iter.Alpha1();
if( d_iter == aD1 )
return true; return true;
d_iter.alpha2();
if (d_iter == d_end) d_iter.Alpha2();
if( d_iter == d_end )
break; break;
} }
return false; return false;
} }
/** Checks if the two darts belong to the same 1-orbit, i.e.,
//------------------------------------------------------------------------------------------------
/** Checks if the two darts belong to the same 1-orbit, i.e.,
* if they share an edge. * if they share an edge.
* \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 DART_TYPE>
bool TriangulationHelper::same_1_orbit(const DartType& d1, const DartType& d2) { bool TRIANGULATION_HELPER::Same1Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 )
{
DART_TYPE d_iter = aD2;
DartType d_iter = d2;
// (Also works at the boundary) // (Also works at the boundary)
if (d_iter == d1 || d_iter.alpha0() == d1 || d_iter.alpha2() == d1 || d_iter.alpha0() == d1) return ( d_iter == aD1 || d_iter.Alpha0() == aD1 ||
return true; d_iter.Alpha2() == aD1 || d_iter.Alpha0() == aD1 );
return false; }
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
/** Checks if the two darts belong to the same 2-orbit, i.e., /** Checks if the two darts belong to the same 2-orbit, i.e.,
* if they lie in the same triangle. * if they lie in the same triangle.
* \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 DART_TYPE>
bool TriangulationHelper::same_2_orbit(const DartType& d1, const DartType& d2) { bool TRIANGULATION_HELPER::Same2Orbit( const DART_TYPE& aD1, const DART_TYPE& aD2 )
{
DartType d_iter = d2; DART_TYPE d_iter = aD2;
if (d_iter == d1 || d_iter.alpha0() == d1 ||
d_iter.alpha1() == d1 || d_iter.alpha0() == d1 ||
d_iter.alpha1() == d1 || d_iter.alpha0() == d1)
return true;
return false;
}
//------------------------------------------------------------------------------------------------ return ( d_iter == aD1 || d_iter.Alpha0() == aD1 || d_iter.Alpha1() == aD1 ||
// Private/Hidden function d_iter.Alpha0() == aD1 || d_iter.Alpha1() == aD1 || d_iter.Alpha0() == aD1 );
template <class TraitsType, class DartType> }
bool TriangulationHelper::degenerateTriangle(const DartType& dart) {
// Private/Hidden function
template <class TRAITS_TYPE, class DART_TYPE>
bool TRIANGULATION_HELPER::degenerateTriangle( const DART_TYPE& aDart )
{
// Check if triangle is degenerate // Check if triangle is degenerate
// Assumes CCW dart // Assumes CCW dart
DartType d1 = dart; DART_TYPE d1 = aDart;
DartType d2 = d1; DART_TYPE d2 = d1;
d2.alpha1(); d2.Alpha1();
if (TraitsType::crossProduct2d(d1,d2) == 0)
return true;
return false;
}
return ( TRAITS_TYPE::CrossProduct2D( d1, d2 ) == 0 );
}
//------------------------------------------------------------------------------------------------ /** Checks if the edge associated with \e dart is swappable, i.e., if the edge
/** Checks if the edge associated with \e dart is swappable, i.e., if the edge
* is a diagonal in a \e strictly convex (or convex) quadrilateral. * is a diagonal in a \e strictly convex (or convex) quadrilateral.
* *
* \param allowDegeneracy * \param aAllowDegeneracy
* If set to true, the function will also return true if the numerical calculations * If set to true, the function will also return true if the numerical calculations
* indicate that the quadrilateral is convex only, and not necessarily strictly * indicate that the quadrilateral is convex only, and not necessarily strictly
* convex. * convex.
* *
* \require * \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (Dart&, Dart&) * - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (Dart&, Dart&)
*/ */
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
bool TriangulationHelper::swappableEdge(const DartType& dart, bool allowDegeneracy) { bool TRIANGULATION_HELPER::SwappableEdge( const DART_TYPE& aDart, bool aAllowDegeneracy )
{
// How "safe" is it? // How "safe" is it?
if (isBoundaryEdge(dart)) if( IsBoundaryEdge( aDart ) )
return false; return false;
// "angles" are at the diagonal // "angles" are at the diagonal
DartType d1 = dart; DART_TYPE d1 = aDart;
d1.alpha2().alpha1(); d1.Alpha2().Alpha1();
DartType d2 = dart; DART_TYPE d2 = aDart;
d2.alpha1(); d2.Alpha1();
if (allowDegeneracy) {
if (TraitsType::crossProduct2d(d1,d2) < 0.0) if( aAllowDegeneracy )
{
if( TRAITS_TYPE::CrossProduct2D( d1, d2 ) < 0.0 )
return false; return false;
} }
else { else
if (TraitsType::crossProduct2d(d1,d2) <= 0.0) {
if( TRAITS_TYPE::CrossProduct2D( d1, d2 ) <= 0.0 )
return false; return false;
} }
// Opposite side (still angle at the diagonal) // Opposite side (still angle at the diagonal)
d1 = dart; d1 = aDart;
d1.alpha0(); d1.Alpha0();
d2 = d1; d2 = d1;
d1.alpha1(); d1.Alpha1();
d2.alpha2().alpha1(); d2.Alpha2().Alpha1();
if (allowDegeneracy) { if( aAllowDegeneracy )
if (TraitsType::crossProduct2d(d1,d2) < 0.0) {
if( TRAITS_TYPE::CrossProduct2D( d1, d2 ) < 0.0 )
return false; return false;
} }
else { else
if (TraitsType::crossProduct2d(d1,d2) <= 0.0) {
if( TRAITS_TYPE::CrossProduct2D( d1, d2 ) <= 0.0 )
return false; return false;
} }
return true;
}
return true;
}
//------------------------------------------------------------------------------------------------ /** Given a \e dart, CCW or CW, positioned in a 0-orbit at the boundary of a tessellation.
/** Given a \e dart, CCW or CW, positioned in a 0-orbit at the boundary of a tessellation.
* Position \e dart at a boundary edge in the same 0-orbit.\n * Position \e dart at a boundary edge in the same 0-orbit.\n
* If the given \e dart is CCW, \e dart is positioned at the left boundary edge * If the given \e dart is CCW, \e dart is positioned at the left boundary edge
* and will be CW.\n * and will be CW.\n
...@@ -1358,59 +1353,66 @@ private: ...@@ -1358,59 +1353,66 @@ private:
* - The given \e dart must have a source node at the boundary, otherwise an * - The given \e dart must have a source node at the boundary, otherwise an
* infinit loop occurs. * infinit loop occurs.
*/ */
template <class DartType> template <class DART_TYPE>
void TriangulationHelper::positionAtNextBoundaryEdge(DartType& dart) { void TRIANGULATION_HELPER::PositionAtNextBoundaryEdge( DART_TYPE& aDart )
{
DartType dart_prev; DART_TYPE dart_prev;
// If alpha2(d)=d, then boundary // If alpha2(d)=d, then boundary
//old convention: dart.alpha0(); //old convention: dart.Alpha0();
do { do
dart.alpha1(); {
dart_prev = dart; aDart.Alpha1();
dart.alpha2(); dart_prev = aDart;
} while (dart != dart_prev); aDart.Alpha2();
} }
while( aDart != dart_prev );
}
/** Checks if the boundary of a triangulation is convex.
//------------------------------------------------------------------------------------------------
/** Checks if the boundary of a triangulation is convex.
* *
* \param dart * \param dart
* A CCW dart at the boundary of the triangulation * A CCW dart at the boundary of the m_triangulation
* *
* \require * \require
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (const Dart&, const Dart&) * - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (const Dart&, const Dart&)
*/ */
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
bool TriangulationHelper::convexBoundary(const DartType& dart) { bool TRIANGULATION_HELPER::ConvexBoundary( const DART_TYPE& aDart )
{
std::list<DartType> blist; std::list<DART_TYPE> blist;
getBoundary(dart, blist); getBoundary( aDart, blist );
int no; int no;
no = (int)blist.size(); no = (int) blist.size();
typename std::list<DartType>::const_iterator bit = blist.begin(); typename std::list<DART_TYPE>::const_iterator bit = blist.begin();
DartType d1 = *bit; DART_TYPE d1 = *bit;
++bit; ++bit;
DartType d2; DART_TYPE d2;
bool convex = true; bool convex = true;
for (; bit != blist.end(); ++bit) {
for( ; bit != blist.end(); ++bit )
{
d2 = *bit; d2 = *bit;
double crossProd = TraitsType::crossProduct2d(d1, d2); double crossProd = TRAITS_TYPE::CrossProduct2D( d1, d2 );
if (crossProd < 0.0) {
if( crossProd < 0.0 )
{
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl; //cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
convex = false; convex = false;
return convex; return convex;
} }
d1 = d2; d1 = d2;
} }
// Check the last angle // Check the last angle
d2 = *blist.begin(); d2 = *blist.begin();
double crossProd = TraitsType::crossProduct2d(d1, d2); double crossProd = TRAITS_TYPE::CrossProduct2D( d1, d2 );
if (crossProd < 0.0) {
if( crossProd < 0.0 )
{
//cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl; //cout << "!!! Boundary is NOT convex: crossProd = " << crossProd << endl;
convex = false; convex = false;
} }
...@@ -1419,46 +1421,41 @@ private: ...@@ -1419,46 +1421,41 @@ private:
// cout << "\n---> Boundary is convex\n" << endl; // cout << "\n---> Boundary is convex\n" << endl;
//cout << endl; //cout << endl;
return convex; return convex;
} }
//@} // End of Topological and Geometric Queries Group
//------------------------------------------------------------------------------------------------
// ------------------------ Utilities for Delaunay Triangulation Group --------------------------
//------------------------------------------------------------------------------------------------
/** @name Utilities for Delaunay Triangulation */ //@} // End of Topological and Geometric Queries Group
//@{
//------------------------------------------------------------------------------------------------ /** @name Utilities for Delaunay Triangulation */
/** Optimizes the edges in the given sequence according to the //@{
//------------------------------------------------------------------------------------------------
/** Optimizes the edges in the given sequence according to the
* \e Delaunay criterion, i.e., such that the edge will fullfill the * \e Delaunay criterion, i.e., such that the edge will fullfill the
* \e circumcircle criterion (or equivalently the \e MaxMin * \e circumcircle criterion (or equivalently the \e MaxMin
* angle criterion) with respect to the quadrilaterals where * angle criterion) with respect to the quadrilaterals where
* they are diagonals. * they are diagonals.
* *
* \param elist * \param aElist
* The sequence of edges * The sequence of edges
* *
* \require * \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType& \e dart)\n * - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as * \b Note: Must be implemented such that \e dart 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
* *
* \using * \using
* - swapTestDelaunay * - swapTestDelaunay
*/ */
template <class TraitsType, class DartType, class DartListType> template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
void TriangulationHelper::optimizeDelaunay(DartListType& elist) { void TRIANGULATION_HELPER::OptimizeDelaunay( DART_LIST_TYPE& aElist )
optimizeDelaunay<TraitsType, DartType, DartListType>(elist, elist.end()); {
} OptimizeDelaunay<TRAITS_TYPE, DART_TYPE, DART_LIST_TYPE>( aElist, aElist.end() );
}
//------------------------------------------------------------------------------------------------
template <class TraitsType, class DartType, class DartListType>
void TriangulationHelper::optimizeDelaunay(DartListType& elist, const typename DartListType::iterator end) {
//------------------------------------------------------------------------------------------------
template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
void TRIANGULATION_HELPER::OptimizeDelaunay( DART_LIST_TYPE& aElist,
const typename DART_LIST_TYPE::iterator aEnd )
{
// CCW darts // CCW darts
// Optimize here means Delaunay, but could be any criterion by // Optimize here means Delaunay, but could be any criterion by
// requiring a "should swap" in the traits class, or give // requiring a "should swap" in the traits class, or give
...@@ -1475,15 +1472,15 @@ private: ...@@ -1475,15 +1472,15 @@ private:
// (A vector instead of a list may be better.) // (A vector instead of a list may be better.)
// First check that elist is not empty // First check that elist is not empty
if (elist.empty()) if( aElist.empty() )
return; return;
// Avoid cycling by more extensive circumcircle test // Avoid cycling by more extensive circumcircle test
bool cycling_check = true; bool cycling_check = true;
bool optimal = false; bool optimal = false;
typename DartListType::iterator it; typename DART_LIST_TYPE::iterator it;
typename DartListType::iterator end_opt = end; typename DART_LIST_TYPE::iterator end_opt = aEnd;
// Hmm... The following code is trying to derefence an iterator that may // Hmm... The following code is trying to derefence an iterator that may
// be invalid. This may lead to debug error on Windows, so we comment out // be invalid. This may lead to debug error on Windows, so we comment out
...@@ -1491,52 +1488,53 @@ private: ...@@ -1491,52 +1488,53 @@ private:
// problems... // problems...
// //
// last_opt is passed the end of the "active list" // last_opt is passed the end of the "active list"
//typename DartListType::iterator end_opt; //typename DART_LIST_TYPE::iterator end_opt;
//if (*end != NULL) //if (*end != NULL)
// end_opt = end; // end_opt = end;
//else //else
// end_opt = elist.end(); // end_opt = elist.end();
while(!optimal) { while( !optimal )
{
optimal = true; optimal = true;
for (it = elist.begin(); it != end_opt; ++it) { for( it = aElist.begin(); it != end_opt; ++it )
if (swapTestDelaunay<TraitsType>(*it, cycling_check)) { {
if( SwapTestDelaunay<TRAITS_TYPE>( *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)
swapEdgeInList<TraitsType, DartType>(it, elist); SwapEdgeInList<TRAITS_TYPE, DART_TYPE>( it, aElist );
optimal = false; optimal = false;
} // end if should swap } // end if should swap
} // end for } // end for
} // end pass } // end pass
} }
//------------------------------------------------------------------------------------------------ /** Checks if the edge associated with \e dart should be swapped according
/** Checks if the edge associated with \e dart should be swapped according
* to the \e Delaunay criterion, i.e., the \e circumcircle criterion (or * to the \e Delaunay criterion, i.e., the \e circumcircle criterion (or
* equivalently the \e MaxMin angle criterion). * equivalently the \e MaxMin angle criterion).
* *
* \param cycling_check * \param aCyclingCheck
* Must be set to \c true when used in connection with optimization algorithms, * Must be set to \c true when used in connection with optimization algorithms,
* e.g., optimizeDelaunay. This will avoid cycling and infinite loops in nearly * e.g., OptimizeDelaunay. This will avoid cycling and infinite loops in nearly
* neutral cases. * neutral cases.
* *
* \require * \require
* - \ref hed::TTLtraits::scalarProduct2d "TraitsType::scalarProduct2d" (DartType&, DartType&) * - \ref hed::TTLtraits::ScalarProduct2D "TRAITS_TYPE::ScalarProduct2D" (DART_TYPE&, DART_TYPE&)
* - \ref hed::TTLtraits::crossProduct2d "TraitsType::crossProduct2d" (DartType&, DartType&) * - \ref hed::TTLtraits::CrossProduct2D "TRAITS_TYPE::CrossProduct2D" (DART_TYPE&, DART_TYPE&)
*/ */
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
#if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER #if ((_MSC_VER > 0) && (_MSC_VER < 1300))//#ifdef _MSC_VER
bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check = false) const { bool TRIANGULATION_HELPER::SwapTestDelaunay(const DART_TYPE& aDart, bool aCyclingCheck = false) const
{
#else #else
bool TriangulationHelper::swapTestDelaunay(const DartType& dart, bool cycling_check) const { bool TRIANGULATION_HELPER::SwapTestDelaunay( const DART_TYPE& aDart, bool aCyclingCheck ) 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
// their algorithm insure numerical stability, but experiments show // their algorithm insure numerical stability, but experiments show
// that this is not correct for neutral, or almost neutral cases. // that this is not correct for neutral, or almost neutral cases.
...@@ -1544,41 +1542,44 @@ private: ...@@ -1544,41 +1542,44 @@ private:
// cycling and infinit loops when used in connection with LOP algorithms; // cycling and infinit loops when used in connection with LOP algorithms;
// see the comments below. // see the comments below.
typedef typename TraitsType::real_type real_type; typedef typename TRAITS_TYPE::REAL_TYPE REAL_TYPE;
if (isBoundaryEdge(dart)) if( IsBoundaryEdge( aDart ) )
return false; return false;
DartType v11 = dart; DART_TYPE v11 = aDart;
v11.alpha1().alpha0(); v11.Alpha1().Alpha0();
DartType v12 = v11; DART_TYPE v12 = v11;
v12.alpha1(); v12.Alpha1();
DartType v22 = dart; DART_TYPE v22 = aDart;
v22.alpha2().alpha1().alpha0(); v22.Alpha2().Alpha1().Alpha0();
DartType v21 = v22; DART_TYPE v21 = v22;
v21.alpha1(); v21.Alpha1();
real_type cos1 = TraitsType::scalarProduct2d(v11,v12); REAL_TYPE cos1 = TRAITS_TYPE::ScalarProduct2D( v11, v12 );
real_type cos2 = TraitsType::scalarProduct2d(v21,v22); REAL_TYPE cos2 = TRAITS_TYPE::ScalarProduct2D( v21, v22 );
// "Angles" are opposite to the diagonal. // "Angles" are opposite to the diagonal.
// The diagonals should be swapped iff (t1+t2) .gt. 180 // The diagonals should be swapped iff (t1+t2) .gt. 180
// degrees. The following two tests insure numerical // degrees. The following two tests insure numerical
// stability according to Cline & Renka. But experiments show // stability according to Cline & Renka. But experiments show
// that cycling may still happen; see the aditional test below. // that cycling may still happen; see the aditional test below.
if (cos1 >= 0 && cos2 >= 0) // both angles are grater or equual 90 if( cos1 >= 0 && cos2 >= 0 ) // both angles are grater or equual 90
return false; return false;
if (cos1 < 0 && cos2 < 0) // both angles are less than 90
if( cos1 < 0 && cos2 < 0 ) // both angles are less than 90
return true; return true;
real_type sin1 = TraitsType::crossProduct2d(v11,v12); REAL_TYPE sin1 = TRAITS_TYPE::CrossProduct2D( v11, v12 );
real_type sin2 = TraitsType::crossProduct2d(v21,v22); REAL_TYPE sin2 = TRAITS_TYPE::CrossProduct2D( v21, v22 );
real_type sin12 = sin1*cos2 + cos1*sin2; REAL_TYPE sin12 = sin1 * cos2 + cos1 * sin2;
if (sin12 >= 0) // equality represents a neutral case
if( sin12 >= 0 ) // equality represents a neutral case
return false; return false;
if (cycling_check) { if( aCyclingCheck )
{
// situation so far is sin12 < 0. Test if this also // situation so far is sin12 < 0. Test if this also
// happens for the swapped edge. // happens for the swapped edge.
...@@ -1587,108 +1588,111 @@ private: ...@@ -1587,108 +1588,111 @@ private:
// in neutral cases, or almost neutral cases, it may happen that // in neutral cases, or almost neutral cases, it may happen that
// the swapped edge may again be found to be not Delaunay and thus // the swapped edge may again be found to be not Delaunay and thus
// be swapped if we return true here. This may lead to cycling and // be swapped if we return true here. This may lead to cycling and
// an infinte loop when used, e.g., in connection with optimizeDelaunay. // an infinte loop when used, e.g., in connection with OptimizeDelaunay.
// //
// In an attempt to avoid this we test if the swapped edge will // In an attempt to avoid this we test if the swapped edge will
// also be found to be not Delaunay by repeating the last test above // also be found to be not Delaunay by repeating the last test above
// for the swapped edge. // for the swapped edge.
// We now rely on the general requirement for TraitsType::swapEdge which // We now rely on the general requirement for TRAITS_TYPE::swapEdge which
// should deliver CCW dart back in "the same position"; see the general // should deliver CCW dart back in "the same position"; see the general
// description. This will insure numerical stability as the next calculation // description. This will insure numerical stability as the next calculation
// is the same as if this function was called again with the swapped edge. // is the same as if this function was called again with the swapped edge.
// Cycling is thus impossible provided that the initial tests above does // Cycling is thus impossible provided that the initial tests above does
// not result in ambiguity (and they should probably not do so). // not result in ambiguity (and they should probably not do so).
v11.alpha0(); v11.Alpha0();
v12.alpha0(); v12.Alpha0();
v21.alpha0(); v21.Alpha0();
v22.alpha0(); v22.Alpha0();
// as if the edge was swapped/rotated CCW // as if the edge was swapped/rotated CCW
cos1 = TraitsType::scalarProduct2d(v22,v11); cos1 = TRAITS_TYPE::ScalarProduct2D( v22, v11 );
cos2 = TraitsType::scalarProduct2d(v12,v21); cos2 = TRAITS_TYPE::ScalarProduct2D( v12, v21 );
sin1 = TraitsType::crossProduct2d(v22,v11); sin1 = TRAITS_TYPE::CrossProduct2D( v22, v11 );
sin2 = TraitsType::crossProduct2d(v12,v21); sin2 = TRAITS_TYPE::CrossProduct2D( v12, v21 );
sin12 = sin1*cos2 + cos1*sin2; sin12 = sin1 * cos2 + cos1 * sin2;
if (sin12 < 0) {
if( sin12 < 0 )
{
// A neutral case, but the tests above lead to swapping // A neutral case, but the tests above lead to swapping
return false; return false;
} }
} }
return true; return true;
} }
//-----------------------------------------------------------------------
//----------------------------------------------------------------------- //
// // x
// x //" / \ "
//" / \ " // / | \ Darts:
// / | \ Darts: //oe2 / | \ oe2 = oppEdge2
//oe2 / | \ oe2 = oppEdge2 // x....|....x
// x....|....x // \ d| d/ d = diagonal (input and output)
// \ d| d/ d = diagonal (input and output) // \ | /
// \ | / // oe1 \ / oe1 = oppEdge1
// oe1 \ / oe1 = oppEdge1 // x
// x //
// //-----------------------------------------------------------------------
//----------------------------------------------------------------------- /** Recursively swaps edges in the triangulation according to the \e Delaunay criterion.
/** Recursively swaps edges in the triangulation according to the \e Delaunay criterion. *
* * \param aDiagonal
* \param diagonal
* A CCW dart representing the edge where the recursion starts from. * A CCW dart representing the edge where the recursion starts from.
* *
* \require * \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType&)\n * - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE&)\n
* \b Note: Must be implemented such that the darts outside the quadrilateral * \b Note: Must be implemented such that the darts outside the quadrilateral
* are not affected by the swap. * are not affected by the swap.
* *
* \using * \using
* - Calls itself recursively * - Calls itself recursively
*/ */
template <class TraitsType, class DartType> template <class TRAITS_TYPE, class DART_TYPE>
void TriangulationHelper::recSwapDelaunay(DartType& diagonal) { void TRIANGULATION_HELPER::RecSwapDelaunay( DART_TYPE& aDiagonal )
{
if (!swapTestDelaunay<TraitsType>(diagonal)) if( !SwapTestDelaunay<TRAITS_TYPE>( aDiagonal ) )
// ??? 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; DART_TYPE oppEdge1 = aDiagonal;
oppEdge1.alpha1(); oppEdge1.Alpha1();
bool b1; bool b1;
if (isBoundaryEdge(oppEdge1))
if( IsBoundaryEdge( oppEdge1 ) )
b1 = true; b1 = true;
else { else
{
b1 = false; b1 = false;
oppEdge1.alpha2(); oppEdge1.Alpha2();
} }
DART_TYPE oppEdge2 = aDiagonal;
DartType oppEdge2 = diagonal; oppEdge2.Alpha0().Alpha1().Alpha0();
oppEdge2.alpha0().alpha1().alpha0();
bool b2; bool b2;
if (isBoundaryEdge(oppEdge2))
if( IsBoundaryEdge( oppEdge2 ) )
b2 = true; b2 = true;
else { else
{
b2 = false; b2 = false;
oppEdge2.alpha2(); oppEdge2.Alpha2();
} }
// Swap the given diagonal // Swap the given diagonal
triangulation.swapEdge(diagonal); m_triangulation.swapEdge( aDiagonal );
if (!b1) if( !b1 )
recSwapDelaunay<TraitsType>(oppEdge1); RecSwapDelaunay<TRAITS_TYPE>( oppEdge1 );
if (!b2)
recSwapDelaunay<TraitsType>(oppEdge2);
}
if( !b2 )
RecSwapDelaunay<TRAITS_TYPE>( oppEdge2 );
}
//------------------------------------------------------------------------------------------------ /** 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 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
...@@ -1698,7 +1702,7 @@ private: ...@@ -1698,7 +1702,7 @@ private:
* triangulation. * triangulation.
* *
* \require * \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType& \e dart)\n * - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as * \b Note: Must be implemented such that \e dart 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
* *
...@@ -1708,13 +1712,15 @@ private: ...@@ -1708,13 +1712,15 @@ private:
* at the node that is given as input. * at the node that is given as input.
* *
* \see * \see
* swapEdgesAwayFromBoundaryNode * SwapEdgesAwayFromBoundaryNode
*/ */
template <class TraitsType, class DartType, class ListType> template <class TRAITS_TYPE, class DART_TYPE, class LIST_TYPE>
void TriangulationHelper::swapEdgesAwayFromInteriorNode(DartType& dart, ListType& swapped_edges) { void TRIANGULATION_HELPER::SwapEdgesAwayFromInteriorNode( DART_TYPE& aDart,
LIST_TYPE& aSwappedEdges )
{
// Same iteration as in fixEdgesAtCorner, but not boundary // Same iteration as in fixEdgesAtCorner, but not boundary
DartType dnext = dart; DART_TYPE dnext = aDart;
// Allow degeneracy, otherwise we might end up with degree=4. // Allow degeneracy, otherwise we might end up with degree=4.
// For example, the reverse operation of inserting a point on an // For example, the reverse operation of inserting a point on an
...@@ -1725,52 +1731,55 @@ private: ...@@ -1725,52 +1731,55 @@ private:
// infinite loop with degree > 3. // infinite loop with degree > 3.
bool allowDegeneracy = true; bool allowDegeneracy = true;
int degree = getDegreeOfNode(dart); int degree = getDegreeOfNode( aDart );
DartType d_iter; DART_TYPE d_iter;
while (degree > 3) {
while( degree > 3 )
{
d_iter = dnext; d_iter = dnext;
dnext.alpha1().alpha2(); dnext.Alpha1().Alpha2();
if (swappableEdge<TraitsType>(d_iter, allowDegeneracy)) { if( SwappableEdge<TRAITS_TYPE>( d_iter, allowDegeneracy ) )
triangulation.swapEdge(d_iter); // swap the edge away {
m_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
DartType swapped_edge = d_iter; // it was delivered back DART_TYPE swapped_edge = d_iter; // it was delivered back
swapped_edge.alpha2().alpha0(); // CCW (if not at boundary) swapped_edge.Alpha2().Alpha0(); // CCW (if not at boundary)
swapped_edges.push_back(swapped_edge); aSwappedEdges.push_back( swapped_edge );
degree--; degree--;
} }
} }
// Output, incident to the node
dart = dnext;
}
// Output, incident to the node
aDart = dnext;
}
//------------------------------------------------------------------------------------------------ /** 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 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
* *
* \require * \require
* - \ref hed::TTLtraits::swapEdge "TraitsType::swapEdge" (DartType& \e dart)\n * - \ref hed::TTLtraits::swapEdge "TRAITS_TYPE::swapEdge" (DART_TYPE& \e dart)\n
* \b Note: Must be implemented such that \e dart is delivered back in a position as * \b Note: Must be implemented such that \e dart 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
* *
* \par Assumes: * \par Assumes:
* - 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 m_triangulation.
* *
* \see * \see
* swapEdgesAwayFromInteriorNode * SwapEdgesAwayFromInteriorNode
*/ */
template <class TraitsType, class DartType, class ListType> template <class TRAITS_TYPE, class DART_TYPE, class LIST_TYPE>
void TriangulationHelper::swapEdgesAwayFromBoundaryNode(DartType& dart, ListType& swapped_edges) { void TRIANGULATION_HELPER::SwapEdgesAwayFromBoundaryNode( DART_TYPE& aDart,
LIST_TYPE& aSwappedEdges )
{
// 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
// when swapping to the boundary. // when swapping to the boundary.
...@@ -1783,94 +1792,104 @@ private: ...@@ -1783,94 +1792,104 @@ private:
//int degree = getDegreeOfNode(dart); //int degree = getDegreeOfNode(dart);
passes: passes:
// Swap swappable edges that radiate from the node away // Swap swappable edges that radiate from the node away
DartType d_iter = dart; // ???? can simply use dart DART_TYPE d_iter = aDart; // ???? can simply use dart
d_iter.alpha1().alpha2(); // first not at boundary d_iter.Alpha1().Alpha2(); // first not at boundary
DartType d_next = d_iter; DART_TYPE d_next = d_iter;
bool bend = false; bool bend = false;
bool swapped_next_to_boundary = false; bool swapped_next_to_boundary = false;
bool swapped_in_pass = false; bool swapped_in_pass = false;
bool allowDegeneracy; // = true; bool allowDegeneracy; // = true;
DartType tmp1, tmp2; DART_TYPE tmp1, tmp2;
while (!bend) { while( !bend )
{
d_next.Alpha1().Alpha2();
d_next.alpha1().alpha2(); if( 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,
// degenerate triangles must be allowed // degenerate triangles must be allowed
// (they will be removed when used in connection with removeBoundaryNode) // (they will be removed when used in connection with RemoveBoundaryNode)
tmp1 = d_iter; tmp1.alpha1(); tmp1 = d_iter;
tmp2 = d_iter; tmp2.alpha2().alpha1(); // don't bother with boundary (checked later) tmp1.Alpha1();
tmp2 = d_iter;
tmp2.Alpha2().Alpha1(); // don't bother with boundary (checked later)
if (isBoundaryEdge(tmp1) && isBoundaryEdge(tmp2)) if( IsBoundaryEdge( tmp1 ) && IsBoundaryEdge( tmp2 ) )
allowDegeneracy = true; allowDegeneracy = true;
else else
allowDegeneracy = false; allowDegeneracy = false;
if (swappableEdge<TraitsType>(d_iter, allowDegeneracy)) { if( SwappableEdge<TRAITS_TYPE>( d_iter, allowDegeneracy ) )
triangulation.swapEdge(d_iter); {
m_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
// other swapps // other swapps
DartType swapped_edge = d_iter; // it was delivered back DART_TYPE swapped_edge = d_iter; // it was delivered back
swapped_edge.alpha2().alpha0(); // CCW swapped_edge.Alpha2().Alpha0(); // CCW
swapped_edges.push_back(swapped_edge); aSwappedEdges.push_back( swapped_edge );
//degree--; // if degree is 2, or bend=true, we are done //degree--; // if degree is 2, or bend=true, we are done
swapped_in_pass = true; swapped_in_pass = true;
if (bend) if( bend )
swapped_next_to_boundary = true; swapped_next_to_boundary = true;
} }
if (!bend)
if( !bend )
d_iter = d_next; d_iter = d_next;
} }
// Deliver a dart as output in the same position as the incoming dart // Deliver a dart as output in the same position as the incoming dart
if (swapped_next_to_boundary) { if( swapped_next_to_boundary )
{
// Assume that "swapping is CCW and dart is preserved in the same position // Assume that "swapping is CCW and dart is preserved in the same position
d_iter.alpha1().alpha0().alpha1(); // CW and see below d_iter.Alpha1().Alpha0().Alpha1(); // CW and see below
} }
else { else
d_iter.alpha1(); // CW and see below {
d_iter.Alpha1(); // CW and see below
} }
positionAtNextBoundaryEdge(d_iter); // CCW PositionAtNextBoundaryEdge( d_iter ); // CCW
dart = d_iter; // for next pass or output aDart = d_iter; // for next pass or output
// If a dart was swapped in this iteration we must run it more // If a dart was swapped in this iteration we must run it more
if (swapped_in_pass) if( swapped_in_pass )
goto passes; goto passes;
} }
//------------------------------------------------------------------------------------------------ /** Swap the the edge associated with iterator \e it and update affected darts
/** Swap the the edge associated with iterator \e it and update affected darts
* in \e elist accordingly. * in \e elist accordingly.
* The darts affected by the swap are those in the same quadrilateral. * The darts affected by the swap are those in the same quadrilateral.
* Thus, if one want to preserve one or more of these darts on should * Thus, if one want to preserve one or more of these darts on should
* keep them in \e elist. * keep them in \e elist.
*/ */
template <class TraitsType, class DartType, class DartListType> template <class TRAITS_TYPE, class DART_TYPE, class DART_LIST_TYPE>
void TriangulationHelper::swapEdgeInList(const typename DartListType::iterator& it, DartListType& elist) { void TRIANGULATION_HELPER::SwapEdgeInList( const typename DART_LIST_TYPE::iterator& aIt,
DART_LIST_TYPE& aElist )
typename DartListType::iterator it1, it2, it3, it4; {
DartType dart(*it);
//typename TraitsType::DartType d1 = dart; d1.alpha2().alpha1(); typename DART_LIST_TYPE::iterator it1, it2, it3, it4;
//typename TraitsType::DartType d2 = d1; d2.alpha0().alpha1(); DART_TYPE dart( *aIt );
//typename TraitsType::DartType d3 = dart; d3.alpha0().alpha1();
//typename TraitsType::DartType d4 = d3; d4.alpha0().alpha1(); //typename TRAITS_TYPE::DART_TYPE d1 = dart; d1.Alpha2().Alpha1();
DartType d1 = dart; d1.alpha2().alpha1(); //typename TRAITS_TYPE::DART_TYPE d2 = d1; d2.Alpha0().Alpha1();
DartType d2 = d1; d2.alpha0().alpha1(); //typename TRAITS_TYPE::DART_TYPE d3 = dart; d3.Alpha0().Alpha1();
DartType d3 = dart; d3.alpha0().alpha1(); //typename TRAITS_TYPE::DART_TYPE d4 = d3; d4.Alpha0().Alpha1();
DartType d4 = d3; d4.alpha0().alpha1(); DART_TYPE d1 = dart;
d1.Alpha2().Alpha1();
DART_TYPE d2 = d1;
d2.Alpha0().Alpha1();
DART_TYPE d3 = dart;
d3.Alpha0().Alpha1();
DART_TYPE d4 = d3;
d4.Alpha0().Alpha1();
// Find pinters to the darts that may change. // Find pinters to the darts that may change.
// ??? Note, this is not very efficient since we must use find, which is O(N), // ??? Note, this is not very efficient since we must use find, which is O(N),
...@@ -1881,37 +1900,49 @@ passes: ...@@ -1881,37 +1900,49 @@ passes:
// - sould we use another container type or, // - sould we use another container type or,
// - erase them and reinsert? // - erase them and reinsert?
// - or use two lists? // - or use two lists?
it1 = find(elist.begin(), elist.end(), d1); it1 = find( aElist.begin(), aElist.end(), d1 );
it2 = find(elist.begin(), elist.end(), d2); it2 = find( aElist.begin(), aElist.end(), d2 );
it3 = find(elist.begin(), elist.end(), d3); it3 = find( aElist.begin(), aElist.end(), d3 );
it4 = find(elist.begin(), elist.end(), d4); it4 = find( aElist.begin(), aElist.end(), d4 );
triangulation.swapEdge(dart); m_triangulation.swapEdge( dart );
// Update the current dart which may have changed // Update the current dart which may have changed
*it = dart; *aIt = dart;
// Update darts that may have changed again (if they were present) // Update darts that may have changed again (if they were present)
// Note that dart is delivered back after swapping // Note that dart is delivered back after swapping
if (it1 != elist.end()) { if( it1 != aElist.end() )
d1 = dart; d1.alpha1().alpha0(); {
d1 = dart;
d1.Alpha1().Alpha0();
*it1 = d1; *it1 = d1;
} }
if (it2 != elist.end()) {
d2 = dart; d2.alpha2().alpha1(); if( it2 != aElist.end() )
{
d2 = dart;
d2.Alpha2().Alpha1();
*it2 = d2; *it2 = d2;
} }
if (it3 != elist.end()) {
d3 = dart; d3.alpha2().alpha1().alpha0().alpha1(); if( it3 != aElist.end() )
{
d3 = dart;
d3.Alpha2().Alpha1().Alpha0().Alpha1();
*it3 = d3; *it3 = d3;
} }
if (it4 != elist.end()) {
d4 = dart; d4.alpha0().alpha1(); if( it4 != aElist.end() )
{
d4 = dart;
d4.Alpha0().Alpha1();
*it4 = d4; *it4 = d4;
} }
} }
//@} // End of Utilities for Delaunay Triangulation Group //@} // End of Utilities for Delaunay Triangulation Group
}; // End of ttl namespace scope (but other files may also contain functions for ttl) }
// End of ttl namespace scope (but other files may also contain functions for ttl)
#endif // _TTL_H_ #endif // _TTL_H_
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
* Applied Mathematics, Norway. * Applied Mathematics, Norway.
* *
* Contact information: E-mail: tor.dokken@sintef.no * Contact information: E-mail: tor.dokken@sintef.no
* SINTEF ICT, Department of Applied Mathematics, * SINTEF ICT, DeaPArtment of Applied Mathematics,
* P.O. Box 124 Blindern, * P.O. Box 124 Blindern,
* 0314 Oslo, Norway. * 0314 Oslo, Norway.
* *
* This file is part of TTL. * This file is aPArt of TTL.
* *
* TTL is free software: you can redistribute it and/or modify * TTL is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* TTL is distributed in the hope that it will be useful, * TTL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A aPARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public * You should have received a copy of the GNU Affero General Public
...@@ -40,28 +40,22 @@ ...@@ -40,28 +40,22 @@
#ifndef _TTL_UTIL_H_ #ifndef _TTL_UTIL_H_
#define _TTL_UTIL_H_ #define _TTL_UTIL_H_
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#ifdef _MSC_VER #ifdef _MSC_VER
# if _MSC_VER < 1300 # if _MSC_VER < 1300
# include <minmax.h> # include <minmax.h>
# endif # endif
#endif #endif
//using namespace std;
/** \brief Utilities /** \brief Utilities
* *
* This name space contains utility functions for TTL.\n * This name saPAce contains utility functions for TTL.\n
* *
* Point and vector algebra such as scalar product and cross product * Point and vector algebra such as scalar product and cross product
* between vectors are implemented here. * between vectors are implemented here.
* These functions are required by functions in the \ref ttl namespace, * These functions are required by functions in the \ref ttl namesaPAce,
* where they are assumed to be present in the \ref hed::TTLtraits "TTLtraits" class. * where they are assumed to be present in the \ref hed::TTLtraits "TTLtraits" class.
* Thus, the user can call these functions from the traits class. * Thus, the user can call these functions from the traits class.
* For efficiency reasons, the user may consider implementing these * For efficiency reasons, the user may consider implementing these
...@@ -77,51 +71,41 @@ ...@@ -77,51 +71,41 @@
* ttl and \ref api * ttl and \ref api
* *
* \author * \author
* Øyvind Hjelle, oyvindhj@ifi.uio.no * yvind Hjelle, oyvindhj@ifi.uio.no
*/ */
namespace ttl_util
namespace ttl_util { {
/** @name Computational geometry */
//@{
//------------------------------------------------------------------------------------------------ /** Scalar product between two 2D vectors.
// ------------------------------ Computational Geometry Group ----------------------------------
//------------------------------------------------------------------------------------------------
/** @name Computational geometry */
//@{
//------------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors.
* *
* \par Returns: * \aPAr Returns:
* \code * \code
* dx1*dx2 + dy1*dy2 * aDX1*aDX2 + aDY1*aDY2
* \endcode * \endcode
*/ */
template <class real_type> template <class REAL_TYPE>
real_type scalarProduct2d(real_type dx1, real_type dy1, real_type dx2, real_type dy2) { REAL_TYPE ScalarProduct2D( REAL_TYPE aDX1, REAL_TYPE aDY1, REAL_TYPE aDX2, REAL_TYPE aDY2 )
return dx1*dx2 + dy1*dy2; {
} return aDX1 * aDX2 + aDY1 * aDY2;
}
//------------------------------------------------------------------------------------------------ /** Cross product between two 2D vectors. (The z-component of the actual cross product.)
/** Cross product between two 2D vectors. (The z-component of the actual cross product.)
* *
* \par Returns: * \aPAr Returns:
* \code * \code
* dx1*dy2 - dy1*dx2 * aDX1*aDY2 - aDY1*aDX2
* \endcode * \endcode
*/ */
template <class real_type> template <class REAL_TYPE>
real_type crossProduct2d(real_type dx1, real_type dy1, real_type dx2, real_type dy2) { REAL_TYPE CrossProduct2D( REAL_TYPE aDX1, REAL_TYPE aDY1, REAL_TYPE aDX2, REAL_TYPE aDY2 )
return dx1*dy2 - dy1*dx2; {
} return aDX1 * aDY2 - aDY1 * aDX2;
}
//------------------------------------------------------------------------------------------------ /** Returns a positive value if the 2D nodes/points \e aPA, \e aPB, and
/** Returns a positive value if the 2D nodes/points \e pa, \e pb, and * \e aPC occur in counterclockwise order; a negative value if they occur
* \e pc occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear. * in clockwise order; and zero if they are collinear.
* *
* \note * \note
...@@ -129,15 +113,17 @@ namespace ttl_util { ...@@ -129,15 +113,17 @@ namespace ttl_util {
* exact arithmetic schemes by Jonathan Richard Shewchuk. See * exact arithmetic schemes by Jonathan Richard Shewchuk. See
* http://www-2.cs.cmu.edu/~quake/robust.html * http://www-2.cs.cmu.edu/~quake/robust.html
*/ */
template <class real_type> template <class REAL_TYPE>
real_type orient2dfast(real_type pa[2], real_type pb[2], real_type pc[2]) { REAL_TYPE Orient2DFast( REAL_TYPE aPA[2], REAL_TYPE aPB[2], REAL_TYPE aPC[2] )
real_type acx = pa[0] - pc[0]; {
real_type bcx = pb[0] - pc[0]; REAL_TYPE acx = aPA[0] - aPC[0];
real_type acy = pa[1] - pc[1]; REAL_TYPE bcx = aPB[0] - aPC[0];
real_type bcy = pb[1] - pc[1]; REAL_TYPE acy = aPA[1] - aPC[1];
REAL_TYPE bcy = aPB[1] - aPC[1];
return acx * bcy - acy * bcx; return acx * bcy - acy * bcx;
} }
}; // End of ttl_util namespace scope } // namespace ttl_util
#endif // _TTL_UTIL_H_ #endif // _TTL_UTIL_H_
...@@ -68,7 +68,7 @@ bool sortDistance( const RN_NODE_PTR& aOrigin, const RN_NODE_PTR& aNode1, ...@@ -68,7 +68,7 @@ bool sortDistance( const RN_NODE_PTR& aOrigin, const RN_NODE_PTR& aNode1,
bool sortWeight( const RN_EDGE_PTR& aEdge1, const RN_EDGE_PTR& aEdge2 ) bool sortWeight( const RN_EDGE_PTR& aEdge1, const RN_EDGE_PTR& aEdge2 )
{ {
return aEdge1->getWeight() < aEdge2->getWeight(); return aEdge1->GetWeight() < aEdge2->GetWeight();
} }
...@@ -92,7 +92,7 @@ bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ) ...@@ -92,7 +92,7 @@ bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond )
bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode ) bool isEdgeConnectingNode( const RN_EDGE_PTR& aEdge, const RN_NODE_PTR& aNode )
{ {
return aEdge->getSourceNode() == aNode || aEdge->getTargetNode() == aNode; return aEdge->GetSourceNode() == aNode || aEdge->GetTargetNode() == aNode;
} }
...@@ -125,8 +125,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -125,8 +125,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
{ {
RN_EDGE_PTR& dt = *aEdges.begin(); RN_EDGE_PTR& dt = *aEdges.begin();
int srcTag = tags[dt->getSourceNode()]; int srcTag = tags[dt->GetSourceNode()];
int trgTag = tags[dt->getTargetNode()]; int trgTag = tags[dt->GetTargetNode()];
// Check if by adding this edge we are going to join two different forests // Check if by adding this edge we are going to join two different forests
if( srcTag != trgTag ) if( srcTag != trgTag )
...@@ -139,7 +139,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -139,7 +139,7 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
// Move nodes that were marked with old tag to the list marked with the new tag // Move nodes that were marked with old tag to the list marked with the new tag
cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] ); cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] );
if( dt->getWeight() == 0 ) // Skip already existing connections (weight == 0) if( dt->GetWeight() == 0 ) // Skip already existing connections (weight == 0)
{ {
mstExpectedSize--; mstExpectedSize--;
} }
...@@ -148,9 +148,9 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -148,9 +148,9 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
// Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE, // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
// RN_EDGE_MST saves both source and target node and does not require any other // RN_EDGE_MST saves both source and target node and does not require any other
// edges to exist for getting source/target nodes // edges to exist for getting source/target nodes
RN_EDGE_MST_PTR newEdge = boost::make_shared<RN_EDGE_MST>( dt->getSourceNode(), RN_EDGE_MST_PTR newEdge = boost::make_shared<RN_EDGE_MST>( dt->GetSourceNode(),
dt->getTargetNode(), dt->GetTargetNode(),
dt->getWeight() ); dt->GetWeight() );
mst->push_back( newEdge ); mst->push_back( newEdge );
++mstSize; ++mstSize;
} }
...@@ -169,8 +169,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges, ...@@ -169,8 +169,8 @@ std::vector<RN_EDGE_PTR>* kruskalMST( RN_LINKS::RN_EDGE_LIST& aEdges,
void RN_NET::validateEdge( RN_EDGE_PTR& aEdge ) void RN_NET::validateEdge( RN_EDGE_PTR& aEdge )
{ {
RN_NODE_PTR source = aEdge->getSourceNode(); RN_NODE_PTR source = aEdge->GetSourceNode();
RN_NODE_PTR target = aEdge->getTargetNode(); RN_NODE_PTR target = aEdge->GetTargetNode();
bool valid = true; bool valid = true;
// If any of nodes belonging to the edge has the flag set, // If any of nodes belonging to the edge has the flag set,
...@@ -280,13 +280,13 @@ void RN_NET::compute() ...@@ -280,13 +280,13 @@ void RN_NET::compute()
std::partial_sort_copy( boardNodes.begin(), boardNodes.end(), nodes.begin(), nodes.end() ); std::partial_sort_copy( boardNodes.begin(), boardNodes.end(), nodes.begin(), nodes.end() );
TRIANGULATOR triangulator; TRIANGULATOR triangulator;
triangulator.createDelaunay( nodes.begin(), nodes.end() ); triangulator.CreateDelaunay( nodes.begin(), nodes.end() );
boost::scoped_ptr<RN_LINKS::RN_EDGE_LIST> triangEdges( triangulator.getEdges() ); boost::scoped_ptr<RN_LINKS::RN_EDGE_LIST> triangEdges( triangulator.GetEdges() );
// Compute weight/distance for edges resulting from triangulation // Compute weight/distance for edges resulting from triangulation
RN_LINKS::RN_EDGE_LIST::iterator eit, eitEnd; RN_LINKS::RN_EDGE_LIST::iterator eit, eitEnd;
for( eit = (*triangEdges).begin(), eitEnd = (*triangEdges).end(); eit != eitEnd; ++eit ) for( eit = (*triangEdges).begin(), eitEnd = (*triangEdges).end(); eit != eitEnd; ++eit )
(*eit)->setWeight( getDistance( (*eit)->getSourceNode(), (*eit)->getTargetNode() ) ); (*eit)->SetWeight( getDistance( (*eit)->GetSourceNode(), (*eit)->GetTargetNode() ) );
// Add the currently existing connections list to the results of triangulation // Add the currently existing connections list to the results of triangulation
std::copy( boardEdges.begin(), boardEdges.end(), std::front_inserter( *triangEdges ) ); std::copy( boardEdges.begin(), boardEdges.end(), std::front_inserter( *triangEdges ) );
...@@ -508,8 +508,8 @@ void RN_NET::RemoveItem( const TRACK* aTrack ) ...@@ -508,8 +508,8 @@ void RN_NET::RemoveItem( const TRACK* aTrack )
RN_EDGE_PTR& edge = m_tracks.at( aTrack ); RN_EDGE_PTR& edge = m_tracks.at( aTrack );
// Save nodes, so they can be cleared later // Save nodes, so they can be cleared later
RN_NODE_PTR aBegin = edge->getSourceNode(); RN_NODE_PTR aBegin = edge->GetSourceNode();
RN_NODE_PTR aEnd = edge->getTargetNode(); RN_NODE_PTR aEnd = edge->GetTargetNode();
m_links.RemoveConnection( edge ); m_links.RemoveConnection( edge );
// Remove nodes associated with the edge. It is done in a safe way, there is a check // Remove nodes associated with the edge. It is done in a safe way, there is a check
...@@ -696,8 +696,8 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con ...@@ -696,8 +696,8 @@ std::list<RN_NODE_PTR> RN_NET::GetNodes( const BOARD_CONNECTED_ITEM* aItem ) con
const TRACK* track = static_cast<const TRACK*>( aItem ); const TRACK* track = static_cast<const TRACK*>( aItem );
RN_EDGE_PTR edge = m_tracks.at( track ); RN_EDGE_PTR edge = m_tracks.at( track );
nodes.push_back( edge->getSourceNode() ); nodes.push_back( edge->GetSourceNode() );
nodes.push_back( edge->getTargetNode() ); nodes.push_back( edge->GetTargetNode() );
} }
break; break;
......
...@@ -50,13 +50,13 @@ class ZONE_CONTAINER; ...@@ -50,13 +50,13 @@ class ZONE_CONTAINER;
class CPolyPt; class CPolyPt;
// Preserve KiCad coding style policy // Preserve KiCad coding style policy
typedef hed::Node RN_NODE; typedef hed::NODE RN_NODE;
typedef hed::NodePtr RN_NODE_PTR; typedef hed::NODE_PTR RN_NODE_PTR;
typedef hed::Edge RN_EDGE; typedef hed::EDGE RN_EDGE;
typedef hed::EdgePtr RN_EDGE_PTR; typedef hed::EDGE_PTR RN_EDGE_PTR;
typedef hed::EdgeMST RN_EDGE_MST; typedef hed::EDGE_MST RN_EDGE_MST;
typedef boost::shared_ptr<hed::EdgeMST> RN_EDGE_MST_PTR; typedef hed::TRIANGULATION TRIANGULATOR;
typedef hed::Triangulation TRIANGULATOR; typedef boost::shared_ptr<hed::EDGE_MST> RN_EDGE_MST_PTR;
bool operator==( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ); bool operator==( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond );
bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond ); bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond );
......
...@@ -97,8 +97,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const ...@@ -97,8 +97,8 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const
BOOST_FOREACH( const RN_EDGE_PTR& edge, *edges ) BOOST_FOREACH( const RN_EDGE_PTR& edge, *edges )
{ {
const RN_NODE_PTR& sourceNode = edge->getSourceNode(); const RN_NODE_PTR& sourceNode = edge->GetSourceNode();
const RN_NODE_PTR& targetNode = edge->getTargetNode(); const RN_NODE_PTR& targetNode = edge->GetTargetNode();
VECTOR2D source( sourceNode->GetX(), sourceNode->GetY() ); VECTOR2D source( sourceNode->GetX(), sourceNode->GetY() );
VECTOR2D target( targetNode->GetX(), targetNode->GetY() ); VECTOR2D target( targetNode->GetX(), targetNode->GetY() );
......
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