From 84c80a197239d241433a996154032073d209210e Mon Sep 17 00:00:00 2001 From: cignoni Date: Mon, 25 Nov 2013 10:01:24 +0000 Subject: [PATCH] Include header cleaning and reordering. --- vcg/complex/algorithms/attribute_seam.h | 668 ++++--- vcg/complex/algorithms/bitquad_creation.h | 309 ++- vcg/complex/algorithms/bitquad_support.h | 6 +- vcg/complex/algorithms/clean.h | 943 +++++---- .../algorithms/create/advancing_front.h | 334 ++-- vcg/complex/allocate.h | 1770 ++++++++--------- vcg/complex/append.h | 102 +- vcg/complex/complex.h | 17 +- 8 files changed, 2080 insertions(+), 2069 deletions(-) diff --git a/vcg/complex/algorithms/attribute_seam.h b/vcg/complex/algorithms/attribute_seam.h index b8646d0e..594205cc 100644 --- a/vcg/complex/algorithms/attribute_seam.h +++ b/vcg/complex/algorithms/attribute_seam.h @@ -1,46 +1,64 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004-2012 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program 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 General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ #ifndef VCG_TRI_ATTRIBUTE_SEAM_H #define VCG_TRI_ATTRIBUTE_SEAM_H -#include - -#include - /* // sample extract functor void v_extract(const src_mesh_t & wm, const src_face_t & f, int k, const dst_mesh_t & vm, dst_vertex_t & v) { - (void)wm; - (void)vm; + (void)wm; + (void)vm; - v.P() = f.cP (k); - v.N() = f.cWN(k); - v.C() = f.cWC(k); - v.T() = f.cWT(k); + v.P() = f.cP (k); + v.N() = f.cWN(k); + v.C() = f.cWC(k); + v.T() = f.cWT(k); } // sample compare functor bool v_compare(const dst_mesh_t & vm, const dst_vertex_t & u, const dst_vertex_t & v) { - (void)vm; + (void)vm; - return - ( - (u.cN() == v.cN()) - && (u.cC() == v.cC()) - && (u.cT() == v.cT()) - ); + return + ( + (u.cN() == v.cN()) + && (u.cC() == v.cC()) + && (u.cT() == v.cT()) + ); } // sample copy functor void v_copy(const dst_mesh_t & vm, const dst_vertex_t & u, dst_vertex_t & v) { - (void)vm; + (void)vm; - v.P() = u.cP(); - v.N() = u.cN(); - v.C() = u.cC(); - v.T() = u.cT(); + v.P() = u.cP(); + v.N() = u.cN(); + v.C() = u.cC(); + v.T() = u.cT(); } // create seams @@ -56,310 +74,310 @@ namespace tri class AttributeSeam { - public: - - typedef AttributeSeam ThisType; - - enum ASMask - { - POSITION_PER_VERTEX = (1 << 0), - - NORMAL_PER_VERTEX = (1 << 1), - NORMAL_PER_WEDGE = (1 << 2), - NORMAL_PER_FACE = (1 << 3), - - COLOR_PER_VERTEX = (1 << 4), - COLOR_PER_WEDGE = (1 << 5), - COLOR_PER_FACE = (1 << 6), - - TEXCOORD_PER_VERTEX = (1 << 7), - TEXCOORD_PER_WEDGE = (1 << 8) - }; - - template - struct ASExtract - { - const unsigned int mask; - - ASExtract(unsigned int vmask = 0) : mask(vmask) - { - ; - } - - void operator () (const src_trimesh_t & sm, const typename src_trimesh_t::FaceType & f, int k, const dst_trimesh_t & dm, typename dst_trimesh_t::VertexType & v) const - { - (void)sm; - (void)dm; - - const unsigned int m = this->mask; - const typename src_trimesh_t::VertexType & u = *(f.cV(k)); - - if ((m & AttributeSeam::POSITION_PER_VERTEX) != 0) v.P() = f.cP (k); - - if ((m & AttributeSeam::NORMAL_PER_VERTEX) != 0) v.N() = u.cN ( ); - if ((m & AttributeSeam::NORMAL_PER_WEDGE) != 0) v.N() = f.cWN(k); - if ((m & AttributeSeam::NORMAL_PER_FACE) != 0) v.N() = f.cN ( ); - - if ((m & AttributeSeam::COLOR_PER_VERTEX) != 0) v.C() = u.cC ( ); - if ((m & AttributeSeam::COLOR_PER_WEDGE) != 0) v.C() = f.cWC(k); - if ((m & AttributeSeam::COLOR_PER_FACE) != 0) v.C() = f.cC ( ); - - if ((m & AttributeSeam::TEXCOORD_PER_VERTEX) != 0) v.T() = u.cT ( ); - if ((m & AttributeSeam::TEXCOORD_PER_WEDGE) != 0) v.T() = f.cWT(k); - } - }; - - template - struct ASCompare - { - const unsigned int mask; - - ASCompare(unsigned int vmask = 0) : mask(vmask) - { - ; - } - - bool operator () (const dst_trimesh_t & sm, const typename dst_trimesh_t::VertexType & u, const typename dst_trimesh_t::VertexType & v) const - { - (void)sm; - - const unsigned int m = this->mask; - - /* - if ((m & (AttributeSeam::POSITION_PER_VERTEX)) != 0) - { - if (u.cP() != v.cP()) return false; - } - */ - - if ((m & (AttributeSeam::NORMAL_PER_VERTEX | AttributeSeam::NORMAL_PER_WEDGE | AttributeSeam::NORMAL_PER_FACE)) != 0) - { - if (u.cN() != v.cN()) return false; - } - - if ((m & (AttributeSeam::COLOR_PER_VERTEX | AttributeSeam::COLOR_PER_WEDGE | AttributeSeam::COLOR_PER_FACE)) != 0) - { - if (u.cC() != v.cC()) return false; - } - - if ((m & (AttributeSeam::TEXCOORD_PER_VERTEX | AttributeSeam::TEXCOORD_PER_WEDGE)) != 0) - { - if (u.cT() != v.cT()) return false; - } - - return true; - } - }; - - // in-place version - template - static inline bool SplitVertex(src_trimesh_t & src, extract_wedge_attribs_t v_extract, compare_vertex_attribs_t & v_compare) - { - typedef typename src_trimesh_t::VertexType src_vertex_t; - typedef typename src_trimesh_t::VertexIterator src_vertex_i; - typedef typename src_trimesh_t::FaceType src_face_t; - typedef typename src_trimesh_t::FaceIterator src_face_i; - typedef typename src_trimesh_t::VertContainer src_vertex_container_t; - - typedef vcg::tri::Allocator src_mesh_allocator_t; - typedef typename src_mesh_allocator_t :: template PointerUpdater src_pointer_updater_t; - - if ((src.vn <= 0) || (src.fn <= 0)) - { - return true; - } - - src_pointer_updater_t pt_upd; - src_vertex_i vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd); - src_vertex_t * vtx = &(*vi); - src_vertex_t * vtxbase = &(src.vert[0]); - - const size_t vertex_count = src.vert.size(); - const size_t vertex_pool_size = vertex_count; - - std::vector vloc; - vloc.reserve(vertex_pool_size); - vloc.resize(vertex_count, -2); - - int vcount = int(src.vert.size()); - int idx = 0; - - for (src_face_i it=src.face.begin(); it!=src.face.end(); ++it) - { - src_face_t & f = (*it); - if (f.IsD()) continue; - - for (int k=0; k<3; ++k) - { - idx = (f.cV(k) - vtxbase); - v_extract(src, f, k, src, *vtx); - - if (vloc[idx] == -2) - { - vloc[idx] = -1; - src.vert[idx].ImportData(*vtx); - } - else - { - int vidx = idx; - do - { - if (v_compare(src, src.vert[vidx], *vtx)) break; - vidx = vloc[vidx]; - } while (vidx >= 0); - - if (vidx < 0) - { - vloc.push_back(vloc[idx]); - vloc[idx] = vcount; - - vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd); - pt_upd.Update(vtx); - pt_upd.Update(vtxbase); - - (*vi).ImportData(*vtx); - - idx = vcount; - vcount++; - } - else - { - idx = vidx; - } - } - - f.V(k) = &(src.vert[idx]); - } - } - - src_mesh_allocator_t::DeleteVertex(src, *vtx); - - return true; - } - - // out-of-place version - template - static inline bool SplitVertex(const src_trimesh_t & src, dst_trimesh_t & dst, extract_wedge_attribs_t & v_extract, compare_vertex_attribs_t & v_compare, copy_vertex_t & v_copy) - { - typedef typename src_trimesh_t::VertexType src_vertex_t; - typedef typename src_trimesh_t::FaceType src_face_t; - typedef typename src_trimesh_t::ConstFaceIterator src_face_ci; - - typedef typename dst_trimesh_t::VertContainer dst_vertex_container_t; - typedef typename dst_trimesh_t::VertexType dst_vertex_t; - typedef typename dst_trimesh_t::VertexIterator dst_vertex_i; - typedef typename dst_trimesh_t::FaceType dst_face_t; - typedef typename dst_trimesh_t::FaceIterator dst_face_i; - - typedef vcg::tri::Allocator dst_mesh_allocator_t; - - /* GCC gets in troubles and need some hints ("template") to parse the following line */ - typedef typename dst_mesh_allocator_t :: template PointerUpdater dst_pointer_updater_t; - - if (reinterpret_cast(&src) == reinterpret_cast(&dst)) - { - return false; - } - - dst.Clear(); - - if ((src.vn <= 0) || (src.fn <= 0)) - { - return true; - } - - const size_t vertex_count = src.vert.size(); - const size_t vertex_pool_size = vertex_count; - - const src_vertex_t * vtxbase = &(src.vert[0]); - - std::vector vloc; - vloc.reserve(vertex_pool_size); - vloc.resize(vertex_count, -2); - - dst_vertex_i vv; - dst_pointer_updater_t pt_upd; - pt_upd.preventUpdateFlag = true; - dst_mesh_allocator_t::AddVertices(dst, 1 + int(vertex_count), pt_upd); - dst_vertex_t * vtx = &(dst.vert[0]); - - dst_face_i fbase = dst_mesh_allocator_t::AddFaces(dst, src.fn); - dst_face_i fi = fbase; - - int vcount = int(dst.vert.size()); - int idx = 0; - - for (src_face_ci it=src.face.begin(); it!=src.face.end(); ++it) - { - const src_face_t & wf = (*it); - if (wf.IsD()) continue; - - dst_face_t & vf = (*fi); - - for (int k=0; k<3; ++k) - { - idx = (wf.cV(k) - vtxbase); - - v_extract(src, wf, k, dst, *vtx); - - if (vloc[idx] == -2) - { - vloc[idx] = -1; - v_copy(dst, *vtx, dst.vert[idx]); - } - else - { - int vidx = idx; - do - { - if (v_compare(dst, dst.vert[vidx], *vtx)) break; - vidx = vloc[vidx]; - } while (vidx >= 0); - - if (vidx < 0) - { - vloc.push_back(vloc[idx]); - vloc[idx] = vcount; - - vv = dst_mesh_allocator_t::AddVertices(dst, 1, pt_upd); - pt_upd.Update(vtx); - v_copy(dst, *vtx, *vv); - - idx = vcount; - vcount++; - } - else - { - idx = vidx; - } - } - - vf.V(k) = reinterpret_cast(idx); - } - - fi++; - } - - { - std::vector tmp; - vloc.swap(tmp); - } - - dst_vertex_t * vstart = &(dst.vert[0]); - - for (dst_face_i it=fbase; it!=dst.face.end(); ++it) - { - dst_face_t & vf = (*it); + public: + + typedef AttributeSeam ThisType; + + enum ASMask + { + POSITION_PER_VERTEX = (1 << 0), + + NORMAL_PER_VERTEX = (1 << 1), + NORMAL_PER_WEDGE = (1 << 2), + NORMAL_PER_FACE = (1 << 3), + + COLOR_PER_VERTEX = (1 << 4), + COLOR_PER_WEDGE = (1 << 5), + COLOR_PER_FACE = (1 << 6), + + TEXCOORD_PER_VERTEX = (1 << 7), + TEXCOORD_PER_WEDGE = (1 << 8) + }; + + template + struct ASExtract + { + const unsigned int mask; + + ASExtract(unsigned int vmask = 0) : mask(vmask) + { + ; + } + + void operator () (const src_trimesh_t & sm, const typename src_trimesh_t::FaceType & f, int k, const dst_trimesh_t & dm, typename dst_trimesh_t::VertexType & v) const + { + (void)sm; + (void)dm; + + const unsigned int m = this->mask; + const typename src_trimesh_t::VertexType & u = *(f.cV(k)); + + if ((m & AttributeSeam::POSITION_PER_VERTEX) != 0) v.P() = f.cP (k); + + if ((m & AttributeSeam::NORMAL_PER_VERTEX) != 0) v.N() = u.cN ( ); + if ((m & AttributeSeam::NORMAL_PER_WEDGE) != 0) v.N() = f.cWN(k); + if ((m & AttributeSeam::NORMAL_PER_FACE) != 0) v.N() = f.cN ( ); + + if ((m & AttributeSeam::COLOR_PER_VERTEX) != 0) v.C() = u.cC ( ); + if ((m & AttributeSeam::COLOR_PER_WEDGE) != 0) v.C() = f.cWC(k); + if ((m & AttributeSeam::COLOR_PER_FACE) != 0) v.C() = f.cC ( ); + + if ((m & AttributeSeam::TEXCOORD_PER_VERTEX) != 0) v.T() = u.cT ( ); + if ((m & AttributeSeam::TEXCOORD_PER_WEDGE) != 0) v.T() = f.cWT(k); + } + }; + + template + struct ASCompare + { + const unsigned int mask; + + ASCompare(unsigned int vmask = 0) : mask(vmask) + { + ; + } + + bool operator () (const dst_trimesh_t & sm, const typename dst_trimesh_t::VertexType & u, const typename dst_trimesh_t::VertexType & v) const + { + (void)sm; + + const unsigned int m = this->mask; + + /* + if ((m & (AttributeSeam::POSITION_PER_VERTEX)) != 0) + { + if (u.cP() != v.cP()) return false; + } + */ + + if ((m & (AttributeSeam::NORMAL_PER_VERTEX | AttributeSeam::NORMAL_PER_WEDGE | AttributeSeam::NORMAL_PER_FACE)) != 0) + { + if (u.cN() != v.cN()) return false; + } + + if ((m & (AttributeSeam::COLOR_PER_VERTEX | AttributeSeam::COLOR_PER_WEDGE | AttributeSeam::COLOR_PER_FACE)) != 0) + { + if (u.cC() != v.cC()) return false; + } + + if ((m & (AttributeSeam::TEXCOORD_PER_VERTEX | AttributeSeam::TEXCOORD_PER_WEDGE)) != 0) + { + if (u.cT() != v.cT()) return false; + } + + return true; + } + }; + + // in-place version + template + static inline bool SplitVertex(src_trimesh_t & src, extract_wedge_attribs_t v_extract, compare_vertex_attribs_t & v_compare) + { + typedef typename src_trimesh_t::VertexType src_vertex_t; + typedef typename src_trimesh_t::VertexIterator src_vertex_i; + typedef typename src_trimesh_t::FaceType src_face_t; + typedef typename src_trimesh_t::FaceIterator src_face_i; + typedef typename src_trimesh_t::VertContainer src_vertex_container_t; + + typedef vcg::tri::Allocator src_mesh_allocator_t; + typedef typename src_mesh_allocator_t :: template PointerUpdater src_pointer_updater_t; + + if ((src.vn <= 0) || (src.fn <= 0)) + { + return true; + } + + src_pointer_updater_t pt_upd; + src_vertex_i vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd); + src_vertex_t * vtx = &(*vi); + src_vertex_t * vtxbase = &(src.vert[0]); + + const size_t vertex_count = src.vert.size(); + const size_t vertex_pool_size = vertex_count; + + std::vector vloc; + vloc.reserve(vertex_pool_size); + vloc.resize(vertex_count, -2); + + int vcount = int(src.vert.size()); + int idx = 0; + + for (src_face_i it=src.face.begin(); it!=src.face.end(); ++it) + { + src_face_t & f = (*it); + if (f.IsD()) continue; + + for (int k=0; k<3; ++k) + { + idx = (f.cV(k) - vtxbase); + v_extract(src, f, k, src, *vtx); + + if (vloc[idx] == -2) + { + vloc[idx] = -1; + src.vert[idx].ImportData(*vtx); + } + else + { + int vidx = idx; + do + { + if (v_compare(src, src.vert[vidx], *vtx)) break; + vidx = vloc[vidx]; + } while (vidx >= 0); + + if (vidx < 0) + { + vloc.push_back(vloc[idx]); + vloc[idx] = vcount; + + vi = src_mesh_allocator_t::AddVertices(src, 1, pt_upd); + pt_upd.Update(vtx); + pt_upd.Update(vtxbase); + + (*vi).ImportData(*vtx); + + idx = vcount; + vcount++; + } + else + { + idx = vidx; + } + } + + f.V(k) = &(src.vert[idx]); + } + } + + src_mesh_allocator_t::DeleteVertex(src, *vtx); + + return true; + } + + // out-of-place version + template + static inline bool SplitVertex(const src_trimesh_t & src, dst_trimesh_t & dst, extract_wedge_attribs_t & v_extract, compare_vertex_attribs_t & v_compare, copy_vertex_t & v_copy) + { + typedef typename src_trimesh_t::VertexType src_vertex_t; + typedef typename src_trimesh_t::FaceType src_face_t; + typedef typename src_trimesh_t::ConstFaceIterator src_face_ci; + + typedef typename dst_trimesh_t::VertContainer dst_vertex_container_t; + typedef typename dst_trimesh_t::VertexType dst_vertex_t; + typedef typename dst_trimesh_t::VertexIterator dst_vertex_i; + typedef typename dst_trimesh_t::FaceType dst_face_t; + typedef typename dst_trimesh_t::FaceIterator dst_face_i; + + typedef vcg::tri::Allocator dst_mesh_allocator_t; + + /* GCC gets in troubles and need some hints ("template") to parse the following line */ + typedef typename dst_mesh_allocator_t :: template PointerUpdater dst_pointer_updater_t; + + if (reinterpret_cast(&src) == reinterpret_cast(&dst)) + { + return false; + } + + dst.Clear(); + + if ((src.vn <= 0) || (src.fn <= 0)) + { + return true; + } + + const size_t vertex_count = src.vert.size(); + const size_t vertex_pool_size = vertex_count; + + const src_vertex_t * vtxbase = &(src.vert[0]); + + std::vector vloc; + vloc.reserve(vertex_pool_size); + vloc.resize(vertex_count, -2); + + dst_vertex_i vv; + dst_pointer_updater_t pt_upd; + pt_upd.preventUpdateFlag = true; + dst_mesh_allocator_t::AddVertices(dst, 1 + int(vertex_count), pt_upd); + dst_vertex_t * vtx = &(dst.vert[0]); + + dst_face_i fbase = dst_mesh_allocator_t::AddFaces(dst, src.fn); + dst_face_i fi = fbase; + + int vcount = int(dst.vert.size()); + int idx = 0; + + for (src_face_ci it=src.face.begin(); it!=src.face.end(); ++it) + { + const src_face_t & wf = (*it); + if (wf.IsD()) continue; + + dst_face_t & vf = (*fi); + + for (int k=0; k<3; ++k) + { + idx = (wf.cV(k) - vtxbase); + + v_extract(src, wf, k, dst, *vtx); + + if (vloc[idx] == -2) + { + vloc[idx] = -1; + v_copy(dst, *vtx, dst.vert[idx]); + } + else + { + int vidx = idx; + do + { + if (v_compare(dst, dst.vert[vidx], *vtx)) break; + vidx = vloc[vidx]; + } while (vidx >= 0); + + if (vidx < 0) + { + vloc.push_back(vloc[idx]); + vloc[idx] = vcount; + + vv = dst_mesh_allocator_t::AddVertices(dst, 1, pt_upd); + pt_upd.Update(vtx); + v_copy(dst, *vtx, *vv); + + idx = vcount; + vcount++; + } + else + { + idx = vidx; + } + } + + vf.V(k) = reinterpret_cast(idx); + } + + fi++; + } + + { + std::vector tmp; + vloc.swap(tmp); + } + + dst_vertex_t * vstart = &(dst.vert[0]); + + for (dst_face_i it=fbase; it!=dst.face.end(); ++it) + { + dst_face_t & vf = (*it); - vf.V(0) = vstart + reinterpret_cast(vf.V(0)); - vf.V(1) = vstart + reinterpret_cast(vf.V(1)); - vf.V(2) = vstart + reinterpret_cast(vf.V(2)); - } - - dst_mesh_allocator_t::DeleteVertex(dst, *vtx); - - return true; - } + vf.V(0) = vstart + reinterpret_cast(vf.V(0)); + vf.V(1) = vstart + reinterpret_cast(vf.V(1)); + vf.V(2) = vstart + reinterpret_cast(vf.V(2)); + } + + dst_mesh_allocator_t::DeleteVertex(dst, *vtx); + + return true; + } }; } // end namespace tri diff --git a/vcg/complex/algorithms/bitquad_creation.h b/vcg/complex/algorithms/bitquad_creation.h index f0a9677b..73b9d038 100644 --- a/vcg/complex/algorithms/bitquad_creation.h +++ b/vcg/complex/algorithms/bitquad_creation.h @@ -1,30 +1,29 @@ #include -#include /** BIT-QUAD creation support: a collection of methods that, starting from a triangular mesh, will create your quad-pure or quad-domainant mesh. - + They all require: - - per face Q, and FF connectivity, 2-manyfold meshes, + - per face Q, and FF connectivity, 2-manyfold meshes, - and tri- or quad- meshes (no penta, etc) (if in need, use MakeBitTriOnly) [ list of available methods: ] - -void MakePureByRefine(Mesh &m) + +void MakePureByRefine(Mesh &m) - adds a vertex for each tri or quad present - thus, miminal complexity increase is the mesh is quad-dominant already - old non-border edges are made faux - never fails -void MakePureByCatmullClark(MeshType &m) - - adds a vertex in each (non-faux) edge. +void MakePureByCatmullClark(MeshType &m) + - adds a vertex in each (non-faux) edge. - twice complexity increase w.r.t. "ByRefine" method. - - preserves edges: old edges are still edges + - preserves edges: old edges are still edges - never fails - -bool MakePureByFlip(MeshType &m [, int maxdist] ) + +bool MakePureByFlip(MeshType &m [, int maxdist] ) - does not increase # vertices, just flips edges - call in a loop until it returns true (temporary hack) - fails if number of triangle is odd (only happens in open meshes) @@ -65,9 +64,9 @@ namespace vcg{namespace tri{ template > class BitQuadCreation{ - + public: - + typedef _MeshType MeshType; typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::CoordType CoordType; @@ -84,37 +83,37 @@ typedef BitQuad BQ; // static class to make basic quad operations // given a triangle, merge it with its best neightboord to form a quad template static void selectBestDiag(FaceType *fi){ - + if (!override) { if (fi->IsAnyF()) return; } - + // select which edge to make faux (if any)... int whichEdge = -1; - ScalarType bestScore = fi->Q(); - + ScalarType bestScore = fi->Q(); + whichEdge=-1; for (int k=0; k<3; k++){ - + // todo: check creases? (continue if edge k is a crease) - + if (!override) { - if (fi->FFp(k)->IsAnyF()) continue; + if (fi->FFp(k)->IsAnyF()) continue; } if (fi->FFp(k)==fi) continue; // never make a border faux - + ScalarType score = BQ::quadQuality( &*fi, k ); if (override) { // don't override anyway iff other face has a better match - if (score < fi->FFp(k)->Q()) continue; + if (score < fi->FFp(k)->Q()) continue; } - if (score>bestScore) { + if (score>bestScore) { bestScore = score; whichEdge = k; } } - + // ...and make it faux if (whichEdge>=0) { //if (override && fi->FFp(whichEdge)->IsAnyF()) { @@ -122,8 +121,8 @@ static void selectBestDiag(FaceType *fi){ // fi->Q() = fi->FFp(whichEdge)->Q() = ( bestScore + fi->FFp(whichEdge)->Q() ) /2; //} else { //} - - if (override) { + + if (override) { // clear any faux edge of the other face for (int k=0; k<3; k++) if (fi->FFp(whichEdge)->IsF(k)) { @@ -131,7 +130,7 @@ static void selectBestDiag(FaceType *fi){ fi->FFp(whichEdge)->FFp(k)->ClearF( fi->FFp(whichEdge)->FFi(k) ); fi->FFp(whichEdge)->FFp(k)->Q()=0.0; // other face's ex-buddy is now single and sad :( } - + // clear all faux edges of this face... for (int k=0; k<3; k++) if (fi->IsF(k)) { @@ -143,11 +142,11 @@ static void selectBestDiag(FaceType *fi){ // set (new?) quad fi->SetF(whichEdge); fi->FFp(whichEdge)->SetF( fi->FFi(whichEdge) ); - fi->Q() = fi->FFp(whichEdge)->Q() = bestScore; + fi->Q() = fi->FFp(whichEdge)->Q() = bestScore; } - - + + } @@ -156,11 +155,11 @@ static void selectBestDiag(FaceType *fi){ // a pass though all triangles to merge triangle pairs into quads template // override previous decisions? static void MakeDominantPass(MeshType &m){ - + for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { selectBestDiag(&(*fi)); } - + } /** * This function split a face along the specified border edge it does not compute any property of the new vertex. It only do the topological work. @@ -265,9 +264,9 @@ static bool MakeTriEvenBySplit(MeshType& m){ // make tri count even by delete... static bool MakeTriEvenByDelete(MeshType& m) -{ +{ if (m.fn%2==0) return false; // it's already Even - + for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) { for (int k=0; k<3; k++) { if (face::IsBorder(*fi,k) ) { @@ -304,7 +303,7 @@ static int SplitNonFlatQuads(MeshType &m, ScalarType deg=0){ } -/** +/** Given a mesh, makes it bit trianglular (makes all edges NOT faux) */ static void MakeBitTriOnly(MeshType &m){ @@ -331,7 +330,7 @@ static bool IsBitTriQuadConventional(const MeshType &m){ if (fi->IsAnyF()) if ( (fi->Flags() & FaceType::FAUX012 ) != FaceType::FAUX2 ) { return false; - } + } } return true; } @@ -347,11 +346,11 @@ static bool IsTriOnly(const MeshType &m){ /* returns true if mesh is a pure quad-mesh. */ static bool IsQuadOnly(const MeshType &m){ for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { - int count = 0; - if (fi->IsF(0)) count++; - if (fi->IsF(1)) count++; - if (fi->IsF(2)) count++; - if (count!=1) return false; + int count = 0; + if (fi->IsF(0)) count++; + if (fi->IsF(1)) count++; + if (fi->IsF(2)) count++; + if (count!=1) return false; } return true; } @@ -359,11 +358,11 @@ static bool IsQuadOnly(const MeshType &m){ /* returns true if mesh has only tris and quads (no penta etc) */ static bool IsTriQuadOnly(const MeshType &m){ for (ConstFaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { - int count = 0; - if (fi->IsF(0)) count++; - if (fi->IsF(1)) count++; - if (fi->IsF(2)) count++; - if (count>1) return false; + int count = 0; + if (fi->IsF(0)) count++; + if (fi->IsF(1)) count++; + if (fi->IsF(2)) count++; + if (count>1) return false; } return true; } @@ -384,20 +383,20 @@ static void CopyTopology(FaceType *fnew, FaceType * fold) requires that the mesh is made only of quads and tris. */ static void MakePureByRefine(MeshType &m){ - + // todo: update VF connectivity if present - + int ev = 0; // EXTRA vertices (times 2) - int ef = 0; // EXTRA faces - + int ef = 0; // EXTRA faces + // first pass: count triangles to be added for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { int k=0; if (face::IsBorder(*fi,0)) k++; if (face::IsBorder(*fi,1)) k++; if (face::IsBorder(*fi,2)) k++; - if (!fi->IsAnyF()) { + if (!fi->IsAnyF()) { // it's a triangle if (k==0) // add a vertex in the center of the face, splitting it in 3 { ev+=2; ef+=2; } @@ -410,17 +409,17 @@ static void MakePureByRefine(MeshType &m){ } else { // assuming is a quad (not a penta, etc), i.e. only one faux - // add a vertex in the center of the faux edge, splitting the face in 2 + // add a vertex in the center of the faux edge, splitting the face in 2 ev+=1; ef+=1; - assert(k!=3); - } + assert(k!=3); + } } - assert(ev%2==0); // should be even by now + assert(ev%2==0); // should be even by now ev/=2; // I was counting each of them twice //int originalFaceNum = m.fn; - FaceIterator nfi = tri::Allocator::AddFaces(m,ef); - VertexIterator nvi = tri::Allocator::AddVertices(m,ev); + FaceIterator nfi = tri::Allocator::AddFaces(m,ef); + VertexIterator nvi = tri::Allocator::AddVertices(m,ev); tri::UpdateFlags::FaceClearV(m); @@ -429,10 +428,10 @@ static void MakePureByRefine(MeshType &m){ for (FaceIterator fi = m.face.begin(), fend = nfi; fi!=fend; fi++) if (!fi->IsD() && !fi->IsV() ) { fi->SetV(); - - if (!fi->IsAnyF()) { + + if (!fi->IsAnyF()) { // it's a triangle - + int k=0; // number of borders if (face::IsBorder(*fi,0)) k++; if (face::IsBorder(*fi,1)) k++; @@ -443,31 +442,31 @@ static void MakePureByRefine(MeshType &m){ assert(nvi!=m.vert.end()); VertexType *nv = &*nvi; nvi++; //*nv = *fi->V0( 0 ); // lazy: copy everything from the old vertex - nv->ImportData(*(fi->V0( 0 ))); // lazy: copy everything from the old vertex + nv->ImportData(*(fi->V0( 0 ))); // lazy: copy everything from the old vertex nv->P() = ( fi->V(0)->P() + fi->V(1)->P() + fi->V(2)->P() ) /3.0; FaceType *fa = &*fi; FaceType *fb = &*nfi; nfi++; FaceType *fc = &*nfi; nfi++; - fb->ImportData(*fa); CopyTopology(fb,fa); - fc->ImportData(*fa); CopyTopology(fc,fa); + fb->ImportData(*fa); CopyTopology(fb,fa); + fc->ImportData(*fa); CopyTopology(fc,fa); fa->V(0) = nv; fb->V(1) = nv; fc->V(2) = nv; fb->FFp(2)=fa->FFp(2); fb->FFi(2)=fa->FFi(2); - fc->FFp(0)=fa->FFp(0); fc->FFi(0)=fa->FFi(0); + fc->FFp(0)=fa->FFp(0); fc->FFi(0)=fa->FFi(0); assert( fa->FFp(1)->FFp(fa->FFi(1)) == fa ); /* */fb->FFp(2)->FFp(fb->FFi(2)) = fb; /* */fc->FFp(0)->FFp(fc->FFi(0)) = fc; - + fa->FFp(0) = fc; fa->FFp(2) = fb; fa->FFi(0) = fa->FFi(2) = 1; fb->FFp(1) = fa; fb->FFp(0) = fc; fb->FFi(0) = fb->FFi(1) = 2; fc->FFp(1) = fa; fc->FFp(2) = fb; fc->FFi(1) = fc->FFi(2) = 0; - + if (fb->FFp(2)==fa) fb->FFp(2)=fb; // recover border status if (fc->FFp(0)==fa) fc->FFp(0)=fc; @@ -477,7 +476,7 @@ static void MakePureByRefine(MeshType &m){ fa->SetF(1); fb->SetF(2); fc->SetF(0); - + fa->SetV();fb->SetV();fc->SetV(); } if (k==1) { // make a border face faux, anf other two as well @@ -487,18 +486,18 @@ static void MakePureByRefine(MeshType &m){ nsplit++; } if (k==2) // do nothing, just mark the non border edge as faux - { + { fi->ClearAllF(); for (int w=0; w<3; w++) if (fi->FFp(w) != &*fi) fi->SetF(w); } if (k==3) // disconnected single triangle (all borders): use catmull-clark (tree vertices, split it in 6 - { + { fi->ClearAllF(); - fi->SetF(2); + fi->SetF(2); nsplit++; } } - else { + else { // assuming is a part of quad (not a penta, etc), i.e. only one faux FaceType *fa = &*fi; int ea2 = BQ::FauxIndex(fa); // index of the only faux edge @@ -507,7 +506,7 @@ static void MakePureByRefine(MeshType &m){ assert(fb->FFp(eb2)==fa) ; assert(fa->IsF(ea2)); //assert(fb->IsF(eb2)); // reciprocal faux edge - + int ea0 = (ea2+1) %3; int ea1 = (ea2+2) %3; int eb0 = (eb2+1) %3; @@ -517,7 +516,7 @@ static void MakePureByRefine(MeshType &m){ assert(nvi!=m.vert.end()); VertexType *nv = &*nvi; nvi++; // *nv = * fa->V0( ea2 ); - nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex + nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex //nv->P() = ( fa->V(ea2)->P() + fa->V(ea0)->P() ) /2.0; Interpolator::Apply(*(fa->V(ea2)),*(fa->V(ea0)),0.5,*nv); // split faces: add 2 faces (one per side) @@ -526,33 +525,33 @@ static void MakePureByRefine(MeshType &m){ assert(nfi!=m.face.end()); FaceType *fd = &*nfi; nfi++; - fc->ImportData(*fa ); CopyTopology(fc,fa); // lazy: copy everything from the old vertex - fd->ImportData(*fb ); CopyTopology(fd,fb);// lazy: copy everything from the old vertex + fc->ImportData(*fa ); CopyTopology(fc,fa); // lazy: copy everything from the old vertex + fd->ImportData(*fb ); CopyTopology(fd,fb);// lazy: copy everything from the old vertex - fa->V(ea2) = fc->V(ea0) = + fa->V(ea2) = fc->V(ea0) = fb->V(eb2) = fd->V(eb0) = nv ; - + fa->FFp(ea1)->FFp( fa->FFi(ea1) ) = fc; fb->FFp(eb1)->FFp( fb->FFi(eb1) ) = fd; - - fa->FFp(ea1) = fc ; fa->FFp(ea2) = fd; - fa->FFi(ea1) = ea0; fa->FFi(ea2) = eb2; - fb->FFp(eb1) = fd ; fb->FFp(eb2) = fc; - fb->FFi(eb1) = eb0; fb->FFi(eb2) = ea2; - fc->FFp(ea0) = fa ; fc->FFp(ea2) = fb; - fc->FFi(ea0) = ea1; fc->FFi(ea2) = eb2; - fd->FFp(eb0) = fb ; fd->FFp(eb2) = fa; + + fa->FFp(ea1) = fc ; fa->FFp(ea2) = fd; + fa->FFi(ea1) = ea0; fa->FFi(ea2) = eb2; + fb->FFp(eb1) = fd ; fb->FFp(eb2) = fc; + fb->FFi(eb1) = eb0; fb->FFi(eb2) = ea2; + fc->FFp(ea0) = fa ; fc->FFp(ea2) = fb; + fc->FFi(ea0) = ea1; fc->FFi(ea2) = eb2; + fd->FFp(eb0) = fb ; fd->FFp(eb2) = fa; fd->FFi(eb0) = eb1; fd->FFi(eb2) = ea2; - + // detect boundaries bool ba = fa->FFp(ea0)==fa; bool bc = fc->FFp(ea1)==fa; bool bb = fb->FFp(eb0)==fb; bool bd = fd->FFp(eb1)==fb; - + if (bc) fc->FFp(ea1)=fc; // repristinate boundary status if (bd) fd->FFp(eb1)=fd; // of new faces - + fa->SetV(); fb->SetV(); fc->SetV(); @@ -562,103 +561,103 @@ static void MakePureByRefine(MeshType &m){ fb->ClearAllF(); fc->ClearAllF(); fd->ClearAllF(); - + fa->SetF( ea0 ); fb->SetF( eb0 ); fc->SetF( ea1 ); fd->SetF( eb1 ); - + // fix faux mesh boundary... if two any consecutive, merge it in a quad if (ba&&bc) { - fa->ClearAllF(); fa->SetF(ea1); + fa->ClearAllF(); fa->SetF(ea1); fc->ClearAllF(); fc->SetF(ea0); - ba = bc = false; + ba = bc = false; } if (bc&&bb) { - fc->ClearAllF(); fc->SetF(ea2); + fc->ClearAllF(); fc->SetF(ea2); fb->ClearAllF(); fb->SetF(eb2); - bc = bb = false; + bc = bb = false; } if (bb&&bd) { - fb->ClearAllF(); fb->SetF(eb1); + fb->ClearAllF(); fb->SetF(eb1); fd->ClearAllF(); fd->SetF(eb0); - bb = bd = false; + bb = bd = false; } if (bd&&ba) { - fd->ClearAllF(); fd->SetF(eb2); + fd->ClearAllF(); fd->SetF(eb2); fa->ClearAllF(); fa->SetF(ea2); - bd = ba = false; + bd = ba = false; } - // remaninig boudaries will be fixed by splitting in the last pass + // remaninig boudaries will be fixed by splitting in the last pass if (ba) nsplit++; if (bb) nsplit++; if (bc) nsplit++; if (bd) nsplit++; - } + } } assert(nfi==m.face.end()); assert(nvi==m.vert.end()); - + // now and there are no tris left, but there can be faces with ONE edge border & faux () // last pass: add vertex on faux border faces... (if any) - if (nsplit>0) { + if (nsplit>0) { FaceIterator nfi = tri::Allocator::AddFaces(m,nsplit); - VertexIterator nvi = tri::Allocator::AddVertices(m,nsplit); + VertexIterator nvi = tri::Allocator::AddVertices(m,nsplit); for (FaceIterator fi = m.face.begin(), fend = nfi; fi!=fend; fi++) if (!fi->IsD()) { FaceType* fa = &*fi; int ea2 = -1; // border and faux face (if any) if (fa->FFp(0)==fa && fa->IsF(0) ) ea2=0; if (fa->FFp(1)==fa && fa->IsF(1) ) ea2=1; if (fa->FFp(2)==fa && fa->IsF(2) ) ea2=2; - + if (ea2 != -1) { // ea2 edge is naughty (border AND faux) int ea0 = (ea2+1) %3; - int ea1 = (ea2+2) %3; - + int ea1 = (ea2+2) %3; + // create new vert in center of faux edge VertexType *nv = &*nvi; nvi++; //*nv = * fa->V0( ea2 ); - nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex + nv->ImportData(*(fa->V0( ea2 ) )); // lazy: copy everything from the old vertex nv->P() = ( fa->V(ea2)->P() + fa->V(ea0)->P() ) /2.0; Interpolator::Apply(*(fa->V(ea2)),*(fa->V(ea0)),0.5,*nv); // split face: add 1 face FaceType *fc = &*nfi; nfi++; - fc->ImportData(*fa);CopyTopology(fc,fa); // lazy: copy everything from the old vertex + fc->ImportData(*fa);CopyTopology(fc,fa); // lazy: copy everything from the old vertex fa->V(ea2) = fc->V(ea0) = nv ; - + fc->FFp(ea2) = fc; - + fa->FFp(ea1)->FFp( fa->FFi(ea1) ) = fc; - - fa->FFp(ea1) = fc ; - fa->FFi(ea1) = ea0; - fc->FFp(ea0) = fa ; fc->FFp(ea2) = fc; - fc->FFi(ea0) = ea1; - + + fa->FFp(ea1) = fc ; + fa->FFi(ea1) = ea0; + fc->FFp(ea0) = fa ; fc->FFp(ea2) = fc; + fc->FFi(ea0) = ea1; + if (fc->FFp(ea1)==fa) fc->FFp(ea1)=fc; // recover border status - + assert(fa->IsF(ea0) == fa->IsF(ea1) ); bool b = fa->IsF(ea1); - + fa->ClearAllF(); fc->ClearAllF(); - + if (b) { fa->SetF( ea0 ); - fc->SetF( ea1 ); + fc->SetF( ea1 ); } else { fa->SetF( ea1 ); - fc->SetF( ea0 ); + fc->SetF( ea0 ); } } } } - + } @@ -676,13 +675,13 @@ static void MakePureByCatmullClark(MeshType &m){ // Stops at maxDist or at the distance when a triangle is found static FaceType * MarkEdgeDistance(MeshType &m, FaceType *startF, int maxDist){ assert(tri::HasPerFaceQuality(m)); - + for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { fi->Q()=maxDist; } FaceType * firstTriangleFound = NULL; - + startF->Q() = 0; std::vector stack; int stackPos=0; @@ -707,65 +706,65 @@ static FaceType * MarkEdgeDistance(MeshType &m, FaceType *startF, int maxDist){ /* given a tri-quad mesh, - uses edge rotates to make a tri move toward another tri and to merges them into a quad. + uses edge rotates to make a tri move toward another tri and to merges them into a quad. Retunrs number of surviving triangles (0, or 1), or -1 if not done yet. StepbyStep: makes just one step! use it in a loop as long as it returns 0 or 1. - + maxdist is the maximal edge distance where to look for a companion triangle */ static int MakePureByFlipStepByStep(MeshType &m, int maxdist=10000, int restart=false){ - + static FaceType *ta, *tb; // faces to be matched into a quad - + static int step = 0; // hack - + if (restart) { step=0; return false; } if (step==0) { - + // find a triangular face ta ta = NULL; for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) if (!fi->IsD()) { if (!fi->IsAnyF()) { ta=&*fi; break; } } if (!ta) return 0; // success: no triangle left (done?) - - + + tb = MarkEdgeDistance(m,ta,maxdist); if (!tb) return 1; // fail: no matching triagle found (increase maxdist?) - + step=1; - + } else { int marriageEdge=-1; bool done = false; while (!done) { - + int bestScore = int(tb->Q()); int edge = -1; bool mustDoFlip; - + // select which edge to use for (int k=0; k<3; k++) { if (tb->FFp(k) == tb) continue; // border - + FaceType* tbk = tb->FFp(k); - + if (!tbk->IsAnyF()) {done=true; marriageEdge=k; break; } // found my match - + int back = tb->FFi(k); int faux = BQ::FauxIndex(tbk); int other = 3-back-faux; - + int scoreA = int(tbk->FFp(other)->Q()); - + FaceType* tbh = tbk->FFp(faux); int fauxh = BQ::FauxIndex(tbh); - + int scoreB = int(tbh->FFp( (fauxh+1)%3 )->Q()); int scoreC = int(tbh->FFp( (fauxh+2)%3 )->Q()); - + int scoreABC = std::min( scoreC, std::min( scoreA, scoreB ) ); if (scoreABCFFp(edge)) ); } - + FaceType* next = tb->FFp(edge)->FFp( BQ::FauxIndex(tb->FFp(edge)) ); - + // create new edge next->ClearAllF(); tb->FFp(edge)->ClearAllF(); - + // dissolve old edge tb->SetF(edge); tb->FFp(edge)->SetF( tb->FFi(edge) ); tb->FFp(edge)->Q() = tb->Q(); - + tb = next; -break; +break; } - + if (marriageEdge!=-1) { // consume the marriage (two tris = one quad) assert(!(tb->IsAnyF())); assert(!(tb->FFp(marriageEdge)->IsAnyF())); tb->SetF(marriageEdge); tb->FFp(marriageEdge)->SetF(tb->FFi(marriageEdge)); - + step=0; } -} +} return -1; // not done yet } /* given a tri-quad mesh, - uses edge rotates to make a tri move toward another tri and to merges them into a quad. + uses edge rotates to make a tri move toward another tri and to merges them into a quad. - maxdist is the maximal edge distance where to look for a companion triangle - retunrs true if all triangles are merged (always, unless they are odd, or maxdist not enough). */ @@ -825,18 +824,18 @@ static bool MakePureByFlip(MeshType &m, int maxdist=10000) /** given a triangle mesh, makes it quad dominant by merging triangle pairs into quads - various euristics: + various euristics: level = 0: maximally greedy. Leaves fewest triangles level = 1: smarter: leaves more triangles, but makes better quality quads level = 2: even more so (marginally) */ static void MakeDominant(MeshType &m, int level){ - + for (FaceIterator fi = m.face.begin(); fi!=m.face.end(); fi++) { fi->ClearAllF(); fi->Q() = 0; } - + MakeDominantPass (m); if (level>0) MakeDominantPass (m); diff --git a/vcg/complex/algorithms/bitquad_support.h b/vcg/complex/algorithms/bitquad_support.h index 0810a096..de1a1d5e 100644 --- a/vcg/complex/algorithms/bitquad_support.h +++ b/vcg/complex/algorithms/bitquad_support.h @@ -1,7 +1,5 @@ #ifndef VCG_BITQUAD_SUPPORT #define VCG_BITQUAD_SUPPORT -#include -#include #include #include #include @@ -811,8 +809,8 @@ static bool CollapseDiag(FaceType &f, ScalarType interpol, MeshType& m, Pos* aff pf = t; } while ((pf!=fb)); - pi = fauxb; - pf = fb; + pi = fauxb; + pf = fb; do { pf->V(pi) = va; diff --git a/vcg/complex/algorithms/clean.h b/vcg/complex/algorithms/clean.h index dd0c18bc..e8840123 100644 --- a/vcg/complex/algorithms/clean.h +++ b/vcg/complex/algorithms/clean.h @@ -24,12 +24,6 @@ #ifndef __VCGLIB_CLEAN #define __VCGLIB_CLEAN -// Standard headers -#include -#include -#include -#include - // VCG headers #include #include @@ -37,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -142,58 +135,58 @@ public: }; - /** This function removes all duplicate vertices of the mesh by looking only at their spatial positions. - Note that it does not update any topology relation that could be affected by this like the VT or TT relation. - the reason this function is usually performed BEFORE building any topology information. - */ - static int RemoveDuplicateVertex( MeshType & m, bool RemoveDegenerateFlag=true) // V1.0 - { - if(m.vert.size()==0 || m.vn==0) return 0; + /** This function removes all duplicate vertices of the mesh by looking only at their spatial positions. + Note that it does not update any topology relation that could be affected by this like the VT or TT relation. + the reason this function is usually performed BEFORE building any topology information. + */ + static int RemoveDuplicateVertex( MeshType & m, bool RemoveDegenerateFlag=true) // V1.0 + { + if(m.vert.size()==0 || m.vn==0) return 0; - std::map mp; - size_t i,j; - VertexIterator vi; - int deleted=0; - int k=0; - size_t num_vert = m.vert.size(); - std::vector perm(num_vert); - for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k) - perm[k] = &(*vi); + std::map mp; + size_t i,j; + VertexIterator vi; + int deleted=0; + int k=0; + size_t num_vert = m.vert.size(); + std::vector perm(num_vert); + for(vi=m.vert.begin(); vi!=m.vert.end(); ++vi, ++k) + perm[k] = &(*vi); - RemoveDuplicateVert_Compare c_obj; + RemoveDuplicateVert_Compare c_obj; - std::sort(perm.begin(),perm.end(),c_obj); + std::sort(perm.begin(),perm.end(),c_obj); - j = 0; - i = j; - mp[perm[i]] = perm[j]; - ++i; - for(;i!=num_vert;) - { - if( (! (*perm[i]).IsD()) && - (! (*perm[j]).IsD()) && - (*perm[i]).P() == (*perm[j]).cP() ) - { - VertexPointer t = perm[i]; - mp[perm[i]] = perm[j]; - ++i; - Allocator::DeleteVertex(m,*t); - deleted++; - } - else - { - j = i; - ++i; - } - } + j = 0; + i = j; + mp[perm[i]] = perm[j]; + ++i; + for(;i!=num_vert;) + { + if( (! (*perm[i]).IsD()) && + (! (*perm[j]).IsD()) && + (*perm[i]).P() == (*perm[j]).cP() ) + { + VertexPointer t = perm[i]; + mp[perm[i]] = perm[j]; + ++i; + Allocator::DeleteVertex(m,*t); + deleted++; + } + else + { + j = i; + ++i; + } + } - for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi) - if( !(*fi).IsD() ) - for(k = 0; k < 3; ++k) - if( mp.find( (typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() ) - { - (*fi).V(k) = &*mp[ (*fi).V(k) ]; - } + for(FaceIterator fi = m.face.begin(); fi!=m.face.end(); ++fi) + if( !(*fi).IsD() ) + for(k = 0; k < 3; ++k) + if( mp.find( (typename MeshType::VertexPointer)(*fi).V(k) ) != mp.end() ) + { + (*fi).V(k) = &*mp[ (*fi).V(k) ]; + } for(EdgeIterator ei = m.edge.begin(); ei!=m.edge.end(); ++ei) @@ -211,163 +204,163 @@ public: return deleted; } - class SortedPair - { - public: - SortedPair() {} - SortedPair(unsigned int v0, unsigned int v1, EdgePointer _fp) - { - v[0]=v0;v[1]=v1; - fp=_fp; - if(v[0]>v[1]) std::swap(v[0],v[1]); - } - bool operator < (const SortedPair &p) const - { - return (v[1]!=p.v[1])?(v[1]v[1]) std::swap(v[0],v[1]); + } + bool operator < (const SortedPair &p) const + { + return (v[1]!=p.v[1])?(v[1] fvec; - for(fi=m.face.begin();fi!=m.face.end();++fi) - if(!(*fi).IsD()) - { - fvec.push_back(SortedTriple( tri::Index(m,(*fi).V(0)), - tri::Index(m,(*fi).V(1)), - tri::Index(m,(*fi).V(2)), - &*fi)); - } - assert (size_t(m.fn) == fvec.size()); - //for(int i=0;i::DeleteFace(m, *(fvec[i].fp) ); - //qDebug("deleting face %i (pos in fvec %i)",tri::Index(m,fvec[i].fp) ,i); - } - } - return total; - } + /** This function removes all duplicate faces of the mesh by looking only at their vertex reference. + So it should be called after unification of vertices. + Note that it does not update any topology relation that could be affected by this like the VT or TT relation. + the reason this function is usually performed BEFORE building any topology information. + */ + static int RemoveDuplicateFace( MeshType & m) // V1.0 + { + FaceIterator fi; + std::vector fvec; + for(fi=m.face.begin();fi!=m.face.end();++fi) + if(!(*fi).IsD()) + { + fvec.push_back(SortedTriple( tri::Index(m,(*fi).V(0)), + tri::Index(m,(*fi).V(1)), + tri::Index(m,(*fi).V(2)), + &*fi)); + } + assert (size_t(m.fn) == fvec.size()); + //for(int i=0;i::DeleteFace(m, *(fvec[i].fp) ); + //qDebug("deleting face %i (pos in fvec %i)",tri::Index(m,fvec[i].fp) ,i); + } + } + return total; + } - /** This function removes all duplicate faces of the mesh by looking only at their vertex reference. - So it should be called after unification of vertices. - Note that it does not update any topology relation that could be affected by this like the VT or TT relation. - the reason this function is usually performed BEFORE building any topology information. - */ - static int RemoveDuplicateEdge( MeshType & m) // V1.0 - { - //assert(m.fn == 0 && m.en >0); // just to be sure we are using an edge mesh... - if (m.en==0)return 0; - std::vector eVec; - for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) - if(!(*ei).IsD()) - { - eVec.push_back(SortedPair( tri::Index(m,(*ei).V(0)), tri::Index(m,(*ei).V(1)), &*ei)); - } - assert (size_t(m.en) == eVec.size()); - //for(int i=0;i::DeleteEdge(m, *(eVec[i].fp) ); - //qDebug("deleting face %i (pos in fvec %i)",tri::Index(m,fvec[i].fp) ,i); - } - } - return total; - } - static int CountUnreferencedVertex( MeshType& m) - { - return RemoveUnreferencedVertex(m,false); - } + /** This function removes all duplicate faces of the mesh by looking only at their vertex reference. + So it should be called after unification of vertices. + Note that it does not update any topology relation that could be affected by this like the VT or TT relation. + the reason this function is usually performed BEFORE building any topology information. + */ + static int RemoveDuplicateEdge( MeshType & m) // V1.0 + { + //assert(m.fn == 0 && m.en >0); // just to be sure we are using an edge mesh... + if (m.en==0)return 0; + std::vector eVec; + for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) + if(!(*ei).IsD()) + { + eVec.push_back(SortedPair( tri::Index(m,(*ei).V(0)), tri::Index(m,(*ei).V(1)), &*ei)); + } + assert (size_t(m.en) == eVec.size()); + //for(int i=0;i::DeleteEdge(m, *(eVec[i].fp) ); + //qDebug("deleting face %i (pos in fvec %i)",tri::Index(m,fvec[i].fp) ,i); + } + } + return total; + } + static int CountUnreferencedVertex( MeshType& m) + { + return RemoveUnreferencedVertex(m,false); + } - /** This function removes that are not referenced by any face. The function updates the vn counter. - @param m The mesh - @return The number of removed vertices - */ - static int RemoveUnreferencedVertex( MeshType& m, bool DeleteVertexFlag=true) // V1.0 - { - FaceIterator fi; - EdgeIterator ei; - VertexIterator vi; - int referredBit = VertexType::NewBitFlag(); + /** This function removes that are not referenced by any face. The function updates the vn counter. + @param m The mesh + @return The number of removed vertices + */ + static int RemoveUnreferencedVertex( MeshType& m, bool DeleteVertexFlag=true) // V1.0 + { + FaceIterator fi; + EdgeIterator ei; + VertexIterator vi; + int referredBit = VertexType::NewBitFlag(); - int j; - int deleted = 0; + int j; + int deleted = 0; - for(vi=m.vert.begin();vi!=m.vert.end();++vi) - (*vi).ClearUserBit(referredBit); + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + (*vi).ClearUserBit(referredBit); - for(fi=m.face.begin();fi!=m.face.end();++fi) - if( !(*fi).IsD() ) - for(j=0;j<3;++j) - (*fi).V(j)->SetUserBit(referredBit); + for(fi=m.face.begin();fi!=m.face.end();++fi) + if( !(*fi).IsD() ) + for(j=0;j<3;++j) + (*fi).V(j)->SetUserBit(referredBit); - for(ei=m.edge.begin();ei!=m.edge.end();++ei) - if( !(*ei).IsD() ){ - (*ei).V(0)->SetUserBit(referredBit); - (*ei).V(1)->SetUserBit(referredBit); - } + for(ei=m.edge.begin();ei!=m.edge.end();++ei) + if( !(*ei).IsD() ){ + (*ei).V(0)->SetUserBit(referredBit); + (*ei).V(1)->SetUserBit(referredBit); + } - for(vi=m.vert.begin();vi!=m.vert.end();++vi) - if( (!(*vi).IsD()) && (!(*vi).IsUserBit(referredBit))) - { - if(DeleteVertexFlag) Allocator::DeleteVertex(m,*vi); - ++deleted; - } - VertexType::DeleteBitFlag(referredBit); - return deleted; - } + for(vi=m.vert.begin();vi!=m.vert.end();++vi) + if( (!(*vi).IsD()) && (!(*vi).IsUserBit(referredBit))) + { + if(DeleteVertexFlag) Allocator::DeleteVertex(m,*vi); + ++deleted; + } + VertexType::DeleteBitFlag(referredBit); + return deleted; + } /** Degenerate vertices are vertices that have coords with invalid floating point values, @@ -378,29 +371,29 @@ public: VertexIterator vi; int count_vd = 0; - for(vi=m.vert.begin(); vi!=m.vert.end();++vi) - if(math::IsNAN( (*vi).P()[0]) || - math::IsNAN( (*vi).P()[1]) || - math::IsNAN( (*vi).P()[2]) ) - { - count_vd++; - Allocator::DeleteVertex(m,*vi); - } + for(vi=m.vert.begin(); vi!=m.vert.end();++vi) + if(math::IsNAN( (*vi).P()[0]) || + math::IsNAN( (*vi).P()[1]) || + math::IsNAN( (*vi).P()[2]) ) + { + count_vd++; + Allocator::DeleteVertex(m,*vi); + } - FaceIterator fi; - int count_fd = 0; + FaceIterator fi; + int count_fd = 0; - for(fi=m.face.begin(); fi!=m.face.end();++fi) - if(!(*fi).IsD()) - if( (*fi).V(0)->IsD() || - (*fi).V(1)->IsD() || - (*fi).V(2)->IsD() ) - { - count_fd++; - Allocator::DeleteFace(m,*fi); - } - return count_vd; - } + for(fi=m.face.begin(); fi!=m.face.end();++fi) + if(!(*fi).IsD()) + if( (*fi).V(0)->IsD() || + (*fi).V(1)->IsD() || + (*fi).V(2)->IsD() ) + { + count_fd++; + Allocator::DeleteFace(m,*fi); + } + return count_vd; + } /** Degenerate faces are faces that are Topologically degenerate, @@ -414,19 +407,19 @@ public: { int count_fd = 0; - for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi) - if(!(*fi).IsD()) - { - if((*fi).V(0) == (*fi).V(1) || - (*fi).V(0) == (*fi).V(2) || - (*fi).V(1) == (*fi).V(2) ) - { - count_fd++; - Allocator::DeleteFace(m,*fi); - } - } - return count_fd; - } + for(FaceIterator fi=m.face.begin(); fi!=m.face.end();++fi) + if(!(*fi).IsD()) + { + if((*fi).V(0) == (*fi).V(1) || + (*fi).V(0) == (*fi).V(2) || + (*fi).V(1) == (*fi).V(2) ) + { + count_fd++; + Allocator::DeleteFace(m,*fi); + } + } + return count_fd; + } static int RemoveDegenerateEdge(MeshType& m) { @@ -444,25 +437,25 @@ public: return count_ed; } - static int RemoveNonManifoldVertex(MeshType& m) - { - /*int count_vd = */ - CountNonManifoldVertexFF(m,true); - /*int count_fd = */ - tri::UpdateSelection::FaceFromVertexLoose(m); - int count_removed = 0; - FaceIterator fi; - for(fi=m.face.begin(); fi!=m.face.end();++fi) - if(!(*fi).IsD() && (*fi).IsS()) - Allocator::DeleteFace(m,*fi); - VertexIterator vi; - for(vi=m.vert.begin(); vi!=m.vert.end();++vi) - if(!(*vi).IsD() && (*vi).IsS()) { - ++count_removed; - Allocator::DeleteVertex(m,*vi); - } - return count_removed; - } + static int RemoveNonManifoldVertex(MeshType& m) + { + /*int count_vd = */ + CountNonManifoldVertexFF(m,true); + /*int count_fd = */ + tri::UpdateSelection::FaceFromVertexLoose(m); + int count_removed = 0; + FaceIterator fi; + for(fi=m.face.begin(); fi!=m.face.end();++fi) + if(!(*fi).IsD() && (*fi).IsS()) + Allocator::DeleteFace(m,*fi); + VertexIterator vi; + for(vi=m.vert.begin(); vi!=m.vert.end();++vi) + if(!(*vi).IsD() && (*vi).IsS()) { + ++count_removed; + Allocator::DeleteVertex(m,*vi); + } + return count_removed; + } /// Removal of faces that were incident on a non manifold edge. @@ -547,16 +540,16 @@ public: int count_fd = 0; std::vector ToDelVec; - for(fi=m.face.begin(); fi!=m.face.end();++fi) - if (!fi->IsD()) - { - if ((!IsManifold(*fi,0))|| - (!IsManifold(*fi,1))|| - (!IsManifold(*fi,2))) - ToDelVec.push_back(&*fi); - } + for(fi=m.face.begin(); fi!=m.face.end();++fi) + if (!fi->IsD()) + { + if ((!IsManifold(*fi,0))|| + (!IsManifold(*fi,1))|| + (!IsManifold(*fi,2))) + ToDelVec.push_back(&*fi); + } - std::sort(ToDelVec.begin(),ToDelVec.end(),CompareAreaFP()); + std::sort(ToDelVec.begin(),ToDelVec.end(),CompareAreaFP()); for(size_t i=0;i(m,MinAreaThr,MaxAreaThr); } - /** - * Is the mesh only composed by quadrilaterals? - */ - static bool IsBitQuadOnly(const MeshType &m) - { - typedef typename MeshType::FaceType F; - tri::RequirePerFaceFlags(m); - for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { - unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2); - if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2) return false; - } - return true; - } + /** + * Is the mesh only composed by quadrilaterals? + */ + static bool IsBitQuadOnly(const MeshType &m) + { + typedef typename MeshType::FaceType F; + tri::RequirePerFaceFlags(m); + for (ConstFaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) { + unsigned int tmp = fi->Flags()&(F::FAUX0|F::FAUX1|F::FAUX2); + if ( tmp != F::FAUX0 && tmp != F::FAUX1 && tmp != F::FAUX2) return false; + } + return true; + } /** @@ -875,17 +868,17 @@ public: RequireFFAdjacency(m); if(selectVert) UpdateSelection::VertexClear(m); - int nonManifoldCnt=0; - SimpleTempData TD(m.vert,0); + int nonManifoldCnt=0; + SimpleTempData TD(m.vert,0); - // First Loop, just count how many faces are incident on a vertex and store it in the TemporaryData Counter. - FaceIterator fi; - for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) - { - TD[(*fi).V(0)]++; - TD[(*fi).V(1)]++; - TD[(*fi).V(2)]++; - } + // First Loop, just count how many faces are incident on a vertex and store it in the TemporaryData Counter. + FaceIterator fi; + for (fi = m.face.begin(); fi != m.face.end(); ++fi) if (!fi->IsD()) + { + TD[(*fi).V(0)]++; + TD[(*fi).V(1)]++; + TD[(*fi).V(2)]++; + } tri::UpdateFlags::VertexClearV(m); // Second Loop. @@ -908,65 +901,65 @@ public: int starSizeFF = pos.NumberOfIncidentFaces(); - if (starSizeFF != TD[(*fi).V(i)]) - { - if(selectVert) (*fi).V(i)->SetS(); - nonManifoldCnt++; - } - } - } - return nonManifoldCnt; - } + if (starSizeFF != TD[(*fi).V(i)]) + { + if(selectVert) (*fi).V(i)->SetS(); + nonManifoldCnt++; + } + } + } + return nonManifoldCnt; + } - static void CountEdges( MeshType & m, int &count_e, int &boundary_e ) - { - tri::RequireFFAdjacency(m); - count_e=0; - boundary_e=0; - UpdateFlags::FaceClearV(m); - bool counted =false; - for(FaceIterator fi=m.face.begin();fi!=m.face.end();fi++) - { - if(!((*fi).IsD())) - { - (*fi).SetV(); - count_e +=3; //assume that we have to increase the number of edges with three - for(int j=0; j<3; j++) - { - if (face::IsBorder(*fi,j)) //If this edge is a border edge - boundary_e++; // then increase the number of boundary edges - else if (IsManifold(*fi,j))//If this edge is manifold - { - if((*fi).FFp(j)->IsV()) //If the face on the other side of the edge is already selected - count_e--; // we counted one edge twice - } - else//We have a non-manifold edge - { - vcg::face::Pos hei(&(*fi), j , fi->V(j)); - vcg::face::Pos he=hei; - he.NextF(); - while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge - { - if (he.f->IsV())// if one of the other faces was already visited than this edge was counted already. - { - counted=true; - break; - } - else - { - he.NextF(); - } - } - if (counted) - { - count_e--; - counted=false; - } - } - } - } - } - } + static void CountEdges( MeshType & m, int &count_e, int &boundary_e ) + { + tri::RequireFFAdjacency(m); + count_e=0; + boundary_e=0; + UpdateFlags::FaceClearV(m); + bool counted =false; + for(FaceIterator fi=m.face.begin();fi!=m.face.end();fi++) + { + if(!((*fi).IsD())) + { + (*fi).SetV(); + count_e +=3; //assume that we have to increase the number of edges with three + for(int j=0; j<3; j++) + { + if (face::IsBorder(*fi,j)) //If this edge is a border edge + boundary_e++; // then increase the number of boundary edges + else if (IsManifold(*fi,j))//If this edge is manifold + { + if((*fi).FFp(j)->IsV()) //If the face on the other side of the edge is already selected + count_e--; // we counted one edge twice + } + else//We have a non-manifold edge + { + vcg::face::Pos hei(&(*fi), j , fi->V(j)); + vcg::face::Pos he=hei; + he.NextF(); + while (he.f!=hei.f)// so we have to iterate all faces that are connected to this edge + { + if (he.f->IsV())// if one of the other faces was already visited than this edge was counted already. + { + counted=true; + break; + } + else + { + he.NextF(); + } + } + if (counted) + { + count_e--; + counted=false; + } + } + } + } + } + } static int CountHoles( MeshType & m) @@ -1076,114 +1069,114 @@ public: } - /** - GENUS. + /** + GENUS. - A topologically invariant property of a surface defined as - the largest number of non-intersecting simple closed curves that can be - drawn on the surface without separating it. + A topologically invariant property of a surface defined as + the largest number of non-intersecting simple closed curves that can be + drawn on the surface without separating it. - Roughly speaking, it is the number of holes in a surface. - The genus g of a closed surface, also called the geometric genus, is related to the - Euler characteristic by the relation $chi$ by $chi==2-2g$. + Roughly speaking, it is the number of holes in a surface. + The genus g of a closed surface, also called the geometric genus, is related to the + Euler characteristic by the relation $chi$ by $chi==2-2g$. - The genus of a connected, orientable surface is an integer representing the maximum - number of cuttings along closed simple curves without rendering the resultant - manifold disconnected. It is equal to the number of handles on it. + The genus of a connected, orientable surface is an integer representing the maximum + number of cuttings along closed simple curves without rendering the resultant + manifold disconnected. It is equal to the number of handles on it. - For general polyhedra the Euler Formula is: + For general polyhedra the Euler Formula is: - V - E + F = 2 - 2G - B + V - E + F = 2 - 2G - B - where V is the number of vertices, F is the number of faces, E is the - number of edges, G is the genus and B is the number of boundary polygons. + where V is the number of vertices, F is the number of faces, E is the + number of edges, G is the genus and B is the number of boundary polygons. - The above formula is valid for a mesh with one single connected component. - By considering multiple connected components the formula becomes: + The above formula is valid for a mesh with one single connected component. + By considering multiple connected components the formula becomes: - V - E + F = 2C - 2Gs - B -> 2Gs = - ( V-E+F +B -2C) + V - E + F = 2C - 2Gs - B -> 2Gs = - ( V-E+F +B -2C) - where C is the number of connected components and Gs is the sum of - the genus of all connected components. + where C is the number of connected components and Gs is the sum of + the genus of all connected components. - Note that in the case of a mesh with boundaries the intuitive meaning of Genus is less intuitive that it could seem. - A closed sphere, a sphere with one hole (e.g. a disk) and a sphere with two holes (e.g. a tube) all of them have Genus == 0 + Note that in the case of a mesh with boundaries the intuitive meaning of Genus is less intuitive that it could seem. + A closed sphere, a sphere with one hole (e.g. a disk) and a sphere with two holes (e.g. a tube) all of them have Genus == 0 - */ + */ - static int MeshGenus(int nvert,int nedges,int nfaces, int numholes, int numcomponents) - { - return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2); - } + static int MeshGenus(int nvert,int nedges,int nfaces, int numholes, int numcomponents) + { + return -((nvert + nfaces - nedges + numholes - 2 * numcomponents) / 2); + } - static int MeshGenus(MeshType &m) - { - int nvert=m.vn; - int nfaces=m.fn; - int boundary_e,nedges; - CountEdges(m,nedges,boundary_e); - int numholes=CountHoles(m); - int numcomponents=CountConnectedComponents(m); - int G=MeshGenus(nvert,nedges,nfaces,numholes,numcomponents); - return G; - } + static int MeshGenus(MeshType &m) + { + int nvert=m.vn; + int nfaces=m.fn; + int boundary_e,nedges; + CountEdges(m,nedges,boundary_e); + int numholes=CountHoles(m); + int numcomponents=CountConnectedComponents(m); + int G=MeshGenus(nvert,nedges,nfaces,numholes,numcomponents); + return G; + } - /** - * Check if the given mesh is regular, semi-regular or irregular. - * - * Each vertex of a \em regular mesh has valence 6 except for border vertices - * which have valence 4. - * - * A \em semi-regular mesh is derived from an irregular one applying - * 1-to-4 subdivision recursively. (not checked for now) - * - * All other meshes are \em irregular. - */ - static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular) - { - RequireVFAdjacency(m); - Regular = true; + /** + * Check if the given mesh is regular, semi-regular or irregular. + * + * Each vertex of a \em regular mesh has valence 6 except for border vertices + * which have valence 4. + * + * A \em semi-regular mesh is derived from an irregular one applying + * 1-to-4 subdivision recursively. (not checked for now) + * + * All other meshes are \em irregular. + */ + static void IsRegularMesh(MeshType &m, bool &Regular, bool &Semiregular) + { + RequireVFAdjacency(m); + Regular = true; - VertexIterator vi; + VertexIterator vi; - // for each vertex the number of edges are count - for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) - { - if (!vi->IsD()) - { - face::Pos he((*vi).VFp(), &*vi); - face::Pos ht = he; + // for each vertex the number of edges are count + for (vi = m.vert.begin(); vi != m.vert.end(); ++vi) + { + if (!vi->IsD()) + { + face::Pos he((*vi).VFp(), &*vi); + face::Pos ht = he; - int n=0; - bool border=false; - do - { - ++n; - ht.NextE(); - if (ht.IsBorder()) - border=true; - } - while (ht != he); + int n=0; + bool border=false; + do + { + ++n; + ht.NextE(); + if (ht.IsBorder()) + border=true; + } + while (ht != he); - if (border) - n = n/2; + if (border) + n = n/2; - if ((n != 6)&&(!border && n != 4)) - { - Regular = false; - break; - } - } - } + if ((n != 6)&&(!border && n != 4)) + { + Regular = false; + break; + } + } + } - if (!Regular) - Semiregular = false; - else - { - // For now we do not account for semi-regularity - Semiregular = false; - } - } + if (!Regular) + Semiregular = false; + else + { + // For now we do not account for semi-regularity + Semiregular = false; + } + } static bool IsCoherentlyOrientedMesh(MeshType &m) @@ -1382,12 +1375,12 @@ public: } - static int RemoveTVertexByFlip(MeshType &m, float threshold=40, bool repeat=true) - { - RequireFFAdjacency(m); - RequirePerVertexMark(m); - //Counters for logging and convergence - int count, total = 0; + static int RemoveTVertexByFlip(MeshType &m, float threshold=40, bool repeat=true) + { + RequireFFAdjacency(m); + RequirePerVertexMark(m); + //Counters for logging and convergence + int count, total = 0; do { tri::UpdateTopology::FaceFace(m); @@ -1430,11 +1423,11 @@ public: return total; } - static int RemoveTVertexByCollapse(MeshType &m, float threshold=40, bool repeat=true) - { - RequirePerVertexMark(m); - //Counters for logging and convergence - int count, total = 0; + static int RemoveTVertexByCollapse(MeshType &m, float threshold=40, bool repeat=true) + { + RequirePerVertexMark(m); + //Counters for logging and convergence + int count, total = 0; do { tri::UnMarkAll(m); @@ -1468,42 +1461,42 @@ public: return total; } - static bool SelfIntersections(MeshType &m, std::vector &ret) - { - RequirePerFaceMark(m); - ret.clear(); - int referredBit = FaceType::NewBitFlag(); - tri::UpdateFlags::FaceClear(m,referredBit); + static bool SelfIntersections(MeshType &m, std::vector &ret) + { + RequirePerFaceMark(m); + ret.clear(); + int referredBit = FaceType::NewBitFlag(); + tri::UpdateFlags::FaceClear(m,referredBit); - TriMeshGrid gM; - gM.Set(m.face.begin(),m.face.end()); + TriMeshGrid gM; + gM.Set(m.face.begin(),m.face.end()); - for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) - { - (*fi).SetUserBit(referredBit); - Box3< ScalarType> bbox; - (*fi).GetBBox(bbox); - std::vector inBox; - vcg::tri::GetInBoxFace(m, gM, bbox,inBox); - bool Intersected=false; - typename std::vector::iterator fib; - for(fib=inBox.begin();fib!=inBox.end();++fib) - { - if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) ) - if(Clean::TestFaceFaceIntersection(&*fi,*fib)){ - ret.push_back(*fib); - if(!Intersected) { - ret.push_back(&*fi); - Intersected=true; - } - } - } - inBox.clear(); - } + for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD()) + { + (*fi).SetUserBit(referredBit); + Box3< ScalarType> bbox; + (*fi).GetBBox(bbox); + std::vector inBox; + vcg::tri::GetInBoxFace(m, gM, bbox,inBox); + bool Intersected=false; + typename std::vector::iterator fib; + for(fib=inBox.begin();fib!=inBox.end();++fib) + { + if(!(*fib)->IsUserBit(referredBit) && (*fib != &*fi) ) + if(Clean::TestFaceFaceIntersection(&*fi,*fib)){ + ret.push_back(*fib); + if(!Intersected) { + ret.push_back(&*fi); + Intersected=true; + } + } + } + inBox.clear(); + } - FaceType::DeleteBitFlag(referredBit); - return (ret.size()>0); - } + FaceType::DeleteBitFlag(referredBit); + return (ret.size()>0); + } /** This function simply test that the vn and fn counters be consistent with the size of the containers and the number of deleted simplexes. @@ -1748,9 +1741,9 @@ static std::pair RemoveHugeConnectedComponentsDiameter(MeshType &m, Sca return std::make_pair(TotalCC,DeletedCC); } - }; // end class - /*@}*/ + }; // end class + /*@}*/ - } //End Namespace Tri + } //End Namespace Tri } // End Namespace vcg #endif diff --git a/vcg/complex/algorithms/create/advancing_front.h b/vcg/complex/algorithms/create/advancing_front.h index 070b97f9..f4a97c8b 100644 --- a/vcg/complex/algorithms/create/advancing_front.h +++ b/vcg/complex/algorithms/create/advancing_front.h @@ -15,27 +15,27 @@ namespace vcg { * v0, v1 the active edge * v2 internal vertex */ -class FrontEdge { - public: - int v0, v1, v2; //v0, v1 represent the FrontEdge, v2 the other vertex - //in the face this FrontEdge belongs to +class FrontEdge { + public: + int v0, v1, v2; //v0, v1 represent the FrontEdge, v2 the other vertex + //in the face this FrontEdge belongs to bool active; //keep tracks of wether it is in front or in deads - + //the loops in the front are mantained as a double linked list - std::list::iterator next; + std::list::iterator next; std::list::iterator previous; - + FrontEdge() {} FrontEdge(int _v0, int _v1, int _v2): v0(_v0), v1(_v1), v2(_v2), active(true) { assert(v0 != v1 && v1 != v2 && v0 != v2); } - + bool operator==(const FrontEdge& f) const - { - return ((v0 == f.v0) && (v1 == f.v1) && (v2 == f.v2) ); - } -}; + { + return ((v0 == f.v0) && (v1 == f.v1) && (v2 == f.v2) ); + } +}; template class AdvancingFront { public: @@ -45,58 +45,58 @@ template class AdvancingFront { typedef typename MESH::FaceIterator FaceIterator; typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexType::CoordType Point3x; - + //class FrontEdgeLists //{ //}; - + // protected: - std::list front; + std::list front; std::list deads; std::vector nb; //number of fronts a vertex is into, //this is used for the Visited and Border flags //but adding topology may not be needed anymore public: - + MESH &mesh; //this structure will be filled by the algorithm - + AdvancingFront(MESH &_mesh): mesh(_mesh) { - - UpdateFlags::FaceBorderFromNone(mesh); - UpdateFlags::VertexBorderFromFace(mesh); + + UpdateFlags::FaceBorderFromNone(mesh); + UpdateFlags::VertexBorderFromFace(mesh); nb.clear(); nb.resize(mesh.vert.size(), 0); - + CreateLoops(); } virtual ~AdvancingFront() {} - + void BuildMesh(CallBackPos call = NULL, int interval = 512) { float finalfacesext = mesh.vert.size() * 2.0f; - if(call) call(0, "Advancing front"); - while(1) { - + if(call) call(0, "Advancing front"); + while(1) { + for(int i = 0; i < interval; i++) { if(!front.size() && !SeedFace()) return; AddFace(); - if(call) - { - float rap = float(mesh.face.size()) / finalfacesext; - int perc = (int) (100.0f * rap); - (*call)(perc,"Adding Faces"); - } + if(call) + { + float rap = float(mesh.face.size()) / finalfacesext; + int perc = (int) (100.0f * rap); + (*call)(perc,"Adding Faces"); + } } } - } - + } + protected: - //Implement these functions in your subclass + //Implement these functions in your subclass enum ListID {FRONT,DEADS}; typedef std::pair< ListID,std::list::iterator > ResultIterator; virtual bool Seed(int &v0, int &v1, int &v2) = 0; @@ -109,20 +109,20 @@ protected: { for(size_t i = 0; i < mesh.face.size(); i++) { - FaceType &f = mesh.face[i]; + FaceType &f = mesh.face[i]; if(f.IsD()) continue; - + for(int k = 0; k < 3; k++) { if(f.IsB(k)) { addNewEdge(FrontEdge(tri::Index(mesh,f.V0(k)),tri::Index(mesh,f.V1(k)),tri::Index(mesh,f.V2(k))) ); nb[tri::Index(mesh,f.V0(k))]++; - } + } } } - + for(std::list::iterator s = front.begin(); s != front.end(); s++) { (*s).previous = front.end(); - (*s).next = front.end(); + (*s).next = front.end(); } //now create loops: for(std::list::iterator s = front.begin(); s != front.end(); s++) { @@ -131,90 +131,90 @@ protected: if((*s).v1 != (*j).v0) continue; if((*j).previous != front.end()) continue; (*s).next = j; - (*j).previous = s; + (*j).previous = s; break; } } - for(std::list::iterator s = front.begin(); s != front.end(); s++) { + for(std::list::iterator s = front.begin(); s != front.end(); s++) { assert((*s).next != front.end()); - assert((*s).previous != front.end()); + assert((*s).previous != front.end()); } - } - + } + bool SeedFace() { int v[3]; bool success = Seed(v[0], v[1], v[2]); if(!success) return false; - + nb.resize(mesh.vert.size(), 0); - - //create the border of the first face + + //create the border of the first face std::list::iterator e = front.end(); std::list::iterator last = e; std::list::iterator first; - + for(int i = 0; i < 3; i++) { int v0 = v[i]; int v1 = v[((i+1)%3)]; int v2 = v[((i+2)%3)]; - + mesh.vert[v0].SetB(); nb[v[i]]++; - + e = front.insert(front.begin(), FrontEdge(v0, v1, v2)); if(i != 0) { - (*last).next = e; + (*last).next = e; (*e).previous = last; } else first = e; - + last = e; - } + } //connect last and first (*last).next = first; (*first).previous = last; - + AddFace(v[0], v[1], v[2]); return true; } - -public: + +public: bool AddFace() { - if(!front.size()) return false; - + if(!front.size()) return false; + std::list::iterator ei = front.begin(); FrontEdge ¤t = *ei; - FrontEdge &previous = *current.previous; - FrontEdge &next = *current.next; - + FrontEdge &previous = *current.previous; + FrontEdge &next = *current.next; + int v0 = current.v0, v1 = current.v1; assert(nb[v0] < 10 && nb[v1] < 10); - + ResultIterator touch; - touch.first = FRONT; - touch.second = front.end(); + touch.first = FRONT; + touch.second = front.end(); int v2 = Place(current, touch); if(v2 == -1) { KillEdge(ei); return false; } - - assert(v2 != v0 && v2 != v1); - - if ((touch.first == FRONT) && (touch.second != front.end()) || - (touch.first == DEADS) && (touch.second != deads.end())) - { - //check for orientation and manifoldness - - //touch == current.previous? - if(v2 == previous.v0) { + assert(v2 != v0 && v2 != v1); + + if ( ( (touch.first == FRONT) && (touch.second != front.end()) ) || + ( (touch.first == DEADS) && (touch.second != deads.end()) ) ) + + { + //check for orientation and manifoldness + + //touch == current.previous? + if(v2 == previous.v0) { if(!CheckEdge(v2, v1)) { KillEdge(ei); return false; - } - /*touching previous FrontEdge (we reuse previous) + } + /*touching previous FrontEdge (we reuse previous) next ------->v2 -----> v1------> \ / @@ -222,9 +222,9 @@ public: previous \ / current \ / v0 */ - + Detach(v0); - + std::list::iterator up = addNewEdge(FrontEdge(v2, v1, v0)); MoveFront(up); (*up).previous = previous.previous; @@ -235,21 +235,21 @@ public: Erase(ei); Glue(up); - //touch == (*current.next).next - } else if(v2 == next.v1) { + //touch == (*current.next).next + } else if(v2 == next.v1) { if(!CheckEdge(v0, v2)) { KillEdge(ei); return false; - } - /*touching next FrontEdge (we reuse next) + } + /*touching next FrontEdge (we reuse next) previous ------->v0 -----> v2------> \ / \ / \ / next \ / - v1 */ - + v1 */ + Detach(v1); std::list::iterator up = addNewEdge(FrontEdge(v0, v2, v1)); MoveFront(up); @@ -264,10 +264,10 @@ public: if(!CheckEdge(v0, v2) || !CheckEdge(v2, v1)) { KillEdge(ei); return false; - } + } //touching some loop: split (or merge it is local does not matter. - //like this - /* + //like this + /* left right <--------v2-<------ /|\ @@ -276,44 +276,44 @@ public: / \ / V ----v0 - - - > v1--------- - current */ + current */ std::list::iterator left = touch.second; - std::list::iterator right = (*touch.second).previous; - + std::list::iterator right = (*touch.second).previous; + //this would be a really bad join if(v1 == (*right).v0 || v0 == (*left).v1) { KillEdge(ei); return false; } - - nb[v2]++; - + + nb[v2]++; + std::list::iterator down = addNewEdge(FrontEdge(v2, v1, v0)); std::list::iterator up = addNewEdge(FrontEdge(v0, v2, v1)); - + (*right).next = down; (*down).previous = right; - + (*down).next = current.next; - next.previous = down; - + next.previous = down; + (*left).previous = up; (*up).next = left; - + (*up).previous = current.previous; previous.next = up; Erase(ei); - } - - - } - else if ((touch.first == FRONT) && (touch.second == front.end()) || - (touch.first == DEADS) && (touch.second == deads.end())) - { + } + + + } + else if (((touch.first == FRONT) && (touch.second == front.end())) || + ((touch.first == DEADS) && (touch.second == deads.end())) ) + { // assert(CheckEdge(v0, v2)); // assert(CheckEdge(v2, v1)); /* adding a new vertex - + v2 /|\ / \ @@ -322,12 +322,12 @@ public: / V ----v0 - - - > v1--------- */ assert(!mesh.vert[v2].IsB()); //fatal error! a new point is already a border? - nb[v2]++; + nb[v2]++; mesh.vert[v2].SetB(); std::list::iterator down = addNewEdge(FrontEdge(v2, v1, v0)); std::list::iterator up = addNewEdge(FrontEdge(v0, v2, v1)); - + (*down).previous = up; (*up).next = down; (*down).next = current.next; @@ -339,11 +339,11 @@ public: AddFace(v0, v2, v1); return false; - } - + } + protected: void AddFace(int v0, int v1, int v2) { - assert(v0 < (int)mesh.vert.size() && v1 < (int)mesh.vert.size() && v2 < (int)mesh.vert.size()); + assert(v0 < (int)mesh.vert.size() && v1 < (int)mesh.vert.size() && v2 < (int)mesh.vert.size()); FaceIterator fi = vcg::tri::Allocator::AddFaces(mesh,1); fi->ClearFlags(); fi->V(0) = &mesh.vert[v0]; @@ -361,17 +361,17 @@ protected: } } } - + void AddVertex(VertexType &vertex) { VertexType *oldstart = NULL; if(mesh.vert.size()) oldstart = &*mesh.vert.begin(); mesh.vert.push_back(vertex); mesh.vn++; VertexType *newstart = &*mesh.vert.begin(); - if(oldstart && oldstart != newstart) { + if(oldstart && oldstart != newstart) { for(int i = 0; i < mesh.face.size(); i++) { FaceType &face = mesh.face[i]; - for(int k = 0; k < 3; k++) + for(int k = 0; k < 3; k++) face.V(k) = newstart + (face.V(k) - oldstart); } } @@ -386,7 +386,7 @@ protected: bool CheckEdge(int v0, int v1) { int tot = 0; VertexType *vv0 = &(mesh.vert[v0]); - VertexType *vv1 = &(mesh.vert[v1]); + VertexType *vv1 = &(mesh.vert[v1]); if(tri::HasVFAdjacency(mesh)) { face::VFIterator vfi(vv0); @@ -401,11 +401,11 @@ protected: } return true; } - for(int i = 0; i < (int)mesh.face.size(); i++) { + for(int i = 0; i < (int)mesh.face.size(); i++) { FaceType &f = mesh.face[i]; for(int k = 0; k < 3; k++) { if(vv0 == f.V0(k) && vv1 == f.V1(k)) //orientation non constistent - return false; + return false; else if(vv1 == f.V0(k) && vv0 == f.V1(k)) ++tot; } if(tot >= 2) { //non manifold @@ -413,71 +413,71 @@ protected: } } return true; - } + } //front management: //Add a new FrontEdge to the back of the queue std::list::iterator addNewEdge(FrontEdge e) { return front.insert(front.end(), e); - } - + } + //move an Edge among the dead ones - void KillEdge(std::list::iterator e) + void KillEdge(std::list::iterator e) { if (e->active) - { - (*e).active = false; - //std::list::iterator res = std::find(front.begin(),front.end(),e); - FrontEdge tmp = *e; - deads.splice(deads.end(), front, e); - std::list::iterator newe = std::find(deads.begin(),deads.end(),tmp); - tmp.previous->next = newe; - tmp.next->previous = newe; - } + { + (*e).active = false; + //std::list::iterator res = std::find(front.begin(),front.end(),e); + FrontEdge tmp = *e; + deads.splice(deads.end(), front, e); + std::list::iterator newe = std::find(deads.begin(),deads.end(),tmp); + tmp.previous->next = newe; + tmp.next->previous = newe; + } } - + void Erase(std::list::iterator e) { if((*e).active) front.erase(e); else deads.erase(e); } - + //move an FrontEdge to the back of the queue void MoveBack(std::list::iterator e) { - front.splice(front.end(), front, e); + front.splice(front.end(), front, e); } - + void MoveFront(std::list::iterator e) { front.splice(front.begin(), front, e); } - + //check if e can be sewed with one of oits neighbours bool Glue(std::list::iterator e) { return Glue((*e).previous, e) || Glue(e, (*e).next); } - + //Glue toghether a and b (where a.next = b bool Glue(std::list::iterator a, std::list::iterator b) { - if((*a).v0 != (*b).v1) return false; - + if((*a).v0 != (*b).v1) return false; + std::list::iterator previous = (*a).previous; std::list::iterator next = (*b).next; (*previous).next = next; (*next).previous = previous; Detach((*a).v1); - Detach((*a).v0); + Detach((*a).v0); Erase(a); - Erase(b); + Erase(b); return true; } - + void Detach(int v) { assert(nb[v] > 0); if(--nb[v] == 0) { - mesh.vert[v].ClearB(); + mesh.vert[v].ClearB(); } - } + } }; - + template class AdvancingTest: public AdvancingFront { public: typedef typename MESH::VertexType VertexType; @@ -487,10 +487,10 @@ template class AdvancingTest: public AdvancingFront { typedef typename MESH::ScalarType ScalarType; typedef typename MESH::VertexType::CoordType Point3x; - + AdvancingTest(MESH &_mesh): AdvancingFront(_mesh) {} - bool Seed(int &v0, int &v1, int &v2) { + bool Seed(int &v0, int &v1, int &v2) { VertexType v[3]; v[0].P() = Point3x(0, 0, 0); v[1].P() = Point3x(1, 0, 0); @@ -507,7 +507,7 @@ template class AdvancingTest: public AdvancingFront { AddVertex(v[2]); return true; } - + int Place(FrontEdge &e, typename AdvancingFront::ResultIterator &touch) { Point3f p[3]; @@ -517,31 +517,31 @@ template class AdvancingTest: public AdvancingFront { Point3f point = p[0] + p[1] - p[2]; int vn = this->mesh.vert.size(); - for(int i = 0; i < this->mesh.vert.size(); i++) - { - if((this->mesh.vert[i].P() - point).Norm() < 0.1) - { - vn = i; - //find the border - assert(this->mesh.vert[i].IsB()); - for(std::list::iterator k = this->front.begin(); k != this->front.end(); k++) - if((*k).v0 == i) - { + for(int i = 0; i < this->mesh.vert.size(); i++) + { + if((this->mesh.vert[i].P() - point).Norm() < 0.1) + { + vn = i; + //find the border + assert(this->mesh.vert[i].IsB()); + for(std::list::iterator k = this->front.begin(); k != this->front.end(); k++) + if((*k).v0 == i) + { touch.first = AdvancingFront::FRONT; - touch.second = k; - } + touch.second = k; + } - for(std::list::iterator k = this->deads.begin(); k != this->deads.end(); k++) - if((*k).v0 == i) - if((*k).v0 == i) - { + for(std::list::iterator k = this->deads.begin(); k != this->deads.end(); k++) + if((*k).v0 == i) + if((*k).v0 == i) + { touch.first = AdvancingFront::FRONT; - touch.second = k; - } - break; + touch.second = k; + } + break; } } - if(vn == this->mesh.vert.size()) { + if(vn == this->mesh.vert.size()) { VertexType v; v.P() = point; v.ClearFlags(); diff --git a/vcg/complex/allocate.h b/vcg/complex/allocate.h index 781348a9..1952ebd5 100644 --- a/vcg/complex/allocate.h +++ b/vcg/complex/allocate.h @@ -20,15 +20,13 @@ * for more details. * * * ****************************************************************************/ +#ifndef __VCG_MESH +#error "This file should not be included alone. It is automatically included by complex.h" +#endif #ifndef __VCGLIB_TRIALLOCATOR #define __VCGLIB_TRIALLOCATOR -#include -#include -#include -#include - namespace vcg { namespace tri { @@ -36,40 +34,40 @@ namespace tri { @{ */ - template - size_t Index(MeshType &m, const typename MeshType::VertexType &v) {return &v-&*m.vert.begin();} - template - size_t Index(MeshType &m, const typename MeshType::FaceType &f) {return &f-&*m.face.begin();} - template - size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();} + template + size_t Index(MeshType &m, const typename MeshType::VertexType &v) {return &v-&*m.vert.begin();} + template + size_t Index(MeshType &m, const typename MeshType::FaceType &f) {return &f-&*m.face.begin();} + template + size_t Index(MeshType &m, const typename MeshType::EdgeType &e) {return &e-&*m.edge.begin();} + template + size_t Index(MeshType &m, const typename MeshType::HEdgeType &h) {return &h-&*m.hedge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} - template - size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();} - template - size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();} - template - size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} + template + size_t Index(MeshType &m, const typename MeshType::VertexType *vp) {return vp-&*m.vert.begin();} + template + size_t Index(MeshType &m, const typename MeshType::FaceType * fp) {return fp-&*m.face.begin();} + template + size_t Index(MeshType &m, const typename MeshType::EdgeType* e) {return e-&*m.edge.begin();} + template + size_t Index(MeshType &m, const typename MeshType::HEdgeType* h) {return h-&*m.hedge.begin();} - template - void ReorderAttribute(ATTR_CONT &c,std::vector & newVertIndex, MeshType & /* m */){ - typename std::set::iterator ai; - for(ai = c.begin(); ai != c.end(); ++ai) - ((typename MeshType::PointerToAttribute)(*ai)).Reorder(newVertIndex); - } + template + void ReorderAttribute(ATTR_CONT &c,std::vector & newVertIndex, MeshType & /* m */){ + typename std::set::iterator ai; + for(ai = c.begin(); ai != c.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Reorder(newVertIndex); + } - template - void ResizeAttribute(ATTR_CONT &c,const int & sz , MeshType &/*m*/){ - typename std::set::iterator ai; - for(ai =c.begin(); ai != c.end(); ++ai) - ((typename MeshType::PointerToAttribute)(*ai)).Resize(sz); - } + template + void ResizeAttribute(ATTR_CONT &c,const int & sz , MeshType &/*m*/){ + typename std::set::iterator ai; + for(ai =c.begin(); ai != c.end(); ++ai) + ((typename MeshType::PointerToAttribute)(*ai)).Resize(sz); + } - /*! - \brief Class to safely add and delete elements in a mesh. + /*! + \brief Class to safely add and delete elements in a mesh. Adding elements to a mesh, like faces and vertices can involve the reallocation of the vectors of the involved elements. This class provide the only safe methods to add elements. @@ -79,51 +77,51 @@ namespace tri { class Allocator { - public: - typedef typename MeshType::VertexType VertexType; - typedef typename MeshType::VertexPointer VertexPointer; - typedef typename MeshType::VertexIterator VertexIterator; - typedef typename MeshType::VertContainer VertContainer; + public: + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::VertexPointer VertexPointer; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::VertContainer VertContainer; - typedef typename MeshType::EdgeType EdgeType; - typedef typename MeshType::EdgePointer EdgePointer; - typedef typename MeshType::EdgeIterator EdgeIterator; - typedef typename MeshType::EdgeContainer EdgeContainer; + typedef typename MeshType::EdgeType EdgeType; + typedef typename MeshType::EdgePointer EdgePointer; + typedef typename MeshType::EdgeIterator EdgeIterator; + typedef typename MeshType::EdgeContainer EdgeContainer; - typedef typename MeshType::FaceType FaceType; - typedef typename MeshType::FacePointer FacePointer; - typedef typename MeshType::FaceIterator FaceIterator; - typedef typename MeshType::FaceContainer FaceContainer; + typedef typename MeshType::FaceType FaceType; + typedef typename MeshType::FacePointer FacePointer; + typedef typename MeshType::FaceIterator FaceIterator; + typedef typename MeshType::FaceContainer FaceContainer; - typedef typename MeshType::HEdgeType HEdgeType; - typedef typename MeshType::HEdgePointer HEdgePointer; - typedef typename MeshType::HEdgeIterator HEdgeIterator; - typedef typename MeshType::HEdgeContainer HEdgeContainer; + typedef typename MeshType::HEdgeType HEdgeType; + typedef typename MeshType::HEdgePointer HEdgePointer; + typedef typename MeshType::HEdgeIterator HEdgeIterator; + typedef typename MeshType::HEdgeContainer HEdgeContainer; - typedef typename MeshType::CoordType CoordType; + typedef typename MeshType::CoordType CoordType; - typedef typename MeshType::PointerToAttribute PointerToAttribute; - typedef typename std::set::iterator AttrIterator; - typedef typename std::set::const_iterator AttrConstIterator; - typedef typename std::set::iterator PAIte; + typedef typename MeshType::PointerToAttribute PointerToAttribute; + typedef typename std::set::iterator AttrIterator; + typedef typename std::set::const_iterator AttrConstIterator; + typedef typename std::set::iterator PAIte; - /*! - \brief Accessory class to update pointers after eventual reallocation caused by adding elements. + /*! + \brief Accessory class to update pointers after eventual reallocation caused by adding elements. - This class is used when allocating new vertexes and faces to update - the pointers that can be changed when resizing the involved vectors of vertex or faces. - It can also be used to prevent any update of the various mesh fields - (e.g. in case you are building all the connections by hand as in a importer); - \sa \ref allocation - */ - template - class PointerUpdater - { - public: - PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; } - void Clear(){newBase=oldBase=newEnd=oldEnd=0;} - /*! \brief Update a pointer to an element of a mesh after a reallocation + This class is used when allocating new vertexes and faces to update + the pointers that can be changed when resizing the involved vectors of vertex or faces. + It can also be used to prevent any update of the various mesh fields + (e.g. in case you are building all the connections by hand as in a importer); + \sa \ref allocation + */ + template + class PointerUpdater + { + public: + PointerUpdater(void) : newBase(0), oldBase(0), newEnd(0), oldEnd(0), preventUpdateFlag(false) { ; } + void Clear(){newBase=oldBase=newEnd=oldEnd=0;} + /*! \brief Update a pointer to an element of a mesh after a reallocation The updating is correctly done only if this PointerUpdater have been passed to the corresponing allocation call. \sa \ref allocation */ @@ -142,92 +140,92 @@ namespace tri { */ bool NeedUpdate() {if((oldBase && newBase!=oldBase && !preventUpdateFlag) || !remap.empty()) return true; else return false;} - SimplexPointerType newBase; - SimplexPointerType oldBase; - SimplexPointerType newEnd; - SimplexPointerType oldEnd; - std::vector remap; // this vector keep the new position of an element. Uninitialized elements have max_int value to denote an element that has not to be remapped. + SimplexPointerType newBase; + SimplexPointerType oldBase; + SimplexPointerType newEnd; + SimplexPointerType oldEnd; + std::vector remap; // this vector keep the new position of an element. Uninitialized elements have max_int value to denote an element that has not to be remapped. - bool preventUpdateFlag; /// when true no update is considered necessary. - }; + bool preventUpdateFlag; /// when true no update is considered necessary. + }; - /** \brief Add n vertices to the mesh. - Function to add n vertices to the mesh. - The elements are added always to the end of the vector. No attempt of reusing previously deleted element is done. - \sa PointerUpdater - \param m the mesh to be modified - \param n the number of elements to be added - \param pu a PointerUpdater initialized so that it can be used to update pointers to vertices that could have become invalid after this adding. - \retval the iterator to the first element added. - */ - static VertexIterator AddVertices(MeshType &m,int n, PointerUpdater &pu) - { - VertexIterator last; - if(n == 0) return m.vert.end(); - pu.Clear(); - if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element - else { - pu.oldBase=&*m.vert.begin(); - pu.oldEnd=&m.vert.back()+1; - } + /** \brief Add n vertices to the mesh. + Function to add n vertices to the mesh. + The elements are added always to the end of the vector. No attempt of reusing previously deleted element is done. + \sa PointerUpdater + \param m the mesh to be modified + \param n the number of elements to be added + \param pu a PointerUpdater initialized so that it can be used to update pointers to vertices that could have become invalid after this adding. + \retval the iterator to the first element added. + */ + static VertexIterator AddVertices(MeshType &m,int n, PointerUpdater &pu) + { + VertexIterator last; + if(n == 0) return m.vert.end(); + pu.Clear(); + if(m.vert.empty()) pu.oldBase=0; // if the vector is empty we cannot find the last valid element + else { + pu.oldBase=&*m.vert.begin(); + pu.oldEnd=&m.vert.back()+1; + } - m.vert.resize(m.vert.size()+n); - m.vn+=n; + m.vert.resize(m.vert.size()+n); + m.vn+=n; - typename std::set::iterator ai; - for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai) - ((PointerToAttribute)(*ai)).Resize(m.vert.size()); + typename std::set::iterator ai; + for(ai = m.vert_attr.begin(); ai != m.vert_attr.end(); ++ai) + ((PointerToAttribute)(*ai)).Resize(m.vert.size()); - pu.newBase = &*m.vert.begin(); - pu.newEnd = &m.vert.back()+1; - if(pu.NeedUpdate()) - { - for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) - if(!(*fi).IsD()) - for(int i=0; i < (*fi).VN(); ++i) - if ((*fi).cV(i)!=0) pu.Update((*fi).V(i)); + pu.newBase = &*m.vert.begin(); + pu.newEnd = &m.vert.back()+1; + if(pu.NeedUpdate()) + { + for (FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi) + if(!(*fi).IsD()) + for(int i=0; i < (*fi).VN(); ++i) + if ((*fi).cV(i)!=0) pu.Update((*fi).V(i)); - for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) - if(!(*ei).IsD()) - { - if(HasEVAdjacency (m)) { pu.Update((*ei).V(0)); pu.Update((*ei).V(1));} - // if(HasEVAdjacency(m)) pu.Update((*ei).EVp()); - } - HEdgeIterator hi; - for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi) - if(!(*hi).IsD()) - { - if(HasHVAdjacency (m)) - { - pu.Update((*hi).HVp()); - } - } + for (EdgeIterator ei=m.edge.begin(); ei!=m.edge.end(); ++ei) + if(!(*ei).IsD()) + { + if(HasEVAdjacency (m)) { pu.Update((*ei).V(0)); pu.Update((*ei).V(1));} + // if(HasEVAdjacency(m)) pu.Update((*ei).EVp()); + } + HEdgeIterator hi; + for (hi=m.hedge.begin(); hi!=m.hedge.end(); ++hi) + if(!(*hi).IsD()) + { + if(HasHVAdjacency (m)) + { + pu.Update((*hi).HVp()); + } + } - // e poiche' lo spazio e' cambiato si ricalcola anche last da zero - } - unsigned int siz=(unsigned int)m.vert.size()-n; + // e poiche' lo spazio e' cambiato si ricalcola anche last da zero + } + unsigned int siz=(unsigned int)m.vert.size()-n; - last = m.vert.begin(); - advance(last,siz); + last = m.vert.begin(); + advance(last,siz); - return last;// deve restituire l'iteratore alla prima faccia aggiunta; - } + return last;// deve restituire l'iteratore alla prima faccia aggiunta; + } - /** \brief Wrapper to AddVertices(); no PointerUpdater - */ - static VertexIterator AddVertices(MeshType &m, int n) - { - PointerUpdater pu; - return AddVertices(m, n,pu); - } + /** \brief Wrapper to AddVertices(); no PointerUpdater + */ + static VertexIterator AddVertices(MeshType &m, int n) + { + PointerUpdater pu; + return AddVertices(m, n,pu); + } - /** \brief Wrapper to AddVertices() no PointerUpdater but a vector of VertexPointer pointers to be updated - */ - static VertexIterator AddVertices(MeshType &m, int n, std::vector &local_vec) - { - PointerUpdater pu; - VertexIterator v_ret = AddVertices(m, n,pu); + /** \brief Wrapper to AddVertices() no PointerUpdater but a vector of VertexPointer pointers to be updated + */ + static VertexIterator AddVertices(MeshType &m, int n, std::vector &local_vec) + { + PointerUpdater pu; + VertexIterator v_ret = AddVertices(m, n,pu); typename std::vector::iterator vi; for(vi=local_vec.begin();vi!=local_vec.end();++vi) @@ -311,33 +309,33 @@ namespace tri { return last;// deve restituire l'iteratore alla prima faccia aggiunta; } - /** Function to add a single edge to the mesh. and initializing it with two VertexPointer - */ - static EdgeIterator AddEdge(MeshType &m, VertexPointer v0, VertexPointer v1) - { - EdgeIterator ei= AddEdges(m, 1); - ei->V(0)=v0; - ei->V(1)=v1; - return ei; - } + /** Function to add a single edge to the mesh. and initializing it with two VertexPointer + */ + static EdgeIterator AddEdge(MeshType &m, VertexPointer v0, VertexPointer v1) + { + EdgeIterator ei= AddEdges(m, 1); + ei->V(0)=v0; + ei->V(1)=v1; + return ei; + } - /** Function to add n edges to the mesh. - First wrapper, with no parameters - */ - static EdgeIterator AddEdges(MeshType &m, int n) - { - PointerUpdater pu; - return AddEdges(m, n,pu); - } + /** Function to add n edges to the mesh. + First wrapper, with no parameters + */ + static EdgeIterator AddEdges(MeshType &m, int n) + { + PointerUpdater pu; + return AddEdges(m, n,pu); + } - /** Function to add n edges to the mesh. - Second Wrapper, with a vector of vertex pointers to be updated. - */ - static EdgeIterator AddEdges(MeshType &m, int n, std::vector &local_vec) - { - PointerUpdater pu; - EdgeIterator v_ret = AddEdges(m, n,pu); + /** Function to add n edges to the mesh. + Second Wrapper, with a vector of vertex pointers to be updated. + */ + static EdgeIterator AddEdges(MeshType &m, int n, std::vector &local_vec) + { + PointerUpdater pu; + EdgeIterator v_ret = AddEdges(m, n,pu); typename std::vector::iterator ei; for(ei=local_vec.begin();ei!=local_vec.end();++ei) @@ -367,11 +365,11 @@ namespace tri { pu.oldEnd=&m.hedge.back()+1; } - m.hedge.resize(m.hedge.size()+n); - m.hn+=n; + m.hedge.resize(m.hedge.size()+n); + m.hn+=n; - pu.newBase = &*m.hedge.begin(); - pu.newEnd = &m.hedge.back()+1; + pu.newBase = &*m.hedge.begin(); + pu.newEnd = &m.hedge.back()+1; if(pu.NeedUpdate()) { @@ -420,69 +418,69 @@ namespace tri { } unsigned int siz = (unsigned int)m.hedge.size()-n; - last = m.hedge.begin(); - advance(last,siz); + last = m.hedge.begin(); + advance(last,siz); - return last;// deve restituire l'iteratore alla prima faccia aggiunta; - } + return last;// deve restituire l'iteratore alla prima faccia aggiunta; + } - /** Function to add n vertices to the mesh. - First wrapper, with no parameters - */ - static HEdgeIterator AddHEdges(MeshType &m, int n) - { - PointerUpdater pu; - return AddHEdges(m, n,pu); - } + /** Function to add n vertices to the mesh. + First wrapper, with no parameters + */ + static HEdgeIterator AddHEdges(MeshType &m, int n) + { + PointerUpdater pu; + return AddHEdges(m, n,pu); + } - /** Function to add n vertices to the mesh. - Second Wrapper, with a vector of vertex pointers to be updated. - */ - static HEdgeIterator AddHEdges(MeshType &m, int n, std::vector &local_vec) - { - PointerUpdater pu; - HEdgeIterator v_ret = AddHEdges(m, n,pu); + /** Function to add n vertices to the mesh. + Second Wrapper, with a vector of vertex pointers to be updated. + */ + static HEdgeIterator AddHEdges(MeshType &m, int n, std::vector &local_vec) + { + PointerUpdater pu; + HEdgeIterator v_ret = AddHEdges(m, n,pu); - typename std::vector::iterator ei; - for(ei=local_vec.begin();ei!=local_vec.end();++ei) - pu.Update(**ei); - return v_ret; - } + typename std::vector::iterator ei; + for(ei=local_vec.begin();ei!=local_vec.end();++ei) + pu.Update(**ei); + return v_ret; + } - /** Function to add a face to the mesh and initializing it with the three given VertexPointers - First wrapper, with no parameters - */ - static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2) - { - assert(m.vert.size()>0); - assert(v0>=&m.vert.front() && v0<=&m.vert.back()); - assert(v1>=&m.vert.front() && v1<=&m.vert.back()); - assert(v2>=&m.vert.front() && v2<=&m.vert.back()); - PointerUpdater pu; - FaceIterator fi = AddFaces(m,1,pu); - fi->V(0)=v0; - fi->V(1)=v1; - fi->V(2)=v2; - return fi; - } + /** Function to add a face to the mesh and initializing it with the three given VertexPointers + First wrapper, with no parameters + */ + static FaceIterator AddFace(MeshType &m, VertexPointer v0, VertexPointer v1, VertexPointer v2) + { + assert(m.vert.size()>0); + assert(v0>=&m.vert.front() && v0<=&m.vert.back()); + assert(v1>=&m.vert.front() && v1<=&m.vert.back()); + assert(v2>=&m.vert.front() && v2<=&m.vert.back()); + PointerUpdater pu; + FaceIterator fi = AddFaces(m,1,pu); + fi->V(0)=v0; + fi->V(1)=v1; + fi->V(2)=v2; + return fi; + } - /** Function to add n faces to the mesh. - First wrapper, with no parameters - */ - static FaceIterator AddFaces(MeshType &m, int n) - { - PointerUpdater pu; - return AddFaces(m,n,pu); - } + /** Function to add n faces to the mesh. + First wrapper, with no parameters + */ + static FaceIterator AddFaces(MeshType &m, int n) + { + PointerUpdater pu; + return AddFaces(m,n,pu); + } - /** Function to add n faces to the mesh. - Second Wrapper, with a vector of face pointer to be updated. - */ - static FaceIterator AddFaces(MeshType &m, int n,std::vector &local_vec) - { - PointerUpdater pu; - FaceIterator f_ret= AddFaces(m,n,pu); + /** Function to add n faces to the mesh. + Second Wrapper, with a vector of face pointer to be updated. + */ + static FaceIterator AddFaces(MeshType &m, int n,std::vector &local_vec) + { + PointerUpdater pu; + FaceIterator f_ret= AddFaces(m,n,pu); typename std::vector::iterator fi; for(fi=local_vec.begin();fi!=local_vec.end();++fi) @@ -507,249 +505,249 @@ namespace tri { last=m.face.end(); } - m.face.resize(m.face.size()+n); - m.fn+=n; + m.face.resize(m.face.size()+n); + m.fn+=n; - typename std::set::iterator ai; - for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) - ((PointerToAttribute)(*ai)).Resize(m.face.size()); + typename std::set::iterator ai; + for(ai = m.face_attr.begin(); ai != m.face_attr.end(); ++ai) + ((PointerToAttribute)(*ai)).Resize(m.face.size()); - pu.newBase = &*m.face.begin(); - pu.newEnd = &m.face.back()+1; + pu.newBase = &*m.face.begin(); + pu.newEnd = &m.face.back()+1; - if(pu.NeedUpdate()) - { - int ii = 0; - FaceIterator fi = m.face.begin(); - while(ii= &m.face.front() && &f <= &m.face.back()); - assert(!f.IsD()); - f.SetD(); - --m.fn; - } + /** Function to delete a face from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE FN + */ + static void DeleteFace(MeshType &m, FaceType &f) + { + assert(&f >= &m.face.front() && &f <= &m.face.back()); + assert(!f.IsD()); + f.SetD(); + --m.fn; + } - /** Function to delete a vertex from the mesh. - NOTE: THIS FUNCTION ALSO UPDATE vn - */ - static void DeleteVertex(MeshType &m, VertexType &v) - { - assert(&v >= &m.vert.front() && &v <= &m.vert.back()); - assert(!v.IsD()); - v.SetD(); - --m.vn; - } + /** Function to delete a vertex from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE vn + */ + static void DeleteVertex(MeshType &m, VertexType &v) + { + assert(&v >= &m.vert.front() && &v <= &m.vert.back()); + assert(!v.IsD()); + v.SetD(); + --m.vn; + } - /** Function to delete an edge from the mesh. - NOTE: THIS FUNCTION ALSO UPDATE en - */ - static void DeleteEdge(MeshType &m, EdgeType &e) - { - assert(&e >= &m.edge.front() && &e <= &m.edge.back()); - assert(!e.IsD()); - e.SetD(); - --m.en; - } + /** Function to delete an edge from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE en + */ + static void DeleteEdge(MeshType &m, EdgeType &e) + { + assert(&e >= &m.edge.front() && &e <= &m.edge.back()); + assert(!e.IsD()); + e.SetD(); + --m.en; + } - /** Function to delete a hedge from the mesh. - NOTE: THIS FUNCTION ALSO UPDATE en - */ - static void DeleteHEdge(MeshType &m, HEdgeType &h) - { - assert(!h.IsD()); - h.SetD(); - --m.hn; - } + /** Function to delete a hedge from the mesh. + NOTE: THIS FUNCTION ALSO UPDATE en + */ + static void DeleteHEdge(MeshType &m, HEdgeType &h) + { + assert(!h.IsD()); + h.SetD(); + --m.hn; + } - /* - Function to rearrange the vertex vector according to a given index permutation - the permutation is vector such that after calling this function + /* + Function to rearrange the vertex vector according to a given index permutation + the permutation is vector such that after calling this function - m.vert[ newVertIndex[i] ] = m.vert[i]; + m.vert[ newVertIndex[i] ] = m.vert[i]; - e.g. newVertIndex[i] is the new index of the vertex i + e.g. newVertIndex[i] is the new index of the vertex i - */ - static void PermutateVertexVector(MeshType &m, PointerUpdater &pu) - { - if(m.vert.empty()) return; - for(unsigned int i=0;i &pu) + { + if(m.vert.empty()) return; + for(unsigned int i=0;i &pu ) - { - // If already compacted fast return please! - if(m.vn==(int)m.vert.size()) return; + \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) + */ + static void CompactVertexVector( MeshType &m, PointerUpdater &pu ) + { + // If already compacted fast return please! + if(m.vn==(int)m.vert.size()) return; - // newVertIndex [ ] gives you the new position of the vertex in the vector; - pu.remap.resize( m.vert.size(),std::numeric_limits::max() ); + // newVertIndex [ ] gives you the new position of the vertex in the vector; + pu.remap.resize( m.vert.size(),std::numeric_limits::max() ); - size_t pos=0; - size_t i=0; + size_t pos=0; + size_t i=0; - for(i=0;i pu; - CompactVertexVector(m,pu); - } + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactVertexVector( MeshType &m ) { + PointerUpdater pu; + CompactVertexVector(m,pu); + } - /*! - \brief Compact vector of edges removing deleted elements. + /*! + \brief Compact vector of edges removing deleted elements. - Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) - After calling this function the \c IsD() test in the scanning a vector, is no more necessary. + Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) + After calling this function the \c IsD() test in the scanning a vector, is no more necessary. - \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) - */ - static void CompactEdgeVector( MeshType &m, PointerUpdater &pu ) - { - // If already compacted fast return please! - if(m.en==(int)m.edge.size()) return; + \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) + */ + static void CompactEdgeVector( MeshType &m, PointerUpdater &pu ) + { + // If already compacted fast return please! + if(m.en==(int)m.edge.size()) return; // remap [ ] gives you the new position of the edge in the vector; pu.remap.resize( m.edge.size(),std::numeric_limits::max() ); @@ -836,156 +834,156 @@ namespace tri { CompactEdgeVector(m,pu); } - /*! - \brief Compact vector of faces removing deleted elements. + /*! + \brief Compact vector of faces removing deleted elements. - Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) - Immediately after calling this function the \c IsD() test during the scanning a vector, is no more necessary. - \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) - */ - static void CompactFaceVector( MeshType &m, PointerUpdater &pu ) - { - // If already compacted fast return please! - if(m.fn==(int)m.face.size()) return; + Deleted elements are put to the end of the vector and the vector is resized. Order between elements is preserved but not their position (hence the PointerUpdater) + Immediately after calling this function the \c IsD() test during the scanning a vector, is no more necessary. + \warning It should not be called when TemporaryData is active (but works correctly if attributes are present) + */ + static void CompactFaceVector( MeshType &m, PointerUpdater &pu ) + { + // If already compacted fast return please! + if(m.fn==(int)m.face.size()) return; - // newFaceIndex [ ] gives you the new position of the face in the vector; - pu.remap.resize( m.face.size(),std::numeric_limits::max() ); + // newFaceIndex [ ] gives you the new position of the face in the vector; + pu.remap.resize( m.face.size(),std::numeric_limits::max() ); - size_t pos=0; - for(size_t i=0;i pu; - CompactFaceVector(m,pu); - } + /*! \brief Wrapper without the PointerUpdater. */ + static void CompactFaceVector( MeshType &m ) { + PointerUpdater pu; + CompactFaceVector(m,pu); + } public: - /*! \brief Check if an handle to a Per-Vertex Attribute is valid - */ - template - static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerVertexAttributeHandle & a){ - if(a._handle == NULL) return false; - for(AttrIterator i = m.vert_attr.begin(); i!=m.vert_attr.end();++i) - if ( (*i).n_attr == a.n_attr ) return true; - return false; - } + /*! \brief Check if an handle to a Per-Vertex Attribute is valid + */ + template + static + bool IsValidHandle( MeshType & m, const typename MeshType::template PerVertexAttributeHandle & a){ + if(a._handle == NULL) return false; + for(AttrIterator i = m.vert_attr.begin(); i!=m.vert_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } - /*! \brief Add a Per-Vertex Attribute of the given ATTR_TYPE with the given name. + /*! \brief Add a Per-Vertex Attribute of the given ATTR_TYPE with the given name. - No attribute with that name must exists (even of different type) - */ - template - static - typename MeshType::template PerVertexAttributeHandle - AddPerVertexAttribute( MeshType & m, std::string name){ - PAIte i; - PointerToAttribute h; - h._name = name; - if(!name.empty()){ - i = m.vert_attr.find(h); - assert(i ==m.vert_attr.end() );// an attribute with this name exists - } + No attribute with that name must exists (even of different type) + */ + template + static + typename MeshType::template PerVertexAttributeHandle + AddPerVertexAttribute( MeshType & m, std::string name){ + PAIte i; + PointerToAttribute h; + h._name = name; + if(!name.empty()){ + i = m.vert_attr.find(h); + assert(i ==m.vert_attr.end() );// an attribute with this name exists + } - h._sizeof = sizeof(ATTR_TYPE); - h._padding = 0; - h._handle = new SimpleTempData(m.vert); - m.attrn++; - h.n_attr = m.attrn; - std::pair < AttrIterator , bool> res = m.vert_attr.insert(h); - return typename MeshType::template PerVertexAttributeHandle(res.first->_handle,res.first->n_attr ); - } + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new SimpleTempData(m.vert); + m.attrn++; + h.n_attr = m.attrn; + std::pair < AttrIterator , bool> res = m.vert_attr.insert(h); + return typename MeshType::template PerVertexAttributeHandle(res.first->_handle,res.first->n_attr ); + } template static typename MeshType::template PerVertexAttributeHandle @@ -1010,32 +1008,32 @@ public: return AddPerVertexAttribute(m,name); } - /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE - \returns a invalid handle if no attribute with that name and type exists. - */ - template - static typename MeshType::template PerVertexAttributeHandle - FindPerVertexAttribute( MeshType & m, const std::string & name) - { - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set :: iterator i; + /*! \brief Try to retrieve an handle to an attribute with a given name and ATTR_TYPE + \returns a invalid handle if no attribute with that name and type exists. + */ + template + static typename MeshType::template PerVertexAttributeHandle + FindPerVertexAttribute( MeshType & m, const std::string & name) + { + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set :: iterator i; - i =m.vert_attr.find(h1); - if(i!=m.vert_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - if( (*i)._padding != 0 ){ - PointerToAttribute attr = (*i); // copy the PointerToAttribute - m.vert_attr.erase(i); // remove it from the set - FixPaddedPerVertexAttribute(m,attr); - std::pair new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute - assert(new_i.second); - i = new_i.first; - } - return typename MeshType::template PerVertexAttributeHandle((*i)._handle,(*i).n_attr); - } - return typename MeshType:: template PerVertexAttributeHandle(NULL,0); - } + i =m.vert_attr.find(h1); + if(i!=m.vert_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + if( (*i)._padding != 0 ){ + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.vert_attr.erase(i); // remove it from the set + FixPaddedPerVertexAttribute(m,attr); + std::pair new_i = m.vert_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerVertexAttributeHandle((*i)._handle,(*i).n_attr); + } + return typename MeshType:: template PerVertexAttributeHandle(NULL,0); + } /*! \brief query the mesh for all the attributes per vertex \returns the name of all attributes with a non-empy name. @@ -1081,45 +1079,45 @@ public: return;} } - // Generic DeleteAttribute. - // It must not crash if you try to delete a non existing attribute, - // because you do not have a way of asking for a handle of an attribute for which you do not know the type. - static - bool DeletePerVertexAttribute( MeshType & m, std::string name){ - AttrIterator i; - PointerToAttribute h1; h1._name = name; - i = m.vert_attr.find(h1); - if(i==m.vert_attr.end()) return false; - delete ((SimpleTempDataBase*)(*i)._handle); - m.vert_attr.erase(i); - return true; - } + // Generic DeleteAttribute. + // It must not crash if you try to delete a non existing attribute, + // because you do not have a way of asking for a handle of an attribute for which you do not know the type. + static + bool DeletePerVertexAttribute( MeshType & m, std::string name){ + AttrIterator i; + PointerToAttribute h1; h1._name = name; + i = m.vert_attr.find(h1); + if(i==m.vert_attr.end()) return false; + delete ((SimpleTempDataBase*)(*i)._handle); + m.vert_attr.erase(i); + return true; + } - /// Per Edge Attributes - template - static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerEdgeAttributeHandle & a){ - if(a._handle == NULL) return false; - for(AttrIterator i = m.edge_attr.begin(); i!=m.edge_attr.end();++i) - if ( (*i).n_attr == a.n_attr ) return true; - return false; - } + /// Per Edge Attributes + template + static + bool IsValidHandle( MeshType & m, const typename MeshType::template PerEdgeAttributeHandle & a){ + if(a._handle == NULL) return false; + for(AttrIterator i = m.edge_attr.begin(); i!=m.edge_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } - template - static - typename MeshType::template PerEdgeAttributeHandle - AddPerEdgeAttribute( MeshType & m, std::string name){ - PAIte i; - PointerToAttribute h; - h._name = name; - if(!name.empty()){ - i = m.edge_attr.find(h); - assert(i ==m.edge_attr.end() );// an attribute with this name exists - } - h._sizeof = sizeof(ATTR_TYPE); - h._padding = 0; + template + static + typename MeshType::template PerEdgeAttributeHandle + AddPerEdgeAttribute( MeshType & m, std::string name){ + PAIte i; + PointerToAttribute h; + h._name = name; + if(!name.empty()){ + i = m.edge_attr.find(h); + assert(i ==m.edge_attr.end() );// an attribute with this name exists + } + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; // h._typename = typeid(ATTR_TYPE).name(); h._handle = new SimpleTempData(m.edge); m.attrn++; @@ -1128,12 +1126,12 @@ public: return typename MeshType::template PerEdgeAttributeHandle(res.first->_handle,res.first->n_attr); } - template - static - typename MeshType::template PerEdgeAttributeHandle - AddPerEdgeAttribute( MeshType & m){ - return AddPerEdgeAttribute(m,std::string("")); - } + template + static + typename MeshType::template PerEdgeAttributeHandle + AddPerEdgeAttribute( MeshType & m){ + return AddPerEdgeAttribute(m,std::string("")); + } /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. @@ -1153,44 +1151,44 @@ public: } - template - static - typename MeshType::template PerEdgeAttributeHandle - FindPerEdgeAttribute( MeshType & m, const std::string & name){ - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set ::const_iterator i; + template + static + typename MeshType::template PerEdgeAttributeHandle + FindPerEdgeAttribute( MeshType & m, const std::string & name){ + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set ::const_iterator i; - i =m.edge_attr.find(h1); - if(i!=m.edge_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - if( (*i)._padding != 0 ){ - PointerToAttribute attr = (*i); // copy the PointerToAttribute - m.edge_attr.erase(i); // remove it from the set - FixPaddedPerEdgeAttribute(m,attr); - std::pair new_i = m.edge_attr.insert(attr); // insert the modified PointerToAttribute - assert(new_i.second); - i = new_i.first; - } - return typename MeshType::template PerEdgeAttributeHandle((*i)._handle,(*i).n_attr); - } + i =m.edge_attr.find(h1); + if(i!=m.edge_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + if( (*i)._padding != 0 ){ + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.edge_attr.erase(i); // remove it from the set + FixPaddedPerEdgeAttribute(m,attr); + std::pair new_i = m.edge_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerEdgeAttributeHandle((*i)._handle,(*i).n_attr); + } - return typename MeshType:: template PerEdgeAttributeHandle(NULL,0); - } + return typename MeshType:: template PerEdgeAttributeHandle(NULL,0); + } - template - static void GetAllPerEdgeAttribute(const MeshType & m, std::vector &all){ - all.clear(); - typename std::set :: const_iterator i; - for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i ) - if(!(*i)._name.empty()) - { - typename MeshType:: template PerEdgeAttributeHandle hh; - hh = Allocator:: template FindPerEdgeAttribute (m,(*i)._name); - if(IsValidHandle(m,hh)) - all.push_back((*i)._name); - } - } + template + static void GetAllPerEdgeAttribute(const MeshType & m, std::vector &all){ + all.clear(); + typename std::set :: const_iterator i; + for(i = m.edge_attr.begin(); i != m.edge_attr.end(); ++i ) + if(!(*i)._name.empty()) + { + typename MeshType:: template PerEdgeAttributeHandle hh; + hh = Allocator:: template FindPerEdgeAttribute (m,(*i)._name); + if(IsValidHandle(m,hh)) + all.push_back((*i)._name); + } + } /*! \brief If the per-edge attribute exists, delete it. */ @@ -1206,41 +1204,41 @@ public: return;} } - // Generic DeleteAttribute. - // It must not crash if you try to delete a non existing attribute, - // because you do not have a way of asking for a handle of an attribute for which you do not know the type. - static - bool DeletePerEdgeAttribute( MeshType & m, std::string name){ - AttrIterator i; - PointerToAttribute h1; h1._name = name; - i = m.edge_attr.find(h1); - if(i==m.edge_attr.end()) return false; - delete ((SimpleTempDataBase*)(*i)._handle); - m.edge_attr.erase(i); - return true; - } + // Generic DeleteAttribute. + // It must not crash if you try to delete a non existing attribute, + // because you do not have a way of asking for a handle of an attribute for which you do not know the type. + static + bool DeletePerEdgeAttribute( MeshType & m, std::string name){ + AttrIterator i; + PointerToAttribute h1; h1._name = name; + i = m.edge_attr.find(h1); + if(i==m.edge_attr.end()) return false; + delete ((SimpleTempDataBase*)(*i)._handle); + m.edge_attr.erase(i); + return true; + } - /// Per Face Attributes - template - static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerFaceAttributeHandle & a){ - if(a._handle == NULL) return false; - for(AttrIterator i = m.face_attr.begin(); i!=m.face_attr.end();++i) - if ( (*i).n_attr == a.n_attr ) return true; - return false; - } + /// Per Face Attributes + template + static + bool IsValidHandle( MeshType & m, const typename MeshType::template PerFaceAttributeHandle & a){ + if(a._handle == NULL) return false; + for(AttrIterator i = m.face_attr.begin(); i!=m.face_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } - template - static - typename MeshType::template PerFaceAttributeHandle - AddPerFaceAttribute( MeshType & m, std::string name){ - PAIte i; - PointerToAttribute h; - h._name = name; - if(!name.empty()){ - i = m.face_attr.find(h); - assert(i ==m.face_attr.end() );// an attribute with this name exists - } + template + static + typename MeshType::template PerFaceAttributeHandle + AddPerFaceAttribute( MeshType & m, std::string name){ + PAIte i; + PointerToAttribute h; + h._name = name; + if(!name.empty()){ + i = m.face_attr.find(h); + assert(i ==m.face_attr.end() );// an attribute with this name exists + } h._sizeof = sizeof(ATTR_TYPE); h._padding = 0; @@ -1251,12 +1249,12 @@ public: return typename MeshType::template PerFaceAttributeHandle(res.first->_handle,res.first->n_attr); } - template - static - typename MeshType::template PerFaceAttributeHandle - AddPerFaceAttribute( MeshType & m){ - return AddPerFaceAttribute(m,std::string("")); - } + template + static + typename MeshType::template PerFaceAttributeHandle + AddPerFaceAttribute( MeshType & m){ + return AddPerFaceAttribute(m,std::string("")); + } /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. @@ -1275,29 +1273,29 @@ public: return AddPerFaceAttribute(m,name); } - template - static - typename MeshType::template PerFaceAttributeHandle - FindPerFaceAttribute( MeshType & m, const std::string & name){ - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set ::iterator i; + template + static + typename MeshType::template PerFaceAttributeHandle + FindPerFaceAttribute( MeshType & m, const std::string & name){ + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set ::iterator i; - i =m.face_attr.find(h1); - if(i!=m.face_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - if( (*i)._padding != 0 ){ - PointerToAttribute attr = (*i); // copy the PointerToAttribute - m.face_attr.erase(i); // remove it from the set - FixPaddedPerFaceAttribute(m,attr); - std::pair new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute - assert(new_i.second); - i = new_i.first; - } - return typename MeshType::template PerFaceAttributeHandle((*i)._handle,(*i).n_attr); - } - return typename MeshType:: template PerFaceAttributeHandle(NULL,0); - } + i =m.face_attr.find(h1); + if(i!=m.face_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + if( (*i)._padding != 0 ){ + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.face_attr.erase(i); // remove it from the set + FixPaddedPerFaceAttribute(m,attr); + std::pair new_i = m.face_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } + return typename MeshType::template PerFaceAttributeHandle((*i)._handle,(*i).n_attr); + } + return typename MeshType:: template PerFaceAttributeHandle(NULL,0); + } template static void GetAllPerFaceAttribute(MeshType & m, std::vector &all){ @@ -1328,49 +1326,49 @@ public: } - // Generic DeleteAttribute. - // It must not crash if you try to delete a non existing attribute, - // because you do not have a way of asking for a handle of an attribute for which you do not know the type. - static - bool DeletePerFaceAttribute( MeshType & m, std::string name){ - AttrIterator i; - PointerToAttribute h1; h1._name = name; - i = m.face_attr.find(h1); - if(i==m.face_attr.end()) return false; - delete ((SimpleTempDataBase*)(*i)._handle); - m.face_attr.erase(i); - return true; - } + // Generic DeleteAttribute. + // It must not crash if you try to delete a non existing attribute, + // because you do not have a way of asking for a handle of an attribute for which you do not know the type. + static + bool DeletePerFaceAttribute( MeshType & m, std::string name){ + AttrIterator i; + PointerToAttribute h1; h1._name = name; + i = m.face_attr.find(h1); + if(i==m.face_attr.end()) return false; + delete ((SimpleTempDataBase*)(*i)._handle); + m.face_attr.erase(i); + return true; + } - /// Per Mesh Attributes - template - static - bool IsValidHandle( MeshType & m, const typename MeshType::template PerMeshAttributeHandle & a){ - if(a._handle == NULL) return false; - for(AttrIterator i = m.mesh_attr.begin(); i!=m.mesh_attr.end();++i) - if ( (*i).n_attr == a.n_attr ) return true; - return false; - } + /// Per Mesh Attributes + template + static + bool IsValidHandle( MeshType & m, const typename MeshType::template PerMeshAttributeHandle & a){ + if(a._handle == NULL) return false; + for(AttrIterator i = m.mesh_attr.begin(); i!=m.mesh_attr.end();++i) + if ( (*i).n_attr == a.n_attr ) return true; + return false; + } - template - static - typename MeshType::template PerMeshAttributeHandle - AddPerMeshAttribute( MeshType & m, std::string name){ - PAIte i; - PointerToAttribute h; - h._name = name; - if(!name.empty()){ - i = m.mesh_attr.find(h); - assert(i ==m.mesh_attr.end() );// an attribute with this name exists - } - h._sizeof = sizeof(ATTR_TYPE); - h._padding = 0; - h._handle = new Attribute(); - m.attrn++; - h.n_attr = m.attrn; - std::pair < AttrIterator , bool> res = m.mesh_attr.insert(h); - return typename MeshType::template PerMeshAttributeHandle(res.first->_handle,res.first->n_attr); - } + template + static + typename MeshType::template PerMeshAttributeHandle + AddPerMeshAttribute( MeshType & m, std::string name){ + PAIte i; + PointerToAttribute h; + h._name = name; + if(!name.empty()){ + i = m.mesh_attr.find(h); + assert(i ==m.mesh_attr.end() );// an attribute with this name exists + } + h._sizeof = sizeof(ATTR_TYPE); + h._padding = 0; + h._handle = new Attribute(); + m.attrn++; + h.n_attr = m.attrn; + std::pair < AttrIterator , bool> res = m.mesh_attr.insert(h); + return typename MeshType::template PerMeshAttributeHandle(res.first->_handle,res.first->n_attr); + } /*! \brief gives a handle to a per-edge attribute with a given name and ATTR_TYPE \returns a valid handle. If the name is not empty and an attribute with that name and type exists returns a handle to it. @@ -1389,39 +1387,39 @@ public: return AddPerMeshAttribute(m,name); } - template - static - typename MeshType::template PerMeshAttributeHandle - FindPerMeshAttribute( MeshType & m, const std::string & name){ - assert(!name.empty()); - PointerToAttribute h1; h1._name = name; - typename std::set ::iterator i; + template + static + typename MeshType::template PerMeshAttributeHandle + FindPerMeshAttribute( MeshType & m, const std::string & name){ + assert(!name.empty()); + PointerToAttribute h1; h1._name = name; + typename std::set ::iterator i; - i =m.mesh_attr.find(h1); - if(i!=m.mesh_attr.end()) - if((*i)._sizeof == sizeof(ATTR_TYPE) ){ - if( (*i)._padding != 0 ){ - PointerToAttribute attr = (*i); // copy the PointerToAttribute - m.mesh_attr.erase(i); // remove it from the set - FixPaddedPerMeshAttribute(m,attr); - std::pair new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute - assert(new_i.second); - i = new_i.first; - } + i =m.mesh_attr.find(h1); + if(i!=m.mesh_attr.end()) + if((*i)._sizeof == sizeof(ATTR_TYPE) ){ + if( (*i)._padding != 0 ){ + PointerToAttribute attr = (*i); // copy the PointerToAttribute + m.mesh_attr.erase(i); // remove it from the set + FixPaddedPerMeshAttribute(m,attr); + std::pair new_i = m.mesh_attr.insert(attr); // insert the modified PointerToAttribute + assert(new_i.second); + i = new_i.first; + } - return typename MeshType::template PerMeshAttributeHandle((*i)._handle,(*i).n_attr); - } + return typename MeshType::template PerMeshAttributeHandle((*i)._handle,(*i).n_attr); + } - return typename MeshType:: template PerMeshAttributeHandle(NULL,0); - } + return typename MeshType:: template PerMeshAttributeHandle(NULL,0); + } - template - static void GetAllPerMeshAttribute(const MeshType & m, std::vector &all){ - typename std::set :: iterator i; - for(i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i ) - if((*i)._sizeof == sizeof(ATTR_TYPE)) - all.push_back((*i)._name); - } + template + static void GetAllPerMeshAttribute(const MeshType & m, std::vector &all){ + typename std::set :: iterator i; + for(i = m.mesh_attr.begin(); i != m.mesh_attr.end(); ++i ) + if((*i)._sizeof == sizeof(ATTR_TYPE)) + all.push_back((*i)._name); + } /*! \brief If the per-mesh attribute exists, delete it. */ @@ -1437,134 +1435,134 @@ public: return;} } - static - void DeletePerMeshAttribute( MeshType & m, std::string name){ - AttrIterator i; - PointerToAttribute h1; h1._name = name; - i = m.mesh_attr.find(h1); - assert(i!=m.mesh_attr.end()); - delete ((SimpleTempDataBase *)(*i)._handle); - m.mesh_attr.erase(i); - } + static + void DeletePerMeshAttribute( MeshType & m, std::string name){ + AttrIterator i; + PointerToAttribute h1; h1._name = name; + i = m.mesh_attr.find(h1); + assert(i!=m.mesh_attr.end()); + delete ((SimpleTempDataBase *)(*i)._handle); + m.mesh_attr.erase(i); + } - template - static - void FixPaddedPerVertexAttribute (MeshType & m, PointerToAttribute & pa){ + template + static + void FixPaddedPerVertexAttribute (MeshType & m, PointerToAttribute & pa){ - // create the container of the right type - SimpleTempData* _handle = new SimpleTempData(m.vert); + // create the container of the right type + SimpleTempData* _handle = new SimpleTempData(m.vert); - // copy the padded container in the new one - _handle->Resize(m.vert.size()); - for(unsigned int i = 0; i < m.vert.size(); ++i){ - ATTR_TYPE * dest = &(*_handle)[i]; - char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); - } + // copy the padded container in the new one + _handle->Resize(m.vert.size()); + for(unsigned int i = 0; i < m.vert.size(); ++i){ + ATTR_TYPE * dest = &(*_handle)[i]; + char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void*)dest , + (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + } - // remove the padded container - delete ((SimpleTempDataBase*) pa._handle); + // remove the padded container + delete ((SimpleTempDataBase*) pa._handle); - // update the pointer to data - pa._sizeof = sizeof(ATTR_TYPE); + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); - // update the pointer to data - pa._handle = _handle; + // update the pointer to data + pa._handle = _handle; - // zero the padding - pa._padding = 0; - } - template - static - void FixPaddedPerEdgeAttribute (MeshType & m, PointerToAttribute & pa){ + // zero the padding + pa._padding = 0; + } + template + static + void FixPaddedPerEdgeAttribute (MeshType & m, PointerToAttribute & pa){ - // create the container of the right type - SimpleTempData* _handle = new SimpleTempData(m.edge); + // create the container of the right type + SimpleTempData* _handle = new SimpleTempData(m.edge); - // copy the padded container in the new one - _handle->Resize(m.edge.size()); - for(unsigned int i = 0; i < m.edge.size(); ++i){ - ATTR_TYPE * dest = &(*_handle)[i]; - char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); - } + // copy the padded container in the new one + _handle->Resize(m.edge.size()); + for(unsigned int i = 0; i < m.edge.size(); ++i){ + ATTR_TYPE * dest = &(*_handle)[i]; + char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void*)dest , + (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + } - // remove the padded container - delete ((SimpleTempDataBase*) pa._handle); + // remove the padded container + delete ((SimpleTempDataBase*) pa._handle); - // update the pointer to data - pa._sizeof = sizeof(ATTR_TYPE); + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); - // update the pointer to data - pa._handle = _handle; + // update the pointer to data + pa._handle = _handle; - // zero the padding - pa._padding = 0; - } + // zero the padding + pa._padding = 0; + } - template - static - void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){ + template + static + void FixPaddedPerFaceAttribute ( MeshType & m,PointerToAttribute & pa){ - // create the container of the right type - SimpleTempData* _handle = new SimpleTempData(m.face); + // create the container of the right type + SimpleTempData* _handle = new SimpleTempData(m.face); - // copy the padded container in the new one - _handle->Resize(m.face.size()); - for(unsigned int i = 0; i < m.face.size(); ++i){ - ATTR_TYPE * dest = &(*_handle)[i]; - char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); - memcpy((void*)dest , - (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); - } + // copy the padded container in the new one + _handle->Resize(m.face.size()); + for(unsigned int i = 0; i < m.face.size(); ++i){ + ATTR_TYPE * dest = &(*_handle)[i]; + char * ptr = (char*)( ((SimpleTempDataBase *)pa._handle)->DataBegin()); + memcpy((void*)dest , + (void*) &(ptr[i * pa._sizeof ]) ,sizeof(ATTR_TYPE)); + } // remove the padded container delete ((SimpleTempDataBase*) pa._handle); - // update the pointer to data - pa._sizeof = sizeof(ATTR_TYPE); + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); - // update the pointer to data - pa._handle = _handle; + // update the pointer to data + pa._handle = _handle; - // zero the padding - pa._padding = 0; - } + // zero the padding + pa._padding = 0; + } - template - static - void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){ + template + static + void FixPaddedPerMeshAttribute ( MeshType & /* m */,PointerToAttribute & pa){ - // create the container of the right type - Attribute * _handle = new Attribute(); + // create the container of the right type + Attribute * _handle = new Attribute(); // copy the padded container in the new one char * ptr = (char*)( ((Attribute *)pa._handle)->DataBegin()); memcpy((void*)_handle->attribute ,(void*) &(ptr[0]) ,sizeof(ATTR_TYPE)); - // remove the padded container - delete ( (Attribute *) pa._handle); + // remove the padded container + delete ( (Attribute *) pa._handle); - // update the pointer to data - pa._sizeof = sizeof(ATTR_TYPE); + // update the pointer to data + pa._sizeof = sizeof(ATTR_TYPE); - // update the pointer to data - pa._handle = _handle; + // update the pointer to data + pa._handle = _handle; - // zero the padding - pa._padding = 0; - } + // zero the padding + pa._padding = 0; + } }; // end class - /*@}*/ - } // End Namespace TriMesh + /*@}*/ + } // End Namespace TriMesh } // End Namespace vcg #endif diff --git a/vcg/complex/append.h b/vcg/complex/append.h index b313b785..418155f2 100644 --- a/vcg/complex/append.h +++ b/vcg/complex/append.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -24,10 +24,6 @@ #ifndef __VCGLIB_APPEND #define __VCGLIB_APPEND -#include -#include -#include - namespace vcg { namespace tri { /** \ingroup trimesh */ @@ -68,7 +64,7 @@ public: typedef typename ConstMeshRight::FacePointer FacePointerRight; struct Remap{ - std::vector vert,face,edge, hedge; + std::vector vert,face,edge, hedge; }; static void ImportVertexAdj(MeshLeft &ml, ConstMeshRight &mr, VertexLeft &vl, VertexRight &vr, Remap &remap ){ @@ -175,7 +171,7 @@ public: } // Append Right Mesh to the Left Mesh -// Append::Mesh(ml, mr) is equivalent to ml += mr. +// Append::Mesh(ml, mr) is equivalent to ml += mr. // Note MeshRigth could be costant... /*! \brief %Append the second mesh to the first one. @@ -316,60 +312,60 @@ static void Mesh(MeshLeft& ml, ConstMeshRight& mr, const bool selected = false, ImportHEdgeAdj(ml,mr,ml.hedge[remap.hedge[Index(mr,*hi)]],*hi,remap,selected); } - // phase 3. - // take care of other per mesh data: textures, attributes + // phase 3. + // take care of other per mesh data: textures, attributes - // At the end concatenate the vector with texture names. - ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); + // At the end concatenate the vector with texture names. + ml.textures.insert(ml.textures.end(),mr.textures.begin(),mr.textures.end()); - // Attributes. Copy only those attributes that are present in both meshes - // Two attributes in different meshes are considered the same if they have the same - // name and the same type. This may be deceiving because they could in fact have - // different semantic, but this is up to the developer. - // If the left mesh has attributes that are not in the right mesh, their values for the elements - // of the right mesh will be uninitialized + // Attributes. Copy only those attributes that are present in both meshes + // Two attributes in different meshes are considered the same if they have the same + // name and the same type. This may be deceiving because they could in fact have + // different semantic, but this is up to the developer. + // If the left mesh has attributes that are not in the right mesh, their values for the elements + // of the right mesh will be uninitialized - unsigned int id_r; - typename std::set< PointerToAttribute >::iterator al, ar; + unsigned int id_r; + typename std::set< PointerToAttribute >::iterator al, ar; - // per vertex attributes - for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.vert_attr.find(*al); - if(ar!= mr.vert_attr.end()){ - id_r = 0; - for(vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) - if( !(*vi).IsD() && (!selected || (*vi).IsS())) - memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r), - (*al)._handle->SizeOf()); - } - } + // per vertex attributes + for(al = ml.vert_attr.begin(); al != ml.vert_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.vert_attr.find(*al); + if(ar!= mr.vert_attr.end()){ + id_r = 0; + for(vi=mr.vert.begin();vi!=mr.vert.end();++vi,++id_r) + if( !(*vi).IsD() && (!selected || (*vi).IsS())) + memcpy((*al)._handle->At(remap.vert[Index(mr,*vi)]),(*ar)._handle->At(id_r), + (*al)._handle->SizeOf()); + } + } - // per edge attributes - for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.edge_attr.find(*al); - if(ar!= mr.edge_attr.end()){ - id_r = 0; - for(ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) - if( !(*ei).IsD() && (!selected || (*ei).IsS())) + // per edge attributes + for(al = ml.edge_attr.begin(); al != ml.edge_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.edge_attr.find(*al); + if(ar!= mr.edge_attr.end()){ + id_r = 0; + for(ei=mr.edge.begin();ei!=mr.edge.end();++ei,++id_r) + if( !(*ei).IsD() && (!selected || (*ei).IsS())) memcpy((*al)._handle->At(remap.edge[Index(mr,*ei)]),(*ar)._handle->At(id_r), - (*al)._handle->SizeOf()); - } - } + (*al)._handle->SizeOf()); + } + } - // per face attributes - for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al) - if(!(*al)._name.empty()){ - ar = mr.face_attr.find(*al); - if(ar!= mr.face_attr.end()){ - id_r = 0; - for(fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) - if( !(*fi).IsD() && (!selected || (*fi).IsS())) + // per face attributes + for(al = ml.face_attr.begin(); al != ml.face_attr.end(); ++al) + if(!(*al)._name.empty()){ + ar = mr.face_attr.find(*al); + if(ar!= mr.face_attr.end()){ + id_r = 0; + for(fi=mr.face.begin();fi!=mr.face.end();++fi,++id_r) + if( !(*fi).IsD() && (!selected || (*fi).IsS())) memcpy((*al)._handle->At(remap.face[Index(mr,*fi)]),(*ar)._handle->At(id_r), - (*al)._handle->SizeOf()); - } - } + (*al)._handle->SizeOf()); + } + } // per mesh attributes // if both ml and mr have an attribute with the same name, no action is done diff --git a/vcg/complex/complex.h b/vcg/complex/complex.h index 85d1a9ed..f60d341a 100644 --- a/vcg/complex/complex.h +++ b/vcg/complex/complex.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -21,21 +21,30 @@ * * ****************************************************************************/ -#ifndef __VCG_MESH +#ifndef __VCG_MESH_H +#define __VCG_MESH_H #define __VCG_MESH #include #include #include #include -#include - +#include +#include +#include +#include +#include +#include +#include #include #include #include #include #include +#include +#include #include +#undef __VCG_MESH #endif