swh:1:snp:818279ffd0c3c25a68d33cc2b97d007e1bdc7ed6
Raw File
Tip revision: 8abaf41b7c113afafcca20c0b869826efb0c6e6b authored by ennetws on 15 January 2014, 06:15:06 UTC
Changes to filtering.
Tip revision: 8abaf41
WingedgeMesh.h
#pragma once
#include <exception>
#include <cassert>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include "StarlabException.h"

namespace CurveskelTypes{

class Wingedge_Base_property_array
{
public:

    /// Default constructor
    Wingedge_Base_property_array(const std::string& name) : name_(name) {}

    /// Destructor.
    virtual ~Wingedge_Base_property_array() {}

    /// Reserve memory for n elements.
    virtual void reserve(size_t n) = 0;

    /// Resize storage to hold n elements.
    virtual void resize(size_t n) = 0;

    /// Free unused memory.
    virtual void free_memory() = 0;

    /// Extend the number of elements by one.
    virtual void push_back() = 0;

    /// Let two elements swap their storage place.
    virtual void swap(size_t i0, size_t i1) = 0;

    /// Return a deep copy of self.
    virtual Wingedge_Base_property_array* clone () const = 0;

    /// Return the name of the property
    const std::string& name() const { return name_; }


protected:

    std::string name_;
};



//== CLASS DEFINITION =========================================================


template <class T>
class WingedgeProperty_array : public Wingedge_Base_property_array
{
public:

    typedef T                                       value_type;
    typedef std::vector<value_type>                 vector_type;
    typedef typename vector_type::reference         reference;
    typedef typename vector_type::const_reference   const_reference;

    WingedgeProperty_array(const std::string& name, T t=T()) : Wingedge_Base_property_array(name), value_(t) {}


public: // virtual interface of Base_property_array

    virtual void reserve(size_t n)
    {
        data_.reserve(n);
    }

    virtual void resize(size_t n)
    {
        data_.resize(n, value_);
    }

    virtual void push_back()
    {
        data_.push_back(value_);
    }

    virtual void free_memory()
    {
        vector_type(data_).swap(data_);
    }

    virtual void swap(size_t i0, size_t i1)
    {
        T d(data_[i0]);
        data_[i0]=data_[i1];
        data_[i1]=d;
    }

    virtual Wingedge_Base_property_array* clone() const
    {
        WingedgeProperty_array<T>* p = new WingedgeProperty_array<T>(name_, value_);
        p->data_ = data_;
        return p;
    }


public:

    /// Get pointer to array (does not work for T==bool)
    const T* data() const
    {
        return &data_[0];
    }

    /// Access the i'th element. No range check is performed!
    reference operator[](int _idx)
    {
        assert( size_t(_idx) < data_.size() );
        return data_[_idx];
    }

    /// Const access to the i'th element. No range check is performed!
    const_reference operator[](int _idx) const
    {
        assert( size_t(_idx) < data_.size());
        return data_[_idx];
    }


private:
    vector_type data_;
    value_type  value_;
};


// specialization for bool properties
template <>
inline const bool*
WingedgeProperty_array<bool>::data() const
{
    assert(false);
    return NULL;
}



//== CLASS DEFINITION =========================================================


template <class T>
class WingedgeProperty
{
public:

    typedef typename WingedgeProperty_array<T>::reference reference;
    typedef typename WingedgeProperty_array<T>::const_reference const_reference;

    friend class Property_container;
    //friend class Surface_mesh;


public:

    WingedgeProperty(WingedgeProperty_array<T>* p=NULL) : parray_(p) {}

    void reset()
    {
        parray_ = NULL;
    }

    operator bool() const
    {
        return parray_ != NULL;
    }
    
    bool is_valid() const{
        return parray_ != NULL;
    }

    reference operator[](int i)
    {
        assert(parray_ != NULL);
        return (*parray_)[i];
    }

    const_reference operator[](int i) const
    {
        assert(parray_ != NULL);
        return (*parray_)[i];
    }

    const T* data() const
    {
        assert(parray_ != NULL);
        return parray_->data();
    }


private:

    WingedgeProperty_array<T>& array()
    {
        assert(parray_ != NULL);
        return *parray_;
    }

    const WingedgeProperty_array<T>& array() const
    {
        assert(parray_ != NULL);
        return *parray_;
    }


private:
    WingedgeProperty_array<T>* parray_;
};



//== CLASS DEFINITION =========================================================


class Property_container
{
public:

    // default constructor
    Property_container() : size_(0) {}

    // destructor (deletes all property arrays)
    virtual ~Property_container() { clear(); }

    // copy constructor: performs deep copy of property arrays
    Property_container(const Property_container& _rhs) { operator=(_rhs); }
    
    // assignment: performs deep copy of property arrays
    Property_container& operator=(const Property_container& _rhs)
    {
        if (this != &_rhs)
        {
            clear();
            parrays_.resize(_rhs.n_properties());
            size_ = _rhs.size();
            for (unsigned int i=0; i<parrays_.size(); ++i)
                parrays_[i] = _rhs.parrays_[i]->clone();
        }
        return *this;
    }

