/*===========================================================================*\ * * * OpenMesh * * Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * * * * OpenMesh is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenMesh 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenMesh. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Date$ * * * \*===========================================================================*/ #include namespace OpenMesh { ArrayKernel::ArrayKernel() : refcount_vstatus_(0), refcount_hstatus_(0), refcount_estatus_(0), refcount_fstatus_(0) { init_bit_masks(); //Status bit masks initialization } ArrayKernel::~ArrayKernel() { clear(); } // ArrayKernel::ArrayKernel(const ArrayKernel& _rhs) // : BaseKernel(_rhs), // vertices_(_rhs.vertices_), edges_(_rhs.edges_), faces_(_rhs.faces_), // vertex_status_(_rhs.vertex_status_), halfedge_status_(_rhs.halfedge_status_), // edge_status_(_rhs.edge_status_), face_status_(_rhs.face_status_), // refcount_vstatus_(_rhs.refcount_vstatus_), refcount_hstatus_(_rhs.refcount_hstatus_), // refcount_estatus_(_rhs.refcount_estatus_), refcount_fstatus_(_rhs.refcount_fstatus_) // {} void ArrayKernel::assign_connectivity(const ArrayKernel& _other) { vertices_ = _other.vertices_; edges_ = _other.edges_; faces_ = _other.faces_; vprops_resize(n_vertices()); hprops_resize(n_halfedges()); eprops_resize(n_edges()); fprops_resize(n_faces()); #define COPY_STATUS_PROPERTY(ENTITY) \ if (_other.ENTITY##_status_.is_valid()) \ { \ if (!ENTITY##_status_.is_valid()) \ { \ request_##ENTITY##_status(); \ } \ property(ENTITY##_status_) = _other.property(_other.ENTITY##_status_); \ } COPY_STATUS_PROPERTY(vertex) COPY_STATUS_PROPERTY(halfedge) COPY_STATUS_PROPERTY(edge) COPY_STATUS_PROPERTY(face) #undef COPY_STATUS_PROPERTY } uint ArrayKernel::delete_isolated_vertices() { assert(has_vertex_status());//this function requires vertex status property uint n_isolated = 0; for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it) { if (is_isolated(handle(*v_it))) { status(handle(*v_it)).set_deleted(true); n_isolated++; } } return n_isolated; } void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f) { int i, i0, i1, nV(n_vertices()), nE(n_edges()), nH(2*n_edges()), nF(n_faces()); std::vector vh_map; std::vector hh_map; std::vector fh_map; // setup handle mapping: vh_map.reserve(nV); for (i=0; i 0) { i0=0; i1=nV-1; while (1) { // find 1st deleted and last un-deleted while (!status(VertexHandle(i0)).deleted() && i0 < i1) ++i0; while ( status(VertexHandle(i1)).deleted() && i0 < i1) --i1; if (i0 >= i1) break; // swap std::swap(vertices_[i0], vertices_[i1]); std::swap(vh_map[i0], vh_map[i1]); vprops_swap(i0, i1); }; vertices_.resize(status(VertexHandle(i0)).deleted() ? i0 : i0+1); vprops_resize(n_vertices()); } // remove deleted edges if (_e && n_edges() > 0) { i0=0; i1=nE-1; while (1) { // find 1st deleted and last un-deleted while (!status(EdgeHandle(i0)).deleted() && i0 < i1) ++i0; while ( status(EdgeHandle(i1)).deleted() && i0 < i1) --i1; if (i0 >= i1) break; // swap std::swap(edges_[i0], edges_[i1]); std::swap(hh_map[2*i0], hh_map[2*i1]); std::swap(hh_map[2*i0+1], hh_map[2*i1+1]); eprops_swap(i0, i1); hprops_swap(2*i0, 2*i1); hprops_swap(2*i0+1, 2*i1+1); }; edges_.resize(status(EdgeHandle(i0)).deleted() ? i0 : i0+1); eprops_resize(n_edges()); hprops_resize(n_halfedges()); } // remove deleted faces if (_f && n_faces() > 0) { i0=0; i1=nF-1; while (1) { // find 1st deleted and last un-deleted while (!status(FaceHandle(i0)).deleted() && i0 < i1) ++i0; while ( status(FaceHandle(i1)).deleted() && i0 < i1) --i1; if (i0 >= i1) break; // swap std::swap(faces_[i0], faces_[i1]); std::swap(fh_map[i0], fh_map[i1]); fprops_swap(i0, i1); }; faces_.resize(status(FaceHandle(i0)).deleted() ? i0 : i0+1); fprops_resize(n_faces()); } // update handles of vertices if (_e) { KernelVertexIter v_it(vertices_begin()), v_end(vertices_end()); VertexHandle vh; for (; v_it!=v_end; ++v_it) { vh = handle(*v_it); if (!is_isolated(vh)) { set_halfedge_handle(vh, hh_map[halfedge_handle(vh).idx()]); } } } HalfedgeHandle hh; // update handles of halfedges for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it) {//in the first pass update the (half)edges vertices hh = halfedge_handle(handle(*e_it), 0); set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]); hh = halfedge_handle(handle(*e_it), 1); set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]); } for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it) {//in the second pass update the connectivity of the (half)edges hh = halfedge_handle(handle(*e_it), 0); set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]); if (!is_boundary(hh)) { set_face_handle(hh, fh_map[face_handle(hh).idx()]); } hh = halfedge_handle(handle(*e_it), 1); set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]); if (!is_boundary(hh)) { set_face_handle(hh, fh_map[face_handle(hh).idx()]); } } // update handles of faces if (_e) { KernelFaceIter f_it(faces_begin()), f_end(faces_end()); FaceHandle fh; for (; f_it!=f_end; ++f_it) { fh = handle(*f_it); set_halfedge_handle(fh, hh_map[halfedge_handle(fh).idx()]); } } } void ArrayKernel::clear() { vertices_.clear(); edges_.clear(); faces_.clear(); vprops_resize(0); eprops_resize(0); hprops_resize(0); fprops_resize(0); } void ArrayKernel::resize( uint _n_vertices, uint _n_edges, uint _n_faces ) { vertices_.resize(_n_vertices); edges_.resize(_n_edges); faces_.resize(_n_faces); vprops_resize(n_vertices()); hprops_resize(n_halfedges()); eprops_resize(n_edges()); fprops_resize(n_faces()); } void ArrayKernel::reserve(uint _n_vertices, uint _n_edges, uint _n_faces ) { vertices_.reserve(_n_vertices); edges_.reserve(_n_edges); faces_.reserve(_n_faces); vprops_reserve(_n_vertices); hprops_reserve(_n_edges*2); eprops_reserve(_n_edges); fprops_reserve(_n_faces); } // Status Sets API void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc) { for (uint i = Attributes::UNUSED; i != 0; i <<= 1) { _bmc.push_back(i); } } void ArrayKernel::init_bit_masks() { init_bit_masks(vertex_bit_masks_); edge_bit_masks_ = vertex_bit_masks_;//init_bit_masks(edge_bit_masks_); face_bit_masks_ = vertex_bit_masks_;//init_bit_masks(face_bit_masks_); halfedge_bit_masks_= vertex_bit_masks_;//init_bit_masks(halfedge_bit_masks_); } };