402 lines
12 KiB
C++
402 lines
12 KiB
C++
/*
|
|
* Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT,
|
|
* Applied Mathematics, Norway.
|
|
* Copyright (C) 2013 CERN
|
|
* @author Maciej Suminski <maciej.suminski@cern.ch>
|
|
*
|
|
* Contact information: E-mail: tor.dokken@sintef.no
|
|
* SINTEF ICT, Department of Applied Mathematics,
|
|
* P.O. Box 124 Blindern,
|
|
* 0314 Oslo, Norway.
|
|
*
|
|
* This file is part of TTL.
|
|
*
|
|
* TTL is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* TTL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public
|
|
* License along with TTL. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*
|
|
* In accordance with Section 7(b) of the GNU Affero General Public
|
|
* License, a covered work must retain the producer line in every data
|
|
* file that is created or manipulated using TTL.
|
|
*
|
|
* Other Usage
|
|
* You can be released from the requirements of the license by purchasing
|
|
* a commercial license. Buying such a license is mandatory as soon as you
|
|
* develop commercial activities involving the TTL library without
|
|
* disclosing the source code of your own applications.
|
|
*
|
|
* This file may be used in accordance with the terms contained in a
|
|
* written agreement between you and SINTEF ICT.
|
|
*/
|
|
|
|
#ifndef _HE_TRIANG_H_
|
|
#define _HE_TRIANG_H_
|
|
|
|
|
|
#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)
|
|
|
|
|
|
#include <list>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <ttl/ttl_util.h>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/weak_ptr.hpp>
|
|
|
|
namespace ttl {
|
|
class TriangulationHelper;
|
|
};
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
|
// The half-edge data structure
|
|
//--------------------------------------------------------------------------------------------------
|
|
|
|
namespace hed {
|
|
// Helper typedefs
|
|
class Node;
|
|
class Edge;
|
|
typedef boost::shared_ptr<Node> NodePtr;
|
|
typedef boost::shared_ptr<Edge> EdgePtr;
|
|
typedef boost::weak_ptr<Edge> EdgeWeakPtr;
|
|
typedef std::vector<NodePtr> NodesContainer;
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// Node class for data structures
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
/** \class Node
|
|
* \brief \b Node class for data structures (Inherits from HandleId)
|
|
*
|
|
* \note
|
|
* - To enable node IDs, TTL_USE_NODE_ID must be defined.
|
|
* - 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
|
|
* required by the application, because they increase the memory usage for each Node object.
|
|
*/
|
|
|
|
class Node {
|
|
|
|
protected:
|
|
#ifdef TTL_USE_NODE_FLAG
|
|
/// TTL_USE_NODE_FLAG must be defined
|
|
bool flag_;
|
|
#endif
|
|
|
|
#ifdef TTL_USE_NODE_ID
|
|
/// TTL_USE_NODE_ID must be defined
|
|
static int id_count;
|
|
|
|
/// A unique id for each node (TTL_USE_NODE_ID must be defined)
|
|
int id_;
|
|
#endif
|
|
|
|
int x_, y_;
|
|
|
|
unsigned int refCount_;
|
|
|
|
public:
|
|
/// Constructor
|
|
Node( int x = 0, int y = 0 ) :
|
|
#ifdef TTL_USE_NODE_FLAG
|
|
flag_( false ),
|
|
#endif
|
|
#ifdef TTL_USE_NODE_ID
|
|
id_( id_count++ ),
|
|
#endif
|
|
x_( x ), y_( y ), refCount_( 0 ) {}
|
|
|
|
/// Destructor
|
|
~Node() {}
|
|
|
|
/// Returns the x-coordinate
|
|
int GetX() const { return x_; }
|
|
|
|
/// Returns the y-coordinate
|
|
int GetY() const { return y_; }
|
|
|
|
#ifdef TTL_USE_NODE_ID
|
|
/// Returns the id (TTL_USE_NODE_ID must be defined)
|
|
int Id() const { return id_; }
|
|
#endif
|
|
|
|
#ifdef TTL_USE_NODE_FLAG
|
|
/// Sets the flag (TTL_USE_NODE_FLAG must be defined)
|
|
void SetFlag(bool aFlag) { flag_ = aFlag; }
|
|
|
|
/// Returns the flag (TTL_USE_NODE_FLAG must be defined)
|
|
const bool& GetFlag() const { return flag_; }
|
|
#endif
|
|
|
|
void IncRefCount() { refCount_++; }
|
|
void DecRefCount() { refCount_--; }
|
|
unsigned int GetRefCount() const { return refCount_; }
|
|
}; // End of class Node
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------
|
|
// Edge class in the half-edge data structure
|
|
//------------------------------------------------------------------------------------------------
|
|
|
|
/** \class Edge
|
|
* \brief \b %Edge class in the in the half-edge data structure.
|
|
*/
|
|
|
|
class Edge {
|
|
public:
|
|
/// Constructor
|
|
Edge() : weight_(0), isLeadingEdge_(false) {}
|
|
|
|
/// Destructor
|
|
virtual ~Edge() {}
|
|
|
|
/// Sets the source node
|
|
void setSourceNode(const NodePtr& node) { sourceNode_ = node; }
|
|
|
|
/// Sets the next edge in face
|
|
void setNextEdgeInFace(const EdgePtr& edge) { nextEdgeInFace_ = edge; }
|
|
|
|
/// Sets the twin edge
|
|
void setTwinEdge(const EdgePtr& edge) { twinEdge_ = edge; }
|
|
|
|
/// Sets the edge as a leading edge
|
|
void setAsLeadingEdge(bool val=true) { isLeadingEdge_ = val; }
|
|
|
|
/// Checks if an edge is a leading edge
|
|
bool isLeadingEdge() const { return isLeadingEdge_; }
|
|
|
|
/// Returns the twin edge
|
|
EdgePtr getTwinEdge() const { return twinEdge_.lock(); };
|
|
|
|
void clearTwinEdge() { twinEdge_.reset(); }
|
|
|
|
/// Returns the next edge in face
|
|
const EdgePtr& getNextEdgeInFace() const { return nextEdgeInFace_; }
|
|
|
|
/// Retuns the source node
|
|
const NodePtr& getSourceNode() const { return sourceNode_; }
|
|
|
|
/// Returns the target node
|
|
virtual const NodePtr& getTargetNode() const { return nextEdgeInFace_->getSourceNode(); }
|
|
|
|
void setWeight( unsigned int weight ) { weight_ = weight; }
|
|
|
|
unsigned int getWeight() const { return weight_; }
|
|
|
|
void clear()
|
|
{
|
|
sourceNode_.reset();
|
|
nextEdgeInFace_.reset();
|
|
|
|
if( !twinEdge_.expired() )
|
|
{
|
|
twinEdge_.lock()->clearTwinEdge();
|
|
twinEdge_.reset();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
NodePtr sourceNode_;
|
|
EdgeWeakPtr twinEdge_;
|
|
EdgePtr nextEdgeInFace_;
|
|
unsigned int weight_;
|
|
bool isLeadingEdge_;
|
|
}; // End of class Edge
|
|
|
|
|
|
/** \class EdgeMST
|
|
* \brief \b Specialization of %Edge class to be used for Minimum Spanning Tree algorithm.
|
|
*/
|
|
class EdgeMST : public Edge
|
|
{
|
|
private:
|
|
NodePtr target_;
|
|
|
|
public:
|
|
EdgeMST( const NodePtr& source, const NodePtr& target, unsigned int weight = 0 ) :
|
|
target_(target)
|
|
{ sourceNode_ = source; weight_ = weight; }
|
|
|
|
EdgeMST( const Edge& edge )
|
|
{
|
|
sourceNode_ = edge.getSourceNode();
|
|
target_ = edge.getTargetNode();
|
|
weight_ = edge.getWeight();
|
|
}
|
|
|
|
~EdgeMST() {};
|
|
|
|
/// @copydoc Edge::setSourceNode()
|
|
virtual const NodePtr& getTargetNode() const { return 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 {
|
|
|
|
protected:
|
|
std::list<EdgePtr> leadingEdges_; // one half-edge for each arc
|
|
|
|
ttl::TriangulationHelper* helper;
|
|
|
|
void addLeadingEdge(EdgePtr& edge) {
|
|
edge->setAsLeadingEdge();
|
|
leadingEdges_.push_front( edge );
|
|
}
|
|
|
|
bool removeLeadingEdgeFromList(EdgePtr& leadingEdge);
|
|
|
|
void cleanAll();
|
|
|
|
/** Swaps the edge associated with \e dart in the actual data structure.
|
|
*
|
|
* <center>
|
|
* \image html swapEdge.gif
|
|
* </center>
|
|
*
|
|
* \param dart
|
|
* Some of the functions require a dart as output.
|
|
* If this is required by the actual function, the dart should be delivered
|
|
* back in a position as seen if it was glued to the edge when swapping (rotating)
|
|
* the edge CCW; see the figure.
|
|
*
|
|
* \note
|
|
* - If the edge is \e constrained, or if it should not be swapped for
|
|
* some other reason, this function need not do the actual swap of the edge.
|
|
* - Some functions in TTL require that \c swapEdge is implemented such that
|
|
* darts outside the quadrilateral are not affected by the swap.
|
|
*/
|
|
void swapEdge(Dart& dart);
|
|
|
|
/** Splits the triangle associated with \e dart in the actual data structure into
|
|
* three new triangles joining at \e point.
|
|
*
|
|
* <center>
|
|
* \image html splitTriangle.gif
|
|
* </center>
|
|
*
|
|
* \param dart
|
|
* Output: A CCW dart incident with the new node; see the figure.
|
|
*/
|
|
void splitTriangle(Dart& dart, const NodePtr& point);
|
|
|
|
/** The reverse operation of TTLtraits::splitTriangle.
|
|
* This function is only required for functions that involve
|
|
* removal of interior nodes; see for example TrinagulationHelper::removeInteriorNode.
|
|
*
|
|
* <center>
|
|
* \image html reverse_splitTriangle.gif
|
|
* </center>
|
|
*/
|
|
void reverse_splitTriangle(Dart& dart);
|
|
|
|
/** Removes a triangle with an edge at the boundary of the triangulation
|
|
* in the actual data structure
|
|
*/
|
|
void removeBoundaryTriangle(Dart& d);
|
|
|
|
public:
|
|
/// Default constructor
|
|
Triangulation();
|
|
|
|
/// Copy constructor
|
|
Triangulation(const Triangulation& tr);
|
|
|
|
/// Destructor
|
|
~Triangulation();
|
|
|
|
/// Creates a Delaunay triangulation from a set of points
|
|
void createDelaunay(NodesContainer::iterator first,
|
|
NodesContainer::iterator last);
|
|
|
|
/// Creates an initial Delaunay triangulation from two enclosing triangles
|
|
// When using rectangular boundary - loop through all points and expand.
|
|
// (Called from createDelaunay(...) when starting)
|
|
EdgePtr initTwoEnclosingTriangles(NodesContainer::iterator first,
|
|
NodesContainer::iterator last);
|
|
|
|
|
|
// These two functions are required by TTL for Delaunay triangulation
|
|
|
|
/// Swaps the edge associated with diagonal
|
|
void swapEdge(EdgePtr& diagonal);
|
|
|
|
/// Splits the triangle associated with edge into three new triangles joining at point
|
|
EdgePtr splitTriangle(EdgePtr& edge, const NodePtr& point);
|
|
|
|
|
|
// Functions required by TTL for removing nodes in a Delaunay triangulation
|
|
|
|
/// Removes the boundary triangle associated with edge
|
|
void removeTriangle(EdgePtr& edge); // boundary triangle required
|
|
|
|
/// The reverse operation of removeTriangle
|
|
void reverse_splitTriangle(EdgePtr& edge);
|
|
|
|
/// Creates an arbitrary CCW dart
|
|
Dart createDart();
|
|
|
|
/// Returns a list of "triangles" (one leading half-edge for each triangle)
|
|
const std::list<EdgePtr>& getLeadingEdges() const { return leadingEdges_; }
|
|
|
|
/// Returns the number of triangles
|
|
int noTriangles() const { return (int)leadingEdges_.size(); }
|
|
|
|
/// Returns a list of half-edges (one half-edge for each arc)
|
|
std::list<EdgePtr>* getEdges(bool skip_boundary_edges = false) const;
|
|
|
|
#ifdef TTL_USE_NODE_FLAG
|
|
/// Sets flag in all the nodes
|
|
void flagNodes(bool flag) const;
|
|
|
|
/// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node.
|
|
std::list<NodePtr>* getNodes() const;
|
|
#endif
|
|
|
|
/// Swaps edges until the triangulation is Delaunay (constrained edges are not swapped)
|
|
void optimizeDelaunay();
|
|
|
|
/// Checks if the triangulation is Delaunay
|
|
bool checkDelaunay() const;
|
|
|
|
/// Returns an arbitrary interior node (as the source node of the returned edge)
|
|
EdgePtr getInteriorNode() const;
|
|
|
|
EdgePtr getBoundaryEdgeInTriangle(const EdgePtr& e) const;
|
|
|
|
/// Returns an arbitrary boundary edge
|
|
EdgePtr getBoundaryEdge() const;
|
|
|
|
/// Print edges for plotting with, e.g., gnuplot
|
|
void printEdges(std::ofstream& os) const;
|
|
|
|
friend class ttl::TriangulationHelper;
|
|
|
|
}; // End of class Triangulation
|
|
|
|
|
|
}; // End of hed namespace
|
|
|
|
#endif
|