    // shallow copier
    void shallow_copy(const Property_container& _rhs){
        if (this != &_rhs)
        {
            clear();
            parrays_.resize(_rhs.n_properties());
            size_ = _rhs.size();
            for (unsigned int i=0; i<_rhs.parrays_.size(); ++i){
                parrays_[i] = _rhs.parrays_[i];
            }
        }
    }
    
    // returns the current size of the property arrays
    size_t size() const { return size_; }

    // returns the number of property arrays
    size_t n_properties() const { return parrays_.size(); }

    // returns a vector of all property names
    std::vector<std::string> properties() const
    {
        std::vector<std::string> names;
        for (unsigned int i=0; i<parrays_.size(); ++i)
            names.push_back(parrays_[i]->name());
        return names;
    }


    // add a property with name \c name and default value \c t
    template <class T> WingedgeProperty<T> add(const std::string& name, const T t=T())
    {
        WingedgeProperty_array<T>* p = new WingedgeProperty_array<T>(name, t);
        p->resize(size_);
        parrays_.push_back(p);
        return WingedgeProperty<T>(p);
    }


    // get a property by its name. returns invalid property if it does not exist.
    template <class T> WingedgeProperty<T> get(const std::string& name) const
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            if (parrays_[i]->name() == name)
                return WingedgeProperty<T>(dynamic_cast<WingedgeProperty_array<T>*>(parrays_[i]));
        return WingedgeProperty<T>();
    }

    // Verifies a property of given name & type exists
    template <class T> bool exists(const std::string& name)
    {     
        WingedgeProperty<T> p = get<T>(name);
        return bool(p);
    }
    
    // returns a property if it exists, otherwise it creates it first.
    template <class T> WingedgeProperty<T> get_or_add(const std::string& name, const T t=T())
    {
        WingedgeProperty<T> p = get<T>(name);
        if (!p) p = add<T>(name, t);
        return p;
    }


    // delete a property
    template <class T> void remove(WingedgeProperty<T>& h)
    {
        std::vector<Wingedge_Base_property_array*>::iterator it=parrays_.begin(), end=parrays_.end();
        for (; it!=end; ++it)
        {
            if (*it == h.parray_)
            {
                delete *it;
                parrays_.erase(it);
                h.reset();
                break;
            }
        }
    }


    // delete all properties
    void clear()
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            delete parrays_[i];
        parrays_.clear();
        size_ = 0;
    }


    // reserve memory for n entries in all arrays
    void reserve(size_t n) const
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            parrays_[i]->reserve(n);
    }

    // resize all arrays to size n
    void resize(size_t n)
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            parrays_[i]->resize(n);
        size_ = n;
    }

    // free unused space in all arrays
    void free_memory() const
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            parrays_[i]->free_memory();
    }

    // add a new element to each vector
    void push_back()
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            parrays_[i]->push_back();
        ++size_;
    }

    // swap elements i0 and i1 in all arrays
    void swap(size_t i0, size_t i1) const
    {
        for (unsigned int i=0; i<parrays_.size(); ++i)
            parrays_[i]->swap(i0, i1);
    }


private:
    std::vector<Wingedge_Base_property_array*>  parrays_;
    size_t  size_;
};

template <class Scalar, class Vector>
class WingedgeMesh {
  
public: //------------------------------------------------------ topology types

    /// Base class for all topology types (internally it is basically an index)
    /// \sa Vertex, Edge, Face
    class Base_handle
    {
    public:

        /// constructor
        explicit Base_handle(int _idx=-1) : idx_(_idx) {}

        /// Get the underlying index of this handle
        int idx() const { return idx_; }

        /// reset handle to be invalid (index=-1)
        void reset() { idx_=-1; }

        /// return whether the handle is valid, i.e., the index is not equal to -1.
        bool is_valid() const { return idx_ != -1; }

        /// are two handles equal?
        bool operator==(const Base_handle& _rhs) const {
            return idx_ == _rhs.idx_;
        }

        /// are two handles different?
        bool operator!=(const Base_handle& _rhs) const {
            return idx_ != _rhs.idx_;
        }

        /// compare operator useful for sorting handles
        bool operator<(const Base_handle& _rhs) const {
            return idx_ < _rhs.idx_;
        }
        
    private:
        friend class Vertex_iterator;
        friend class Halfedge_iterator;
        friend class Edge_iterator;
        friend class Face_iterator;
        friend class WingedgeMesh;
        int idx_;
    };


    /// this type represents a vertex (internally it is basically an index)
    ///  \sa Edge, Face
    struct Vertex : public Base_handle
    {
        /// default constructor (with invalid index)
        explicit Vertex(int _idx=-1) : Base_handle(_idx) {}
    };

    /// this type represents an edge (internally it is basically an index)
    /// \sa Vertex, Face
    struct Edge : public Base_handle
    {
        /// default constructor (with invalid index)
        explicit Edge(int _idx=-1) : Base_handle(_idx) {}
    };


    /// this type represents a face (internally it is basically an index)
    /// \sa Vertex, Edge
    struct Face : public Base_handle
    {
        /// default constructor (with invalid index)
        explicit Face(int _idx=-1) : Base_handle(_idx) {}
    };




public: //-------------------------------------------------- connectivity types

    /// This type stores the vertex connectivity
    struct Vertex_connectivity
    {
        std::set<Edge> edges_;
    };

