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

Formatted ttl library to comply with KiCad coding policy.

parent a0fb4ed0
...@@ -48,685 +48,681 @@ ...@@ -48,685 +48,681 @@
#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()) { }
return EdgePtr();
} if( !edge->IsLeadingEdge() )
{
return edge; return EDGE_PTR();
}
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();
for( it = aFirst; it != aLast; ++it )
NodesContainer::iterator it; {
for (it = first; it != last; ++it) { aXmin = std::min( aXmin, ( *it )->GetX() );
xmin = min(xmin, (*it)->GetX()); aYmin = std::min( aYmin, ( *it )->GetY() );
ymin = min(ymin, (*it)->GetY()); aXmax = std::max( aXmax, ( *it )->GetX() );
xmax = max(xmax, (*it)->GetX()); aYmax = std::max( aYmax, ( *it )->GetY() );
ymax = max(ymax, (*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( aFirst, aLast, xmin, ymin, xmax, ymax );
getLimits(first, last, 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;
NODE_PTR n1 = boost::make_shared<NODE>( xmin - dx, ymin - dy );
NodePtr n1 = boost::make_shared<Node>(xmin-dx, ymin-dy); NODE_PTR n2 = boost::make_shared<NODE>( xmax + dx, ymin - dy );
NodePtr n2 = boost::make_shared<Node>(xmax+dx, ymin-dy); NODE_PTR n3 = boost::make_shared<NODE>( xmax + dx, ymax + dy );
NodePtr n3 = boost::make_shared<Node>(xmax+dx, ymax+dy); NODE_PTR n4 = boost::make_shared<NODE>( xmin - dx, ymax + dy );
NodePtr n4 = boost::make_shared<Node>(xmin-dx, ymax+dy);
// diagonal
// diagonal EDGE_PTR e1d = boost::make_shared<EDGE>();
EdgePtr e1d = boost::make_shared<Edge>(); EDGE_PTR e2d = boost::make_shared<EDGE>();
EdgePtr e2d = boost::make_shared<Edge>();
// lower triangle
// lower triangle EDGE_PTR e11 = boost::make_shared<EDGE>();
EdgePtr e11 = boost::make_shared<Edge>(); EDGE_PTR e12 = boost::make_shared<EDGE>();
EdgePtr e12 = boost::make_shared<Edge>();
// upper triangle
// upper triangle EDGE_PTR e21 = boost::make_shared<EDGE>();
EdgePtr e21 = boost::make_shared<Edge>(); EDGE_PTR e22 = boost::make_shared<EDGE>();
EdgePtr 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();
EDGE_PTR bedge = InitTwoEnclosingTriangles( aFirst, aLast );
EdgePtr bedge = initTwoEnclosingTriangles(first, last); DART dc( bedge );
Dart dc(bedge);
DART d_iter = dc;
Dart d_iter = dc;
NODES_CONTAINER::iterator it;
NodesContainer::iterator it; for( it = aFirst; it != aLast; ++it )
for (it = first; it != last; ++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
// may have been changed. // may have been changed.
// It is the users responsibility to get a valid boundary dart here. // It is the users responsibility to get a valid boundary dart here.
// The half-edge data structure preserves the initial dart. // The half-edge data structure preserves the initial dart.
// (A dart at the boundary can also be found by trying to locate a // (A dart at the boundary can also be found by trying to locate a
// 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() );
EDGE_PTR le( getLeadingEdgeInTriangle( e1 ) );
EdgePtr e1(edge->getNextEdgeInFace());
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->GetTwinEdge()->Clear();
enext->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) std::list<EDGE_PTR>::iterator it;
list<EdgePtr>::iterator it; for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
for (it = leadingEdges_.begin(); it != leadingEdges_.end(); ++it) { {
EDGE_PTR edge = *it;
EdgePtr edge = *it;
if (edge == leadingEdge) { if( edge == aLeadingEdge )
{
edge->setAsLeadingEdge(false); edge->SetAsLeadingEdge( false );
it = leadingEdges_.erase(it); it = m_leadingEdges.erase( it );
return true; return true;
}
} }
}
return false;
return false;
} }
//-------------------------------------------------------------------------------------------------- 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) {
nodeList->push_back(node); if( node->GetFlag() == false )
node->SetFlag(true); {
} nodeList->push_back( node );
edge = edge->getNextEdgeInFace(); node->SetFlag( true );
}
edge = edge->GetNextEdgeInFace();
}
} }
} return nodeList;
return nodeList;
} }
#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;
std::list<EDGE_PTR>* elist = new std::list<EDGE_PTR>;
list<EdgePtr>::const_iterator it;
list<EdgePtr>* elist = new list<EdgePtr>; 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 )
EdgePtr twinedge = edge->getTwinEdge(); {
// only one of the half-edges EDGE_PTR twinedge = edge->GetTwinEdge();
// only one of the half-edges
if ( (!twinedge && !skip_boundary_edges) ||
(twinedge && ((size_t)edge.get() > (size_t)twinedge.get())) ) if( ( !twinedge && !aSkipBoundaryEdges )
elist->push_front(edge); || ( twinedge && ( (size_t) edge.get() > (size_t) twinedge.get() ) ) )
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 aEdge is located in the triangle
// Assumes the half edge is located in the triangle // Returns a half aEdge with source node as the new node
// Returns a half edge with source node as the new node
// e#_n are new edges
// double x, y, z; // e# are existing edges
// x = point.x(); // e#_n and e##_n are new twin edges
// y = point.y(); // e##_n are edges incident to the new node
// z = point.z();
// Add the node to the structure
// e#_n are new edges //NODE_PTR new_node(new Node(x,y,z));
// e# are existing edges
// e#_n and e##_n are new twin edges NODE_PTR n1( aEdge->GetSourceNode() );
// e##_n are edges incident to the new node EDGE_PTR e1( aEdge );
// Add the node to the structure EDGE_PTR e2( aEdge->GetNextEdgeInFace() );
//NodePtr new_node(new Node(x,y,z)); NODE_PTR n2( e2->GetSourceNode() );
NodePtr n1(edge->getSourceNode()); EDGE_PTR e3( e2->GetNextEdgeInFace() );
EdgePtr e1(edge); NODE_PTR n3( e3->GetSourceNode() );
EdgePtr e2(edge->getNextEdgeInFace()); EDGE_PTR e1_n = boost::make_shared<EDGE>();
NodePtr n2(e2->getSourceNode()); EDGE_PTR e11_n = boost::make_shared<EDGE>();
EDGE_PTR e2_n = boost::make_shared<EDGE>();
EdgePtr e3(e2->getNextEdgeInFace()); EDGE_PTR e22_n = boost::make_shared<EDGE>();
NodePtr n3(e3->getSourceNode()); EDGE_PTR e3_n = boost::make_shared<EDGE>();
EDGE_PTR e33_n = boost::make_shared<EDGE>();
EdgePtr e1_n = boost::make_shared<Edge>();
EdgePtr e11_n = boost::make_shared<Edge>(); e1_n->SetSourceNode( n1 );
EdgePtr e2_n = boost::make_shared<Edge>(); e11_n->SetSourceNode( aPoint );
EdgePtr e22_n = boost::make_shared<Edge>(); e2_n->SetSourceNode( n2 );
EdgePtr e3_n = boost::make_shared<Edge>(); e22_n->SetSourceNode( aPoint );
EdgePtr e33_n = boost::make_shared<Edge>(); e3_n->SetSourceNode( n3 );
e33_n->SetSourceNode( aPoint );
e1_n->setSourceNode(n1);
e11_n->setSourceNode(point); e1_n->SetTwinEdge( e11_n );
e2_n->setSourceNode(n2); e11_n->SetTwinEdge( e1_n );
e22_n->setSourceNode(point); e2_n->SetTwinEdge( e22_n );
e3_n->setSourceNode(n3); e22_n->SetTwinEdge( e2_n );
e33_n->setSourceNode(point); e3_n->SetTwinEdge( e33_n );
e33_n->SetTwinEdge( e3_n );
e1_n->setTwinEdge(e11_n);
e11_n->setTwinEdge(e1_n); e1_n->SetNextEdgeInFace( e33_n );
e2_n->setTwinEdge(e22_n); e2_n->SetNextEdgeInFace( e11_n );
e22_n->setTwinEdge(e2_n); e3_n->SetNextEdgeInFace( e22_n );
e3_n->setTwinEdge(e33_n);
e33_n->setTwinEdge(e3_n); e11_n->SetNextEdgeInFace( e1 );
e22_n->SetNextEdgeInFace( e2 );
e1_n->setNextEdgeInFace(e33_n); e33_n->SetNextEdgeInFace( e3 );
e2_n->setNextEdgeInFace(e11_n);
e3_n->setNextEdgeInFace(e22_n); // and update old's next aEdge
e1->SetNextEdgeInFace( e2_n );
e11_n->setNextEdgeInFace(e1); e2->SetNextEdgeInFace( e3_n );
e22_n->setNextEdgeInFace(e2); e3->SetNextEdgeInFace( e1_n );
e33_n->setNextEdgeInFace(e3);
// add the three new leading edges,
// and update old's next edge // Must remove the old leading aEdge from the list.
e1->setNextEdgeInFace(e2_n); // Use the field telling if an aEdge is a leading aEdge
e2->setNextEdgeInFace(e3_n); // NOTE: Must search in the list!!!
e3->setNextEdgeInFace(e1_n);
if( e1->IsLeadingEdge() )
// add the three new leading edges, removeLeadingEdgeFromList( e1 );
// Must remove the old leading edge from the list. else if( e2->IsLeadingEdge() )
// Use the field telling if an edge is a leading edge removeLeadingEdgeFromList( e2 );
// NOTE: Must search in the list!!! else if( e3->IsLeadingEdge() )
removeLeadingEdgeFromList( e3 );
if (e1->isLeadingEdge()) else
removeLeadingEdgeFromList(e1); assert( false ); // one of the edges should be leading
else if (e2->isLeadingEdge())
removeLeadingEdgeFromList(e2); addLeadingEdge( e1_n );
else if(e3->isLeadingEdge()) addLeadingEdge( e2_n );
removeLeadingEdgeFromList(e3); addLeadingEdge( e3_n );
else
assert( false ); // one of the edges should be leading // Return a half aEdge incident to the new node (with the new node as source node)
addLeadingEdge(e1_n); return e11_n;
addLeadingEdge(e2_n);
addLeadingEdge(e3_n);
// Return a half edge incident to the new node (with the new node as source node)
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 EDGE_PTR eL( aDiagonal );
EdgePtr eL(diagonal); EDGE_PTR eR( eL->GetTwinEdge() );
EdgePtr eR(eL->getTwinEdge()); EDGE_PTR eL_1( eL->GetNextEdgeInFace() );
EdgePtr eL_1(eL->getNextEdgeInFace()); EDGE_PTR eL_2( eL_1->GetNextEdgeInFace() );
EdgePtr eL_2(eL_1->getNextEdgeInFace()); EDGE_PTR eR_1( eR->GetNextEdgeInFace() );
EdgePtr eR_1(eR->getNextEdgeInFace()); EDGE_PTR eR_2( eR_1->GetNextEdgeInFace() );
EdgePtr eR_2(eR_1->getNextEdgeInFace());
// avoid node to be dereferenced to zero and deleted
// avoid node to be dereferenced to zero and deleted NODE_PTR nR( eR_2->GetSourceNode() );
NodePtr nR(eR_2->getSourceNode()); NODE_PTR nL( eL_2->GetSourceNode() );
NodePtr 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) { {
// // ???? outputs !!!!
// Dart d0 = dart; // ofstream os("qweND.dat");
// d0.alpha0(); const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
//
// ofile << dart.x() << " " << dart.y() << endl; std::list<EDGE_PTR>::const_iterator it;
// ofile << d0.x() << " " << d0.y() << endl; bool ok = true;
//} int noNotDelaunay = 0;
for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
//-------------------------------------------------------------------------- {
bool Triangulation::checkDelaunay() const { EDGE_PTR edge = *it;
// ???? outputs !!!! for( int i = 0; i < 3; ++i )
// ofstream os("qweND.dat"); {
const list<EdgePtr>& leadingEdges = getLeadingEdges(); EDGE_PTR twinedge = edge->GetTwinEdge();
list<EdgePtr>::const_iterator it; // only one of the half-edges
bool ok = true; if( !twinedge || (size_t) edge.get() > (size_t) twinedge.get() )
int noNotDelaunay = 0; {
DART dart( edge );
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) { if( m_helper->SwapTestDelaunay<TTLtraits>( dart ) )
EdgePtr edge = *it; {
noNotDelaunay++;
for (int i = 0; i < 3; ++i) {
EdgePtr twinedge = edge->getTwinEdge(); //printEdge(dart,os); os << "\n";
ok = false;
// only one of the half-edges //cout << "............. not Delaunay .... " << endl;
if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { }
Dart dart(edge); }
if (helper->swapTestDelaunay<TTLtraits>(dart)) {
noNotDelaunay++; edge = edge->GetNextEdgeInFace();
//printEdge(dart,os); os << "\n";
ok = false;
//cout << "............. not Delaunay .... " << endl;
} }
}
edge = edge->getNextEdgeInFace();
} }
}
#ifdef DEBUG_HE #ifdef DEBUG_HE
cout << "!!! Triangulation is NOT Delaunay: " << noNotDelaunay << " edges\n" << endl; cout << "!!! Triangulation is NOT Delaunay: " << noNotDelaunay << " edges\n" << endl;
#endif #endif
return ok; return ok;
} }
//-------------------------------------------------------------------------------------------------- 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, // and is thus more efficient
// and is thus more efficient
// 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; std::list<EDGE_PTR>* elist = GetEdges( skip_boundary_edges );
list<EdgePtr>* 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; std::list<EDGE_PTR>::const_iterator it;
list<EdgePtr>::const_iterator it;
while(!optimal) { while( !optimal )
optimal = true; {
for (it = elist->begin(); it != elist->end(); ++it) { optimal = true;
EdgePtr edge = *it;
for( it = elist->begin(); it != elist->end(); ++it )
Dart dart(edge); {
// Constrained edges should not be swapped EDGE_PTR edge = *it;
if (helper->swapTestDelaunay<TTLtraits>(dart, cycling_check)) {
optimal = false; DART dart( edge );
swapEdge(edge); // Constrained edges should not be swapped
} if( m_helper->SwapTestDelaunay<TTLtraits>( dart, cycling_check ) )
{
optimal = false;
SwapEdge( edge );
}
}
} }
}
delete elist; delete elist;
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::GetInteriorNode() const
EdgePtr Triangulation::getInteriorNode() const { {
const std::list<EDGE_PTR>& leadingEdges = GetLeadingEdges();
const list<EdgePtr>& leadingEdges = getLeadingEdges(); std::list<EDGE_PTR>::const_iterator it;
list<EdgePtr>::const_iterator it;
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) {
EdgePtr edge = *it;
// multiple checks, but only until found for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
for (int i = 0; i < 3; ++i) { {
if (edge->getTwinEdge()) { EDGE_PTR edge = *it;
if (!helper->isBoundaryNode(Dart(edge))) // multiple checks, but only until found
return edge; for( int i = 0; i < 3; ++i )
} {
edge = edge->getNextEdgeInFace(); if( edge->GetTwinEdge() )
{
if( !m_helper->IsBoundaryNode( DART( edge ) ) )
return edge;
}
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)))
return edge;
edge = edge->getNextEdgeInFace(); if( m_helper->IsBoundaryEdge( DART( edge ) ) )
if (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(); edge = edge->GetNextEdgeInFace();
if( m_helper->IsBoundaryEdge( DART( edge ) ) )
return edge;
return EDGE_PTR();
} }
//-------------------------------------------------------------------------------------------------- EDGE_PTR TRIANGULATION::GetBoundaryEdge() const
EdgePtr Triangulation::getBoundaryEdge() const { {
// Get an arbitrary (CCW) boundary edge
// 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;
// Get an arbitrary (CCW) boundary edge for( it = leadingEdges.begin(); it != leadingEdges.end(); ++it )
// If the triangulation is closed, NULL is returned {
edge = GetBoundaryEdgeInTriangle( *it );
const list<EdgePtr>& leadingEdges = getLeadingEdges(); if( edge )
list<EdgePtr>::const_iterator it; return edge;
EdgePtr edge; }
return EDGE_PTR();
for (it = leadingEdges.begin(); it != leadingEdges.end(); ++it) {
edge = getBoundaryEdgeInTriangle(*it);
if (edge)
return edge;
}
return EdgePtr();
} }
//-------------------------------------------------------------------------------------------------- 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();
list<EdgePtr>::const_iterator it; 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();
// Print only one edge (the highest value of the pointer)
if (!twinedge || (size_t)edge.get() > (size_t)twinedge.get()) { // Print only one edge (the highest value of the pointer)
// Print source node and target node if( !twinedge || (size_t) edge.get() > (size_t) twinedge.get() )
NodePtr node = edge->getSourceNode(); {
os << node->GetX() << " " << node->GetY() << endl; // Print source node and target node
node = edge->getTargetNode(); NODE_PTR node = edge->GetSourceNode();
os << node->GetX() << " " << node->GetY() << endl; aOutput << node->GetX() << " " << node->GetY() << std::endl;
os << '\n'; // blank line node = edge->GetTargetNode();
} aOutput << node->GetX() << " " << node->GetY() << std::endl;
edge = edge->getNextEdgeInFace(); aOutput << '\n'; // blank line
}
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
{
/**
* \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class DART
{
EDGE_PTR m_edge;
namespace hed { /// Dart direction: true if dart is counterclockwise in face
bool m_dir;
//------------------------------------------------------------------------------------------------
// Dart class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class Dart {
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;
m_edge = aDart.m_edge;
m_dir = aDart.m_dir;
return *this; return *this;
edge_ = dart.edge_;
dir_ = dart.dir_;
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();
else { m_dir = false;
edge_ = edge_->getNextEdgeInFace(); }
dir_ = true; else
} {
return *this; m_edge = m_edge->GetNextEdgeInFace();
m_dir = true;
}
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();
// else, the dart is at the boundary and should not be changed m_dir = !m_dir;
return *this; }
// else, the dart is at the boundary and should not be changed
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;
}
void init(const EdgePtr& edge, bool dir = true) { edge_ = edge; dir_ = dir; } double X() const
{
return GetNode()->GetX();
}
double x() const { return getNode()->GetX(); } // x-coordinate of source node double Y() const
double y() const { return getNode()->GetY(); } // y-coordinate of source node {
return GetNode()->GetY();
}
bool isCounterClockWise() const { return dir_; } bool IsCCW() const
{
return m_dir;
}
const NodePtr& getNode() const { return dir_ ? edge_->getSourceNode() : edge_->getTargetNode(); } const NODE_PTR& GetNode() const
const NodePtr& getOppositeNode() const { return dir_ ? edge_->getTargetNode() : edge_->getSourceNode(); } {
EdgePtr& getEdge() { return edge_; } return m_dir ? m_edge->GetSourceNode() : m_edge->GetTargetNode();
}
//@} // End of Utilities not required by TTL const NODE_PTR& GetOppositeNode() const
{
return m_dir ? m_edge->GetTargetNode() : m_edge->GetSourceNode();
}
}; EDGE_PTR& GetEdge()
{
return m_edge;
}
//@} // End of Utilities not required by TTL
};
}; // End of hed namespace } // End of hed namespace
#endif #endif
...@@ -40,136 +40,149 @@ ...@@ -40,136 +40,149 @@
#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
//------------------------------------------------------------------------------------------------ * \brief \b Traits class (static struct) for the half-edge data structure.
// Traits class for the half-edge data structure *
//------------------------------------------------------------------------------------------------ * The member functions are those required by different function templates
* in the TTL. Documentation is given here to explain what actions
/** \struct TTLtraits * should be carried out on the actual data structure as required by the functions
* \brief \b Traits class (static struct) for the half-edge data structure. * in the \ref ttl namespace.
* *
* The member functions are those required by different function templates * The source code of \c %HeTraits.h shows how the traits class is implemented for the
* in the TTL. Documentation is given here to explain what actions * half-edge data structure.
* should be carried out on the actual data structure as required by the functions *
* in the \ref ttl namespace. * \see \ref api
* */
* The source code of \c %HeTraits.h shows how the traits class is implemented for the struct TTLtraits
* half-edge data structure. {
* /**
* \see \ref api * The floating point type used in calculations involving scalar products and cross products.
* */
*/ typedef double REAL_TYPE;
struct TTLtraits {
/** The floating point type used in calculations
* involving scalar products and cross products.
*/
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& aV1, const DART& aV2 )
static real_type scalarProduct2d(const Dart& v1, const Dart& v2) { {
Dart v10 = v1; v10.alpha0(); DART v10 = aV1;
Dart v20 = v2; v20.alpha0(); v10.Alpha0();
return ttl_util::scalarProduct2d(v10.x()-v1.x(), v10.y()-v1.y(),
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(),
v20.X() - aV2.X(), v20.Y() - aV2.Y() );
} }
/**
//---------------------------------------------------------------------------------------------- * Scalar product between two 2D vectors.
/** 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& aV, const NODE_PTR& aP )
static real_type scalarProduct2d(const Dart& v, const NodePtr& p) { {
Dart d0 = v; d0.alpha0(); DART d0 = aV;
return ttl_util::scalarProduct2d(d0.x() - v.x(), d0.y() - v.y(), d0.Alpha0();
p->GetX() - v.x(), p->GetY() - v.y());
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& aV1, const DART& aV2 )
static real_type crossProduct2d(const Dart& v1, const Dart& v2) { {
Dart v10 = v1; v10.alpha0(); DART v10 = aV1;
Dart v20 = v2; v20.alpha0(); v10.Alpha0();
return ttl_util::crossProduct2d(v10.x()-v1.x(), v10.y()-v1.y(),
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(),
v20.X() - aV2.X(), v20.Y() - aV2.Y() );
} }
/**
//---------------------------------------------------------------------------------------------- * Cross product between two vectors in the plane.
/** 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& aV, const NODE_PTR& aP )
static real_type crossProduct2d(const Dart& v, const NodePtr& p) { {
Dart d0 = v; d0.alpha0(); DART d0 = aV;
return ttl_util::crossProduct2d(d0.x() - v.x(), d0.y() - v.y(), d0.Alpha0();
p->GetX() - v.x(), p->GetY() - v.y());
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& aN1, const DART& aN2, const NODE_PTR& aP )
static real_type orient2d(const Dart& n1, const Dart& n2, const NodePtr& p) { {
real_type pa[2]; real_type pb[2]; real_type pc[2]; REAL_TYPE pa[2];
pa[0] = n1.x(); pa[1] = n1.y(); REAL_TYPE pb[2];
pb[0] = n2.x(); pb[1] = n2.y(); REAL_TYPE pc[2];
pc[0] = p->GetX(); pc[1] = p->GetY();
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& aN1, const DART& aN2, const DART& aP )
static real_type orient2d(const Dart& n1, const Dart& n2, const Dart& p) { {
real_type pa[2]; real_type pb[2]; real_type pc[2]; REAL_TYPE pa[2];
pa[0] = n1.x(); pa[1] = n1.y(); REAL_TYPE pb[2];
pb[0] = n2.x(); pb[1] = n2.y(); REAL_TYPE pc[2];
pc[0] = p.x(); pc[1] = p.y();
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,43 +53,40 @@ ...@@ -55,43 +53,40 @@
#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
//------------------------------------------------------------------------------------------------ * \brief \b Node class for data structures (Inherits from HandleId)
*
/** \class Node * \note
* \brief \b Node class for data structures (Inherits from HandleId) * - To enable node IDs, TTL_USE_NODE_ID must be defined.
* * - To enable node flags, TTL_USE_NODE_FLAG must be defined.
* \note * - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is
* - To enable node IDs, TTL_USE_NODE_ID must be defined. * required by the application, because they increase the memory usage for each Node object.
* - To enable node flags, TTL_USE_NODE_FLAG must be defined. */
* - TTL_USE_NODE_ID and TTL_USE_NODE_FLAG should only be enabled if this functionality is class NODE
* required by the application, because they increase the memory usage for each Node object. {
*/
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,303 +94,378 @@ protected: ...@@ -99,303 +94,378 @@ 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()
//------------------------------------------------------------------------------------------------ {
// Edge class in the half-edge data structure m_refCount--;
//------------------------------------------------------------------------------------------------ }
/** \class Edge unsigned int GetRefCount() const
* \brief \b %Edge class in the in the half-edge data structure. {
*/ return m_refCount;
}
};
class Edge {
public: /**
* \class EDGE
* \brief \b %Edge class in the in the half-edge data structure.
*/
class EDGE
{
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)
//------------------------------------------------------------------------------------------------
// Triangulation class in the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Triangulation
* \brief \b %Triangulation class for the half-edge data structure with adaption to TTL.
*/
class Triangulation { class DART; // Forward declaration (class in this namespace)
protected: /**
std::list<EdgePtr> leadingEdges_; // one half-edge for each arc * \class TRIANGULATION
* \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;
ttl::TriangulationHelper* helper; ttl::TRIANGULATION_HELPER* m_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();
/** Swaps the edge associated with \e dart in the actual data structure. /** Swaps the edge associated with \e dart in the actual data structure.
* *
* <center> * <center>
* \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)
* the edge CCW; see the figure. * the edge CCW; see the figure.
* *
* \note * \note
* - If the edge is \e constrained, or if it should not be swapped for * - If the edge is \e constrained, or if it should not be swapped for
* some other reason, this function need not do the actual swap of the edge. * some other reason, this function need not do the actual swap of the edge.
* - Some functions in TTL require that \c swapEdge is implemented such that * - 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 /**
* three new triangles joining at \e point. * Splits the triangle associated with \e dart in the actual data structure into
* * three new triangles joining at \e point.
* <center> *
* \image html splitTriangle.gif * <center>
* </center> * \image html splitTriangle.gif
* * </center>
* \param dart *
* Output: A CCW dart incident with the new node; see the figure. * \param aDart
*/ * 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.
* This function is only required for functions that involve /**
* removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode. * The reverse operation of TTLtraits::splitTriangle.
* * This function is only required for functions that involve
* <center> * removal of interior nodes; see for example TrinagulationHelper::RemoveInteriorNode.
* \image html reverse_splitTriangle.gif *
* </center> * <center>
*/ * \image html reverse_splitTriangle.gif
void reverse_splitTriangle(Dart& dart); * </center>
*/
/** Removes a triangle with an edge at the boundary of the triangulation void reverseSplitTriangle( DART& aDart );
* in the actual data structure
*/ /**
void removeBoundaryTriangle(Dart& d); * Removes a triangle with an edge at the boundary of the triangulation
* in the actual data structure
public: */
void removeBoundaryTriangle( DART& aDart );
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
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -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,67 +71,59 @@ ...@@ -77,67 +71,59 @@
* 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
{
/** @name Computational geometry */
//@{
/** Scalar product between two 2D vectors.
*
* \aPAr Returns:
* \code
* aDX1*aDX2 + aDY1*aDY2
* \endcode
*/
template <class REAL_TYPE>
REAL_TYPE ScalarProduct2D( REAL_TYPE aDX1, REAL_TYPE aDY1, REAL_TYPE aDX2, REAL_TYPE aDY2 )
{
return aDX1 * aDX2 + aDY1 * aDY2;
}
namespace ttl_util { /** Cross product between two 2D vectors. (The z-component of the actual cross product.)
*
* \aPAr Returns:
//------------------------------------------------------------------------------------------------ * \code
// ------------------------------ Computational Geometry Group ---------------------------------- * aDX1*aDY2 - aDY1*aDX2
//------------------------------------------------------------------------------------------------ * \endcode
*/
/** @name Computational geometry */ template <class REAL_TYPE>
//@{ REAL_TYPE CrossProduct2D( REAL_TYPE aDX1, REAL_TYPE aDY1, REAL_TYPE aDX2, REAL_TYPE aDY2 )
{
//------------------------------------------------------------------------------------------------ return aDX1 * aDY2 - aDY1 * aDX2;
/** Scalar product between two 2D vectors. }
*
* \par Returns: /** Returns a positive value if the 2D nodes/points \e aPA, \e aPB, and
* \code * \e aPC occur in counterclockwise order; a negative value if they occur
* dx1*dx2 + dy1*dy2 * in clockwise order; and zero if they are collinear.
* \endcode *
*/ * \note
template <class real_type> * - This is a finite arithmetic fast version. It can be made more robust using
real_type scalarProduct2d(real_type dx1, real_type dy1, real_type dx2, real_type dy2) { * exact arithmetic schemes by Jonathan Richard Shewchuk. See
return dx1*dx2 + dy1*dy2; * http://www-2.cs.cmu.edu/~quake/robust.html
} */
template <class REAL_TYPE>
REAL_TYPE Orient2DFast( REAL_TYPE aPA[2], REAL_TYPE aPB[2], REAL_TYPE aPC[2] )
//------------------------------------------------------------------------------------------------ {
/** Cross product between two 2D vectors. (The z-component of the actual cross product.) REAL_TYPE acx = aPA[0] - aPC[0];
* REAL_TYPE bcx = aPB[0] - aPC[0];
* \par Returns: REAL_TYPE acy = aPA[1] - aPC[1];
* \code REAL_TYPE bcy = aPB[1] - aPC[1];
* dx1*dy2 - dy1*dx2
* \endcode
*/
template <class real_type>
real_type crossProduct2d(real_type dx1, real_type dy1, real_type dx2, real_type dy2) {
return dx1*dy2 - dy1*dx2;
}
//------------------------------------------------------------------------------------------------
/** Returns a positive value if the 2D nodes/points \e pa, \e pb, and
* \e pc occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*
* \note
* - This is a finite arithmetic fast version. It can be made more robust using
* exact arithmetic schemes by Jonathan Richard Shewchuk. See
* http://www-2.cs.cmu.edu/~quake/robust.html
*/
template <class real_type>
real_type orient2dfast(real_type pa[2], real_type pb[2], real_type pc[2]) {
real_type acx = pa[0] - pc[0];
real_type bcx = pb[0] - pc[0];
real_type acy = pa[1] - pc[1];
real_type bcy = pb[1] - pc[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