/* * Copyright (C) 1998, 2000-2007, 2010, 2011, 2012, 2013 SINTEF ICT, * Applied Mathematics, Norway. * Copyright (C) 2013 CERN * @author Maciej Suminski * * 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 * . * * 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 #include #include #include #include #include #include //-------------------------------------------------------------------------------------------------- // The half-edge data structure //-------------------------------------------------------------------------------------------------- namespace hed { // Helper typedefs class Node; class Edge; typedef boost::shared_ptr NodePtr; typedef boost::shared_ptr EdgePtr; typedef std::vector 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) { flags_.isLeadingEdge_ = false; flags_.isConstrained_ = 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) { flags_.isLeadingEdge_ = val; } /// Checks if an edge is a leading edge bool isLeadingEdge() const { return flags_.isLeadingEdge_; } /// Sets the edge as a constrained edge void setConstrained(bool val=true) { flags_.isConstrained_ = val; if (twinEdge_) twinEdge_->flags_.isConstrained_ = val; } /// Checks if an edge is constrained bool isConstrained() const { return flags_.isConstrained_; } /// Returns the twin edge const EdgePtr& getTwinEdge() const { return twinEdge_; }; /// Returns the next edge in face const EdgePtr& getNextEdgeInFace() const { return nextEdgeInFace_; } /// Retuns the source node virtual const NodePtr& getSourceNode() const { return sourceNode_; } /// Returns the target node virtual const NodePtr& getTargetNode() const { return getNextEdgeInFace()->getSourceNode(); } void setWeight( unsigned int weight ) { weight_ = weight; } unsigned int getWeight() const { return weight_; } protected: NodePtr sourceNode_; EdgePtr twinEdge_; EdgePtr nextEdgeInFace_; unsigned int weight_; struct { bool isLeadingEdge_; bool isConstrained_; } flags_; }; // 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() {}; /// @copydoc Edge::setSourceNode() 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: list leadingEdges_; // one half-edge for each arc void addLeadingEdge(EdgePtr& edge) { edge->setAsLeadingEdge(); leadingEdges_.push_front( edge ); } bool removeLeadingEdgeFromList(EdgePtr& leadingEdge); void cleanAll(); public: /// Default constructor Triangulation() {} /// Copy constructor Triangulation(const Triangulation& tr) { std::cout << "Triangulation: Copy constructor not present - EXIT."; exit(-1); } /// Destructor ~Triangulation() { cleanAll(); } /// 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, 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 list& getLeadingEdges() const { return leadingEdges_; } /// Returns the number of triangles int noTriangles() const { return (int)leadingEdges_.size(); } /// Returns a list of half-edges (one half-edge for each arc) list* getEdges(bool skip_boundary_edges = false) const; #ifdef TTL_USE_NODE_FLAG /// Sets flag in all the nodes void flagNodes(bool flag) const; /// Returns a list of nodes. This function requires TTL_USE_NODE_FLAG to be defined. \see Node. list* 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; /// Returns an arbitrary boundary edge EdgePtr getBoundaryEdge() const; /// Print edges for plotting with, e.g., gnuplot void printEdges(std::ofstream& os) const; }; // End of class Triangulation }; // End of hed namespace #endif