    /// This type stores the face connectivity
    struct Face_connectivity
    {
        std::set<Vertex> vertices_;
    };

    /// This type stores the edge connectivity
    struct Edge_connectivity
    {
        /// vertex on the edge
        Vertex    vertex0_;
        Vertex    vertex1_;
        
        /// wing faces
        std::set<Face> faces_;
    };

public: //------------------------------------------------------ property types

    /// Vertex property of type T
    /// \sa Halfedge_property, Edge_property, Face_property
    template <class T> class Vertex_property : public WingedgeProperty<T>
    {
    public:

        /// default constructor
        explicit Vertex_property() {}
        explicit Vertex_property(WingedgeProperty<T> p) : WingedgeProperty<T>(p) {}

        /// access the data stored for vertex \c v
        typename WingedgeProperty<T>::reference operator[](Vertex v)
        {
            return WingedgeProperty<T>::operator[](v.idx());
        }

        /// access the data stored for vertex \c v
        typename WingedgeProperty<T>::const_reference operator[](Vertex v) const
        {
            return WingedgeProperty<T>::operator[](v.idx());
        }
    };

    /// Edge property of type T
    /// \sa Vertex_property, Halfedge_property, Face_property
    template <class T> class Edge_property : public WingedgeProperty<T>
    {
    public:

        /// default constructor
        explicit Edge_property() {}
        explicit Edge_property(WingedgeProperty<T> p) : WingedgeProperty<T>(p) {}

        /// access the data stored for edge \c e
        typename WingedgeProperty<T>::reference operator[](Edge e)
        {
            return WingedgeProperty<T>::operator[](e.idx());
        }

        /// access the data stored for edge \c e
        typename WingedgeProperty<T>::const_reference operator[](Edge e) const
        {
            return WingedgeProperty<T>::operator[](e.idx());
        }
    };


    /// Face property of type T
    /// \sa Vertex_property, Halfedge_property, Edge_property
    template <class T> class Face_property : public WingedgeProperty<T>
    {
    public:

        /// default constructor
        explicit Face_property() {}
        explicit Face_property(WingedgeProperty<T> p) : WingedgeProperty<T>(p) {}

        /// access the data stored for face \c f
        typename WingedgeProperty<T>::reference operator[](Face f)
        {
            return WingedgeProperty<T>::operator[](f.idx());
        }

        /// access the data stored for face \c f
        typename WingedgeProperty<T>::const_reference operator[](Face f) const
        {
            return WingedgeProperty<T>::operator[](f.idx());
        }
    };




public: //------------------------------------------------------ iterator types

    /// this class iterates linearly over all vertices
    /// \sa vertices_begin(), vertices_end()
    /// \sa Edge_iterator, Face_iterator
    class Vertex_iterator
    {
    public:

        /// Default constructor
        Vertex_iterator(Vertex v=Vertex(), const WingedgeMesh* m=NULL) : hnd_(v), mesh_(m)
        {
            if (mesh_ && mesh_->garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
        }

        /// Cast to the vertex the iterator refers to
        operator Vertex() const { return hnd_; }

        /// are two iterators equal?
        bool operator==(const Vertex_iterator& rhs) const
        {
            return (hnd_==rhs.hnd_);
        }

        /// are two iterators different?
        bool operator!=(const Vertex_iterator& rhs) const
        {
            return !operator==(rhs);
        }

        /// pre-increment iterator
        Vertex_iterator& operator++()
        {
            ++hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
            return *this;
        }

        /// pre-decrement iterator
        Vertex_iterator& operator--()
        {
            --hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
            return *this;
        }

    private:
        Vertex  hnd_;
        const WingedgeMesh* mesh_;
    };

    /// this class iterates linearly over all edges
    /// \sa edges_begin(), edges_end()
    /// \sa Vertex_iterator, Face_iterator
    class Edge_iterator
    {
    public:

        /// Default constructor
        Edge_iterator(Edge e=Edge(), const WingedgeMesh* m=NULL) : hnd_(e), mesh_(m)
        {
            if (mesh_ && mesh_->garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
        }

        /// case to the edge the iterator refers to
        operator Edge() const { return hnd_; }

        /// are two iterators equal?
        bool operator==(const Edge_iterator& rhs) const
        {
            return (hnd_==rhs.hnd_);
        }

        /// are two iterators different?
        bool operator!=(const Edge_iterator& rhs) const
        {
            return !operator==(rhs);
        }

        /// pre-increment iterator
        Edge_iterator& operator++()
        {
            ++hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
            return *this;
        }

        /// pre-decrement iterator
        Edge_iterator& operator--()
        {
            --hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
            return *this;
        }

    private:
        Edge  hnd_;
        const WingedgeMesh* mesh_;
    };


    /// this class iterates linearly over all faces
    /// \sa faces_begin(), faces_end()
    /// \sa Vertex_iterator, Edge_iterator
    class Face_iterator
    {
    public:

