diff --git a/Surface_mesh/examples/Surface_mesh/CMakeLists.txt b/Surface_mesh/examples/Surface_mesh/CMakeLists.txt index 2f8a933a74a..6889357d7b8 100644 --- a/Surface_mesh/examples/Surface_mesh/CMakeLists.txt +++ b/Surface_mesh/examples/Surface_mesh/CMakeLists.txt @@ -23,6 +23,7 @@ if ( CGAL_FOUND ) include_directories (BEFORE "../../include") + create_single_source_cgal_program( "sm_join.cpp" ) create_single_source_cgal_program( "sm_aabbtree.cpp" ) create_single_source_cgal_program( "sm_bgl.cpp" ) create_single_source_cgal_program( "sm_circulators.cpp" ) diff --git a/Surface_mesh/examples/Surface_mesh/data/quad.off b/Surface_mesh/examples/Surface_mesh/data/quad.off new file mode 100644 index 00000000000..5fbf20d0821 --- /dev/null +++ b/Surface_mesh/examples/Surface_mesh/data/quad.off @@ -0,0 +1,7 @@ +OFF +4 1 0 +0 0 1 +1 0 1 +1 1 1 +0 1 1 +4 0 1 2 3 diff --git a/Surface_mesh/examples/Surface_mesh/data/triangle.off b/Surface_mesh/examples/Surface_mesh/data/triangle.off new file mode 100644 index 00000000000..a3c407f60fb --- /dev/null +++ b/Surface_mesh/examples/Surface_mesh/data/triangle.off @@ -0,0 +1,6 @@ +OFF +3 1 0 +0 0 0 +1 0 0 +0 1 0 +3 0 1 2 diff --git a/Surface_mesh/examples/Surface_mesh/sm_join.cpp b/Surface_mesh/examples/Surface_mesh/sm_join.cpp new file mode 100644 index 00000000000..c892bfc4cd9 --- /dev/null +++ b/Surface_mesh/examples/Surface_mesh/sm_join.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Surface_mesh Mesh; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + +int main(int argc, char* argv[]) +{ + Mesh sm1, sm2; + std::ifstream in1((argc>1)?argv[1]:"data/triangle.off"); + in1 >> sm1; + + std::ifstream in2((argc>2)?argv[2]:"data/quad.off"); + + Mesh::Property_map name1, name2; + bool created; + sm1.add_property_map("v:weight",7812); + boost::tie(name1, created) = sm1.add_property_map("v:name","hello"); + boost::tie(name2, created) = sm2.add_property_map("v:name","world"); + + in2 >> sm2; + + sm1 += sm2; + + + BOOST_FOREACH(vertex_descriptor vd , vertices(sm1)){ + std::cerr << vd << " " << name1[vd] <* pa = dynamic_cast(&other); + if(pa != NULL){ + std::copy((*pa).data_.begin(), (*pa).data_.end(), data_.end()-(*pa).data_.size()); + return true; + } + return false; + } + virtual void shrink_to_fit() { vector_type(data_).swap(data_); @@ -265,6 +277,18 @@ public: return *this; } + void transfer(const Property_container& _rhs) + { + for(unsigned int i=0; iname() == _rhs.parrays_[j]->name()){ + parrays_[i]->transfer(* _rhs.parrays_[j]); + break; + } + } + } + } + // returns the current size of the property arrays size_t size() const { return size_; } @@ -314,7 +338,9 @@ public: // returns a property if it exists, otherwise it creates it first. - template Property_map get_or_add(const std::string& name, const T t=T()) + template + Property_map + get_or_add(const std::string& name, const T t=T()) { Property_map p; bool b; @@ -325,7 +351,8 @@ public: // get the type of property by its name. returns typeid(void) if it does not exist. - const std::type_info& get_type(const std::string& name) + const std::type_info& + get_type(const std::string& name) { for (unsigned int i=0; iname() == name) @@ -335,7 +362,9 @@ public: // delete a property - template void remove(Property_map& h) + template + void + remove(Property_map& h) { typename std::vector::iterator it=parrays_.begin(), end=parrays_.end(); for (; it!=end; ++it) @@ -488,6 +517,11 @@ public: return (*parray_)[i]; } + bool transfer (const Property_map& other) + { + return parray_->transfer(*(other.parray_)); + } + /// Allows access to the underlying storage of the property. This /// is useful when the key associated with the properties is /// unimportant and only the properties are of interest @@ -646,6 +680,7 @@ private: { return (os << 'h' << (size_type)h ); } + }; /// This class represents a face @@ -1363,6 +1398,95 @@ public: fprops_.reserve(nfaces); } + void resize(size_type nvertices, + size_type nedges, + size_type nfaces ) + { + vprops_.resize(nvertices); + hprops_.resize(2*nedges); + eprops_.resize(nedges); + fprops_.resize(nfaces); + } + + bool join(const Surface_mesh& other) + { + size_type nv = num_vertices(), nh = num_halfedges(), nf = num_faces(); + resize(num_vertices()+ other.num_vertices(), + num_edges()+ other.num_edges(), + num_faces()+ other.num_faces()); + + vprops_.transfer(other.vprops_); + hprops_.transfer(other.hprops_); + fprops_.transfer(other.fprops_); + eprops_.transfer(other.eprops_); + + for(size_type i = nv; i < nv+other.num_vertices(); i++){ + Vertex_index vi(i); + if(vconn_[vi].halfedge_ != null_halfedge()){ + vconn_[vi].halfedge_ = Halfedge_index(size_type(vconn_[vi].halfedge_)+nh); + } + } + for(size_type i = nf; i < nf+other.num_faces(); i++){ + Face_index fi(i); + if(fconn_[fi].halfedge_ != null_halfedge()){ + fconn_[fi].halfedge_ = Halfedge_index(size_type(fconn_[fi].halfedge_)+nh); + } + } + for(size_type i = nh; i < nh+other.num_halfedges(); i++){ + Halfedge_index hi(i); + if(hconn_[hi].face_ != null_face()){ + hconn_[hi].face_ = Face_index(size_type(hconn_[hi].face_)+nf); + } + if( hconn_[hi].vertex_ != null_vertex()){ + hconn_[hi].vertex_ = Vertex_index(size_type(hconn_[hi].vertex_)+nv); + } + if(hconn_[hi].next_halfedge_ != null_halfedge()){ + hconn_[hi].next_halfedge_ = Halfedge_index(size_type(hconn_[hi].next_halfedge_)+nh); + } + if(hconn_[hi].prev_halfedge_ != null_halfedge()){ + hconn_[hi].prev_halfedge_ = Halfedge_index(size_type(hconn_[hi].prev_halfedge_)+nh); + } + } + size_type nil = -1; + if(other.vertices_freelist_ != nil){ + if(vertices_freelist_ != nil){ + Vertex_index vi(nv+other.vertices_freelist_); + Halfedge_index inf(-1); + while(vconn_[vi].halfedge_ != inf){ + vi = Vertex_index(size_type(vconn_[vi].halfedge_)); + } + vconn_[vi].halfedge_ = Halfedge_index(vertices_freelist_); + } + vertices_freelist_ = nv + other.vertices_freelist_; + } + if(other.faces_freelist_ != nil){ + if(faces_freelist_ != nil){ + Face_index fi(nf+other.faces_freelist_); + Halfedge_index inf(-1); + while(fconn_[fi].halfedge_ != inf){ + fi = Face_index(size_type(fconn_[fi].halfedge_)); + } + fconn_[fi].halfedge_ = Halfedge_index(faces_freelist_); + } + faces_freelist_ = nf + other.faces_freelist_; + } + if(other.edges_freelist_ != nil){ + if(edges_freelist_ != nil){ + Halfedge_index hi((nh>>1)+other.edges_freelist_); + Halfedge_index inf(-1); + while(hconn_[hi].next_halfedge_ != inf){ + hi = hconn_[hi].next_halfedge_; + } + hconn_[hi].next_halfedge_ = Halfedge_index(edges_freelist_); + } + edges_freelist_ = (nh>>1) + other.edges_freelist_; + } + garbage_ = garbage_ || other.garbage_; + removed_vertices_ += other.removed_vertices_; + removed_edges_ += other.removed_edges_; + removed_faces_ += other.removed_faces_; + return true; + } ///@} @@ -1514,7 +1638,9 @@ public: bool is_valid(bool verbose = true) const { bool valid = true; + size_type vcount = 0, hcount = 0, fcount = 0; for(Halfedge_iterator it = halfedges_begin(); it != halfedges_end(); ++it) { + ++hcount; valid = valid && next(*it).is_valid(); valid = valid && opposite(*it).is_valid(); if(!valid) { @@ -1560,7 +1686,8 @@ public: } } - for(Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it) { + for(Vertex_iterator it = vertices_begin(); it != vertices_end(); ++it) { + ++vcount; if(halfedge(*it).is_valid()) { // not an isolated vertex valid = valid && (target(halfedge(*it)) == *it); @@ -1571,8 +1698,24 @@ public: } } } + for(Face_iterator it = faces_begin(); it != faces_end(); ++it) { + ++fcount; + } + + valid = valid && (vcount == number_of_vertices()); + if(!valid && verbose){ + std::cerr << "#vertices: iterated: " << vcount << " vs number_of_vertices(): " << number_of_vertices()<< std::endl; + } + valid = valid && (hcount == number_of_halfedges()); + if(!valid && verbose){ + std::cerr << "#halfedges: iterated: " << hcount << " vs number_of_halfedges(): " << number_of_halfedges()<< std::endl; + } + valid = valid && (fcount == number_of_faces()); + if(!valid && verbose){ + std::cerr << "#faces: iterated: " << fcount << " vs number_of_faces(): " << number_of_faces()<< std::endl; + } return valid; } @@ -2120,6 +2263,21 @@ private: //------------------------------------------------------- private data * @{ */ + /// \relates Surface_mesh + /// Inserts `other` into `sm`. + /// Shifts the indices of vertices of `other` by `sm.number_of_vertices() + sm.number_of_removed_vertices()` + /// and analoguously for halfedges, edges, and faces. + /// Copies entries of all property maps which have the same name in `sm` and `other`. + /// that is, property maps which are only in `other` are ignored. + /// Also copies elements which are marked as removed, and concatenates the freelists of `sm` and `other`. + + template + Surface_mesh

& operator+=(Surface_mesh

& sm, const Surface_mesh

& other) + { + sm.join(other); + return sm; + } + /// \relates Surface_mesh /// Inserts the surface mesh in an output stream in Ascii OFF format. /// Only the \em point property is inserted in the stream.