        /// Default constructor
        Face_iterator(Face f=Face(), const WingedgeMesh* m=NULL) : hnd_(f), mesh_(m)
        {
            if (mesh_ && mesh_->garbage()) while (mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
        }

        /// case to the face the iterator refers to
        operator Face() const { return hnd_; }

        /// are two iterators equal?
        bool operator==(const Face_iterator& rhs) const
        {
            return (hnd_==rhs.hnd_);
        }

        /// are two iterators different?
        bool operator!=(const Face_iterator& rhs) const
        {
            return !operator==(rhs);
        }

        /// pre-increment iterator
        Face_iterator& operator++()
        {
            ++hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) ++hnd_.idx_;
            return *this;
        }

        /// pre-decrement iterator
        Face_iterator& operator--()
        {
            --hnd_.idx_;
            assert(mesh_);
            while (mesh_->garbage() && mesh_->is_valid(hnd_) && mesh_->is_deleted(hnd_)) --hnd_.idx_;
            return *this;
        }

    private:
        Face  hnd_;
        const WingedgeMesh* mesh_;
    };

public: //---------------------------------------------------- circulator types
	
	/// this class circulates through all outgoing edges of a vertex
	/// \sa Vertex_around_vertex_circulator, Face_around_vertex_circulator
	class Edge_around_vertex
	{
	public:

		/// default constructor
		Edge_around_vertex(const WingedgeMesh* m=NULL, Vertex v=Vertex()): mesh_(m)
		{
			edge_ = mesh_->vconn_[v].edges_.begin();
			end_ = mesh_->vconn_[v].edges_.end();
		}

		bool end()
		{
			return edge_ == end_;
		}

		/// are two circulators equal?
		bool operator==(const Edge_around_vertex& rhs) const
		{
			return ((mesh_==rhs.mesh_) && (edge_==rhs.edge_));
		}

		/// are two circulators different?
		bool operator!=(const Edge_around_vertex& rhs) const
		{
			return !operator==(rhs);
		}

		/// pre-increment (rotate clockwise)
		Edge_around_vertex& operator++()
		{
			edge_++;
			return *this;
		}

		/// pre-decrement (rotate counter-clockwise)
		Edge_around_vertex& operator--()
		{
			edge_--;
			return *this;
		}

		/// cast to Edge: gives current outgoing halfedge
		operator Edge() const { return *edge_; }

		/// cast to bool: true if vertex is not isolated
		operator bool() const { return mesh_->is_valid(*edge_); }

		operator typename std::set<Edge>::iterator() const { return edge_; }

	private:
		const WingedgeMesh*  mesh_;
		typename std::set<Edge>::iterator edge_, end_;
	};

public: //-------------------------------------------- constructor / destructor

    /// \name Construct, destruct, assignment
    //@{

    /// default constructor
    WingedgeMesh(){
        // allocate standard properties
        // same list is used in operator=() and assign()
        vconn_    = add_vertex_property<Vertex_connectivity>("v:connectivity");
        econn_    = add_edge_property<Edge_connectivity>("e:connectivity");
        fconn_    = add_face_property<Face_connectivity>("f:connectivity");
        vpoint_   = add_vertex_property<Vector>("v:point");
        vdeleted_ = add_vertex_property<bool>("v:deleted", false);
        edeleted_ = add_edge_property<bool>("e:deleted", false);
        fdeleted_ = add_face_property<bool>("f:deleted", false);

        deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0;
        garbage_ = false;
    }

    // destructor
    ~WingedgeMesh(){}
        
    /// assign \c rhs to \c *this. performs a deep copy of all properties.
    //WingedgeMesh& operator=(const WingedgeMesh& rhs);

    /// assign \c rhs to \c *this. does not copy custom properties.
    //WingedgeMesh& assign(const WingedgeMesh& rhs);

    /// assign \c rhs to \c *this. performs a shallow copy of all properties.
    //void shallow_copy(const WingedgeMesh& rhs);
    
    //@}




public: //------------------------------------------------------------- file IO

    /// \name File IO
    //@{

    /// read mesh from file \c filename. file extension determines file type.
    /// \sa write(const std::string& filename)
    //bool read(const std::string& filename);

    /// write mesh to file \c filename. file extensions determines file type.
    /// \sa read(const std::string& filename)
    //bool write(const std::string& filename) const;

    //@}




public: //----------------------------------------------- add new vertex / face

    /// \name Add new elements by hand
    //@{

    /// add a new vertex with position \c p
    Vertex add_vertex(const Vector& p){
        Vertex v = new_vertex();
        vpoint_[v] = p;
        return v;
    }
    
    Edge add_edge(Vertex v0, Vertex v1){
        return new_edge(v0,v1);
    }
        
    /// add a new triangle connecting vertices \c v1, \c v2, \c v3
    /// \sa add_face 
    Face add_triangle(Vertex v0, Vertex v1, Vertex v2){
        std::vector<Vertex> v(3);
        v[0] = v0;
        v[1] = v1;
        v[2] = v2;
        return add_face(v);
    }

    /// add a new face with vertex list \c vertices
    /// \sa add_triangle, add_quad
    Face add_face(const std::vector<Vertex>& vertices){

        int N = vertices.size();

        // Create the face
        Face f(new_face());

        // Add vertices to face
        for(int i = 0; i < N; i++)
            set_vertex(f, vertices[i]);

        // Add edges if needed, or get old ones
        std::vector<Edge> edges;
        for(int i = 0; i < N; i++){
            int j = ((i + 1) % N);
            edges.push_back(add_edge(vertices[i], vertices[j]));
        }

        // Add face to edges
        for(int e = 0; e < (int) edges.size(); e++)
            set_face(edges[e], f);

        return f;
    }

    //@}




public: //--------------------------------------------------- memory management

    /// \name Memory Management
    //@{

    /// returns number of (deleted and valid) vertices in the mesh
    unsigned int vertices_size() const { return (unsigned int) vprops_.size(); }
    /// returns number of (deleted and valid)edges in the mesh
    unsigned int edges_size() const { return (unsigned int) eprops_.size(); }
    /// returns number of (deleted and valid)faces in the mesh
    unsigned int faces_size() const { return (unsigned int) fprops_.size(); }


    /// returns number of vertices in the mesh
    unsigned int n_vertices() const { return vertices_size() - deleted_vertices_; }
    /// returns number of edges in the mesh
    unsigned int n_edges() const { return edges_size() - deleted_edges_; }
    /// returns number of faces in the mesh
    unsigned int n_faces() const { return faces_size() - deleted_faces_; }


    /// returns true iff the mesh is empty, i.e., has no vertices
    unsigned int empty() const { return n_vertices() == 0; }


    /// clear mesh: remove all vertices, edges, faces
    void clear(){
        vprops_.resize(0);
        eprops_.resize(0);
        fprops_.resize(0);
    
        vprops_.free_memory();
        eprops_.free_memory();
        fprops_.free_memory();
    
        deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0;
        garbage_ = false;
    }

    /// remove unused memory from vectors
    void free_memory(){
        vprops_.free_memory();
        eprops_.free_memory();
        fprops_.free_memory();
    }

    /// reserve memory (mainly used in file readers)
    void reserve(unsigned int nvertices, unsigned int nedges, unsigned int nfaces ){
        vprops_.reserve(nvertices);
        eprops_.reserve(nedges);
        fprops_.reserve(nfaces);
    }

    /// remove deleted vertices/edges/[faces: not implemented]
    void garbage_collection()
	{
        std::map<int, int> points;
        std::vector< Vector > points_pos;
        std::vector< std::pair<int,int> > edges;

        int vidx = 0;

        // Collect living vertices
        for(Vertex_iterator vi = vertices_begin(); vi != vertices_end(); ++vi )
        {
            Vertex v = vi;
            if(is_deleted(v) || !is_valid(v)) continue;

            points[v.idx()] = vidx++;
            points_pos.push_back(vpoint_[v]);
        }

        // Collect living edges
        for(Edge_iterator ei = edges_begin(); ei != edges_end(); ++ei)
        {
            Edge e = ei;

            Vertex v0 = vertex(e,0);
            Vertex v1 = vertex(e,1);

            if(!is_deleted(e) && !is_deleted(v0) && !is_deleted(v1) && v0 != v1)
                edges.push_back(std::pair<int,int> (points[v0.idx()], points[v1.idx()]) );
        }

        // Remove old records
        clear();

        // Add clean structure:

		// Vertices
        for(unsigned int i = 0; i < points_pos.size(); i++)
            this->add_vertex(points_pos[i]);

		// Edges
        for(unsigned int i = 0; i < edges.size(); i++)
            this->add_edge(Vertex(edges[i].first), Vertex(edges[i].second));
    }


    /// returns whether vertex \c v is deleted
    /// \sa garbage_collection()
    bool is_deleted(Vertex v) const
    {
        return vdeleted_[v];
    }
    /// returns whether edge \c e is deleted
    /// \sa garbage_collection()
    bool is_deleted(Edge e) const
    {
        return edeleted_[e];
    }
    /// returns whether face \c f is deleted
    /// \sa garbage_collection()
    bool is_deleted(Face f) const
    {
        return fdeleted_[f];
    }


    /// return whether vertex \c v is valid, i.e. the index is stores it within the array bounds.
    bool is_valid(Vertex v) const
    {
        return (0 <= v.idx()) && (v.idx() < (int)vertices_size());
    }
    /// return whether edge \c e is valid, i.e. the index is stores it within the array bounds.
    bool is_valid(Edge e) const
    {
        return (0 <= e.idx()) && (e.idx() < (int)edges_size());
    }
    /// return whether face \c f is valid, i.e. the index is stores it within the array bounds.
    bool is_valid(Face f) const
    {
        return (0 <= f.idx()) && (f.idx() < (int)faces_size());
    }

    //@}




public: //---------------------------------------------- low-level connectivity

    /// \name Low-level connectivity
    //@{

    void set_vertex(Face f, Vertex v)
    {
        fconn_[f].vertices_.insert(v);
    }

    void set_edge(Vertex v, Edge e)
    {
        vconn_[v].edges_.insert(e);
    }

    void set_face(Edge e, Face f)
    {
        econn_[e].faces_.insert(f);
    }
	
    bool edge_connects(Edge e, Vertex v)
    {
        if(econn_[e].vertex0_ == v || econn_[e].vertex1_ == v)
            return true;
        else
            return false;
    }

	bool has_faces(Edge e)
	{
		// Check if any faces are not deleted
		for(typename std::set<Face>::iterator fit = econn_[e].faces_.begin(); fit != econn_[e].faces_.end(); fit++)
		{
			if(!fdeleted_[*fit])
				return true;
		}

		return false;
	}

    /// returns whether \c v is a boundary vertex
    bool is_boundary(Vertex /*v*/) const
    {
        throw StarlabException("is_boundary(Vertex v) NOT IMPLEMENTED");
        return false;
    }

    /// returns whether \c v is isolated, i.e., not incident to any face
    bool is_isolated(Vertex /*v*/) const
    {
        throw StarlabException("is_isolated(Vertex v) NOT IMPLEMENTED");
        return false;
    }

    /// returns the \c i'th vertex of edge \c e. \c i has to be 0 or 1.
    Vertex vertex(Edge e, unsigned int i) const
    {
        assert(i<=1 /*&& i>=0 unnecessary because unsigned*/);
        if(i==0) return econn_[e].vertex0_;
        if(i==1) return econn_[e].vertex1_;
        return Vertex();
    }

    /// returns whether \c e is a boundary edge, i.e., if one of its
    /// halfedges is a boundary halfedge.
    bool is_boundary(Edge /*e*/) const
    {
        throw StarlabException("bool is_boundary(Edge e) const NOT IMPLEMENTED");
        return false;
    }

    /// returns whether \c f is a boundary face, i.e., it one of its edges is a boundary edge.
    bool is_boundary(Face /*f*/) const
    {
        throw StarlabException("bool is_boundary(Face /*f*/) NOT IMPLEMENTED");
        return false;
    }

    //@}


public: //--------------------------------------------------- property handling

    /// \name WingedgeProperty handling
    //@{

    /** add a vertex property of type \c T with name \c name and default value \c t.
     fails if a property named \c name exists already, since the name has to be unique.
     in this case it returns an invalid property */
    template <class T> Vertex_property<T> add_vertex_property(const std::string& name, const T t=T())
    {
        return Vertex_property<T>(vprops_.add<T>(name, t));
    }
    /** add a edge property of type \c T with name \c name and default value \c t.
     fails if a property named \c name exists already, since the name has to be unique.
     in this case it returns an invalid property */
    template <class T> Edge_property<T> add_edge_property(const std::string& name, const T t=T())
    {
        return Edge_property<T>(eprops_.add<T>(name, t));
    }
    /** add a face property of type \c T with name \c name and default value \c t.
     fails if a property named \c name exists already, since the name has to be unique.
     in this case it returns an invalid property */
    template <class T> Face_property<T> add_face_property(const std::string& name, const T t=T())
    {
        return Face_property<T>(fprops_.add<T>(name, t));
    }


    /** get the vertex property named \c name of type \c T. returns an invalid
     Vertex_property if the property does not exist or if the type does not match. */
    template <class T> Vertex_property<T> get_vertex_property(const std::string& name) const
    {
        return Vertex_property<T>(vprops_.get<T>(name));
    }
    /** get the edge property named \c name of type \c T. returns an invalid
     Vertex_property if the property does not exist or if the type does not match. */
    template <class T> Edge_property<T> get_edge_property(const std::string& name) const
    {
        return Edge_property<T>(eprops_.get<T>(name));
    }
    /** get the face property named \c name of type \c T. returns an invalid
     Vertex_property if the property does not exist or if the type does not match. */
    template <class T> Face_property<T> get_face_property(const std::string& name) const
    {
        return Face_property<T>(fprops_.get<T>(name));
    }

    /** checks if a face property of type \c T with name \c name exists. */
    template <class T> bool has_face_property(const std::string& name)
    {
        return fprops_.exists<T>(name);
    } 
    
    /** checks if a vertex property of type \c T with name \c name exists. */
    template <class T> bool has_vertex_property(const std::string& name)
    {
        return vprops_.exists<T>(name);
    }    

    /** if a vertex property of type \c T with name \c name exists, it is returned.
     otherwise this property is added (with default value \c t) */
    template <class T> Vertex_property<T> vertex_property(const std::string& name, const T t=T())
    {
        return Vertex_property<T>(vprops_.get_or_add<T>(name, t));
    }
    
    /** checks if a vertex property of type \c T with name \c name exists. */
    template <class T> bool has_edge_property(const std::string& name)
    {
        return eprops_.exists<T>(name);
    }
    
    /** if an edge property of type \c T with name \c name exists, it is returned.
     otherwise this property is added (with default value \c t) */
    template <class T> Edge_property<T> edge_property(const std::string& name, const T t=T())
    {
        return Edge_property<T>(eprops_.get_or_add<T>(name, t));
    }
    /** if a face property of type \c T with name \c name exists, it is returned.
     otherwise this property is added (with default value \c t) */
    template <class T> Face_property<T> face_property(const std::string& name, const T t=T())
    {
        return Face_property<T>(fprops_.get_or_add<T>(name, t));
    }


    /// remove the vertex property \c p
    template <class T> void remove_vertex_property(Vertex_property<T>& p)
    {
        vprops_.remove(p);
    }
    /// remove the edge property \c p
    template <class T> void remove_edge_property(Edge_property<T>& p)
    {
        eprops_.remove(p);
    }
    /// remove the face property \c p
    template <class T> void remove_face_property(Face_property<T>& p)
    {
        fprops_.remove(p);
    }


    /// returns the names of all vertex properties
    std::vector<std::string> vertex_properties() const
    {
        return vprops_.properties();
    }
    /// returns the names of all edge properties
    std::vector<std::string> edge_properties() const
    {
        return eprops_.properties();
    }
    /// returns the names of all face properties
    std::vector<std::string> face_properties() const
    {
        return fprops_.properties();
    }
    /// prints the names of all properties
    void property_stats() const{
#if 0
        std::vector<std::string> props;
    
        std::cout << "vertex properties:\n";
        props = vertex_properties();
        for (unsigned int i=0; i<props.size(); ++i)
            std::cout << "\t" << props[i] << std::endl;
    
        std::cout << "edge properties:\n";
        props = edge_properties();
        for (unsigned int i=0; i<props.size(); ++i)
            std::cout << "\t" << props[i] << std::endl;
    
        std::cout << "face properties:\n";
        props = face_properties();
        for (unsigned int i=0; i<props.size(); ++i)
            std::cout << "\t" << props[i] << std::endl;        
#endif
    }

    //@}




public: //--------------------------------------------- iterators & circulators

    /// \name Iterators & Circulators
    //@{

    /// returns start iterator for vertices
    Vertex_iterator vertices_begin() const
    {
        return Vertex_iterator(Vertex(0), this);
    }

    /// returns end iterator for vertices
    Vertex_iterator vertices_end() const
    {
        return Vertex_iterator(Vertex(vertices_size()), this);
    }

    /// returns start iterator for edges
    Edge_iterator edges_begin() const
    {
        return Edge_iterator(Edge(0), this);
    }

    /// returns end iterator for edges
    Edge_iterator edges_end() const
    {
        return Edge_iterator(Edge(edges_size()), this);
    }

    /// returns start iterator for faces
    Face_iterator faces_begin() const
    {
        return Face_iterator(Face(0), this);
    }

    /// returns end iterator for faces
    Face_iterator faces_end() const
    {
        return Face_iterator(Face(faces_size()), this);
    }

    //@}

public: //--------------------------------------------- higher-level operations

    /// \name Higher-level Topological Operations
    /// @{
    void collapse(Edge e)
	{
		// remove edge
		remove_edge(e);
	}
    /// @}

    unsigned int valence(Vertex v) const
    {
        return vconn_[v].edges_.size();
    }


public: //------------------------------------------ geometry-related functions

	Scalar edge_length(Edge e) const
	{
		return (vpoint_[vertex(e,0)] - vpoint_[vertex(e,1)]).norm();
	}


	void print_edges(Vertex v)
	{
		printf("Vertex (%d) has edges: {", v.idx());

		for(typename std::set<Edge>::iterator eit = vconn_[v].edges_.begin(); eit != vconn_[v].edges_.end(); eit++){
			printf("%d, ", eit->idx());
		}

		printf("}\n");
	}

	void print_edge_faces(Vertex v)
	{
		printf("Vertex (%d) has edges: {{{{", v.idx());

		for(typename std::set<Edge>::iterator eit = vconn_[v].edges_.begin(); eit != vconn_[v].edges_.end(); eit++)
		{
			printf("\t");
			print_faces(*eit);
		}

		printf("}}}}\n");
	}

	void print_vertices(Edge e)
	{
		printf("Edge (%d) has: { v0 = %d  |  v1 = %d }\n", e.idx(), econn_[e].vertex0_.idx(), econn_[e].vertex1_.idx());
	}

	void print_faces(Edge e)
	{
		printf("Edge (%d) has faces: {", e.idx());

		for(typename std::set<Face>::iterator fit = econn_[e].faces_.begin(); fit != econn_[e].faces_.end(); fit++)
		{
			printf("%d, ", fit->idx());
		}

		printf("}\n");
	}

	void print_stats()
	{
		printf("\nNumber of vertices \t= %d \n", n_vertices());
		printf("Number of faces \t= %d \n", n_faces());
        printf("Number of edges \t= %d \t (out of %d) \n\n", n_edges(), edges_size());
	}
	
protected: //---------------------------------------------- allocate new elements

    /// allocate a new vertex, resize vertex properties accordingly.
    Vertex new_vertex()
    {
        vprops_.push_back();
        return Vertex(vertices_size()-1);
    }

    /// allocate a new edge, resize edge properties accordingly.
    Edge new_edge(Vertex start, Vertex end){
        assert(start != end);

        // If edge exists already, return it
        Edge pastEdge = get_edge(start, end);
        if(pastEdge.idx() >= 0) return pastEdge;

        eprops_.push_back();
        Edge e(edges_size()-1);
        econn_[e].vertex0_ = start;
        econn_[e].vertex1_ = end;

        // Add edge to both vertices
        set_edge(start, e);
        set_edge(end, e);

        return e;
    }

    /// allocate a new face, resize face properties accordingly.
    Face new_face()
    {
        fprops_.push_back();
        return Face(faces_size()-1);
    }


public: //--------------------------------------------------- helper functions

    /// Helper for halfedge collapse
    void remove_edge(Edge e)
	{
		Vertex v1 = vertex(e, 0);  // 'v1' will be deleted
		Vertex v2 = vertex(e, 1);

		// Remove edge from vertex connectivity list
		remove_edge(v1, e);
		remove_edge(v2, e);

		// Replace 'v1' in edges of 'v1' -> 'v2'
		for(typename std::set<Edge>::iterator eit = vconn_[v1].edges_.begin(); eit != vconn_[v1].edges_.end(); eit++){
			replace_vertex(*eit, v1, v2);

			// connect to new vertex
			set_edge(v2, *eit);
		}

		// Delete dead faces of removed edge 'e'
		std::set<Face> deadFaces = econn_[e].faces_;

		// Remove the duplicated edges
		std::vector<Edge> v2_adj = edges_of(v2);

		for(uint i = 0; i < v2_adj.size(); i++)
		{
			// We will kill 'ei'
			Edge ei = v2_adj[i];

			for(uint j = i + 1; j < v2_adj.size(); j++)
			{
				Edge ej = v2_adj[j];

				if( same_edge(ei, ej) )
				{
					// Migrate faces of 'ei'
					std::set<Face> oldFaces = econn_[ei].faces_;

					for(typename std::set<Face>::iterator fit = oldFaces.begin(); fit != oldFaces.end(); fit++)
					{
						if(deadFaces.find(*fit) == deadFaces.end())
							set_face(ej, *fit);
					}

					// Delete the duplicated edge
					remove_edge(v2, ei);
					edeleted_[v2_adj[i]] = true; 
					++deleted_edges_;
				}
			}
		}

		// Not sure why this is needed since defined in constructor..
		// (just following Surface_mesh for now)
		reserve_delete();

		// delete stuff
		vdeleted_[v1]   = true; ++deleted_vertices_;


		for(typename std::set<Face>::iterator fit = deadFaces.begin(); fit != deadFaces.end(); fit++)
		{
			if(!fdeleted_[*fit])
			{
				fdeleted_[*fit] = true; 
				++deleted_faces_;
			}
		}

		garbage_ = true;

		vertex_collapsed = v1;
	}

	bool same_edge(Edge e1, Edge e2)
	{
		// first edge
		Vertex v1 = econn_[e1].vertex0_;
		Vertex v2 = econn_[e1].vertex1_;

		// second edge
		Vertex v3 = econn_[e2].vertex0_;
		Vertex v4 = econn_[e2].vertex1_;

		return ((v1 == v3) || (v1 == v4)) && ((v2 == v3) || (v2 == v4));
	}

	std::vector<Edge> edges_of(Vertex v)
	{
		std::vector<Edge> result;

		for(typename std::set<Edge>::iterator ei = vconn_[v].edges_.begin(); 
			ei != vconn_[v].edges_.end(); ei++)
			result.push_back(*ei);

		return result;
	}

	void remove_edge(Vertex v, Edge e)
	{
		vconn_[v].edges_.erase(e);
	}

	void delete_edge(Edge e)
	{
		if(!edeleted_[e])
		{
			edeleted_[e]	= true; 
			++deleted_edges_;
		}
	}

	void replace_vertex(Edge e, Vertex from, Vertex to)
	{
		if(econn_[e].vertex0_ == from) econn_[e].vertex0_ = to;
		if(econn_[e].vertex1_ == from) econn_[e].vertex1_ = to;
	}

	void replace_face(Edge e, Face oldFace, Face newFace)
	{
		econn_[e].faces_.erase(oldFace);
		econn_[e].faces_.insert(newFace);
	}

    /// find the edge from start to end
	Edge get_edge(Vertex start, Vertex end)
	{
		for(typename std::set<Edge>::iterator eit = vconn_[start].edges_.begin(); eit != vconn_[start].edges_.end(); eit++){
			if(edge_connects(*eit, start) && edge_connects(*eit, end))
				return *eit;
		}
		return Edge();
	}

	void reserve_delete()
	{
        if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false);
        if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false);
        if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false);
	}

public:  //--------------------------------------------------- public helper functions
	Vertex other_vertex(Edge e, Vertex v)
	{
		if(v == econn_[e].vertex0_) 
			return econn_[e].vertex1_;
		else
			return econn_[e].vertex0_; 
	}

	std::set<Vertex> vertex_neighbours(Vertex v)
	{
		std::set<Vertex> result;
		
		for(typename std::set<Edge>::iterator eit = vconn_[v].edges_.begin(); eit != vconn_[v].edges_.end(); eit++)
		{
			Edge e = *eit;
			result.insert(other_vertex(e, v));
		}

		return result;
	}

	int num_edges(Vertex v)
	{
		return vconn_[v].edges_.size();
	}

public:
    /// are there deleted vertices, edges or faces?
    bool garbage() const { return garbage_; }

	Vertex vertex_collapsed; // removed vertex from latest collapsed edge

protected: //------------------------------------------------------- private data

    Property_container vprops_;
    Property_container eprops_;
    Property_container fprops_;

    Vertex_property<Vertex_connectivity>      vconn_;
    Face_property<Face_connectivity>          fconn_;
    Edge_property<Edge_connectivity>          econn_;


    Vertex_property<bool>  vdeleted_;
    Edge_property<bool>    edeleted_;
    Face_property<bool>    fdeleted_;

    Vertex_property<Vector>   vpoint_;

    unsigned int deleted_vertices_;
    unsigned int deleted_edges_;
    unsigned int deleted_faces_;
    bool garbage_;

};

/// @}

} // namespace
back to top