From 40d944d0a3cb56b00e1abd46baba2dc2ad506c76 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 23 Sep 2011 10:52:45 +0200 Subject: [PATCH] modif check 3-carte plongee, ajout catmull clark volumique --- include/Algo/Modelisation/subdivision3map.h | 81 ++++++ include/Algo/Modelisation/subdivision3map.hpp | 273 ++++++++++++++++++ include/Topology/generic/embeddedMap3.hpp | 82 ++++-- src/Topology/map/map3.cpp | 22 +- 4 files changed, 421 insertions(+), 37 deletions(-) create mode 100644 include/Algo/Modelisation/subdivision3map.h create mode 100644 include/Algo/Modelisation/subdivision3map.hpp diff --git a/include/Algo/Modelisation/subdivision3map.h b/include/Algo/Modelisation/subdivision3map.h new file mode 100644 index 00000000..47dc04e0 --- /dev/null +++ b/include/Algo/Modelisation/subdivision3map.h @@ -0,0 +1,81 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.u-strasbg.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#ifndef __SUBDIVISION3MAP_H__ +#define __SUBDIVISION3MAP_H__ + +#include +#include + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Modelisation +{ + +/** +* Cut a 3D ear from a mesh : the ear is sewn by phi3 to the rest of the volume +* @param d dart of the point of the ear +* @return a dart from the new face connecting the ear and the rest of the volume +*/ +template +Dart cut3Ear(typename PFP::MAP& map, Dart d); + +/** +* subdivide a hexahedron into 5 tetrahedron +* @param d dart of the hexahedron +*/ +template +void hexahedronToTetrahedron(typename PFP::MAP& map, Dart d); + +/** +* catmull clark volumic : do not move the original vertices +* @param map the map +* @param attributs geometric attributes of the vertices +* @param selected a functor to select volumes to subdivide +* TODO : test if it works for the functorselect +*/ +template +void catmullClarkVol(typename PFP::MAP& map, EMBV& attributs, const FunctorSelect& selected= SelectorTrue()); + +template +void catmullClarkVol(typename PFP::MAP& map, typename PFP::TVEC3& position, const FunctorSelect& selected= SelectorTrue()) +{ + catmullClarkVol(map, position, selected); +} + +} // namespace Modelisation + +} // namespace Algo + +} // namespace CGoGN + +#include "Algo/Modelisation/subdivision3map.hpp" + +#endif + + diff --git a/include/Algo/Modelisation/subdivision3map.hpp b/include/Algo/Modelisation/subdivision3map.hpp new file mode 100644 index 00000000..8e93d97e --- /dev/null +++ b/include/Algo/Modelisation/subdivision3map.hpp @@ -0,0 +1,273 @@ +/******************************************************************************* +* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps * +* version 0.1 * +* Copyright (C) 2009-2011, IGG Team, LSIIT, University of Strasbourg * +* * +* This library is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by the * +* Free Software Foundation; either version 2.1 of the License, or (at your * +* option) any later version. * +* * +* This library is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this library; if not, write to the Free Software Foundation, * +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* * +* Web site: http://cgogn.u-strasbg.fr/ * +* Contact information: cgogn@unistra.fr * +* * +*******************************************************************************/ + +#include "Algo/Geometry/centroid.h" +#include "Algo/Modelisation/subdivision.h" +#include "Algo/Modelisation/extrusion.h" + +namespace CGoGN +{ + +namespace Algo +{ + +namespace Modelisation +{ + +template +Dart cut3Ear(typename PFP::MAP& map, Dart d) +{ + Dart e=d; + int nb=0; + Dart dNew; + + Dart dRing; + Dart dRing2; + + //count the valence of the vertex + do + { + nb++; + e=map.phi1(map.phi2(e)); + } while (e!=d); + + if(nb<3) + { + CGoGNout << "Warning : cannot cut 2 volumes without creating a degenerated face " << CGoGNendl; + return d; + } + else + { + //triangulate around the vertex + do + { + Dart dN = map.phi1(map.phi2(e)); + if(map.template phi<111>(e)!=e) + map.splitFace(map.phi_1(e), map.phi1(e)); + + dRing = map.phi1(e); + dRing2 = map.phi2(dRing); + + map.unsewFaces(dRing); + + e= dN; + } while (e!=d); + + map.closeHole(dRing); + map.closeHole(dRing2); + map.sewVolumes(map.phi2(dRing),map.phi2(dRing2)); + } + + return map.phi2(dRing); +} + +template +void hexahedronToTetrahedron(typename PFP::MAP& map, Dart d) +{ + Dart d1 = d; + Dart d2 = map.phi1(map.phi1(d)); + Dart d3 = map.phi_1(map.phi2(d)); + Dart d4 = map.phi1(map.phi1(map.phi2(map.phi_1(d3)))); + + cut3Ear(map,d1); + cut3Ear(map,d2); + cut3Ear(map,d3); + cut3Ear(map,d4); +} + +template +void catmullClarkVol(typename PFP::MAP& map, EMBV& attributs, const FunctorSelect& selected) +{ + std::vector l_centers; + std::vector l_vertices; + + DartMarkerNoUnmark mv(map); + CellMarkerNoUnmark me(map, EDGE); + CellMarker mf(map, FACE); + + AutoAttributeHandler< EMB > attBary(map,VOLUME); + CellMarker vol(map,VOLUME); + + //pre-computation : compute the centroid of all volume + for (Dart d = map.begin(); d != map.end(); map.next(d)) + { + if(selected(d) && !vol.isMarked(d)) + { + vol.mark(d); + attBary[d] = Algo::Geometry::volumeCentroidGen(map,d,attributs); + } + } + + std::cout << "test" << std::endl; + +// mv.unmarkAll(); + + // first pass: cut edges + for (Dart d = map.begin(); d != map.end(); map.next(d)) + { + //memorize each vertices per volumes + if(selected(d) && !mv.isMarked(d)) + { + l_vertices.push_back(d); + Dart dd = d; + do { + mv.mark(dd); + dd = map.phi1(map.phi2(dd)); + } while(dd!=d); + } + + //cut edges + if (selected(d) && !me.isMarked(d)) + { + std::cout << "edge to cut " << d << std::endl; + std::cout << "edge degree " << map.edgeDegree(d) << std::endl; + + Dart f = map.phi1(d); + map.cutEdge(d); + Dart e = map.phi1(d) ; + std::cout << "cut cut cut " << std::endl; + + attributs[e] = attributs[d]; + attributs[e] += attributs[f]; + attributs[e] *= 0.5; + + me.mark(d); + me.mark(e); + + //mark new vertices + mv.markOrbit(VERTEX, e); + + Dart dd = d; + do + { + mf.mark(dd) ; + mf.mark(map.phi2(dd)); + dd = map.alpha2(dd); + } while(dd != d); + } + } + + std::cout << "edge cut" << std::endl; + + // second pass: quandrangule faces + std::map toSew; + for (Dart d = map.begin(); d != map.end(); map.next(d)) + { + mv.unmark(d); + + if (selected(d) && mf.isMarked(d)) // for each face not subdivided + { + mf.unmark(d); + // compute center skip darts of new vertices non embedded + EMB center = AttribOps::zero(); + unsigned int count = 0 ; + Dart it = d; + + do + { + me.unmark(it); + me.unmark(map.phi1(it)); + + center += attributs[it]; + ++count ; + + it = map.template phi<11>(it) ; + } while(it != d) ; + + center /= double(count); + + Dart cf = quadranguleFace(map, d); // quadrangule the face + attributs[cf] = center; // affect the data to the central vertex + } + } + + std::cout << "nb vertices " << l_vertices.size() << std::endl; + + //third pass : create the inner faces + for (std::vector::iterator it = l_vertices.begin(); it != l_vertices.end(); ++it) + { + Dart d = *it; + //unsew all around the vertex + //there are 2 links to unsew for each face around (-> quadrangulation) + do + { + Dart dN = map.phi1(map.phi2(d)); + + Dart dRing = map.phi1(d); + + if(map.phi2(dRing)!=dRing) + { + toSew.insert(std::pair(dRing,map.phi2(dRing))); + map.unsewFaces(dRing); + } + + dRing = map.phi1(dRing); + + if(map.phi2(dRing)!=dRing) + { + toSew.insert(std::pair(dRing,map.phi2(dRing))); + map.unsewFaces(dRing); + } + + d= dN; + } while (*it!=d); + + //close the generated hole and create the central vertex + unsigned int degree = map.closeHole(map.phi1(d)); + std::cout << "degree " << degree << std::endl; + + Dart dd = map.phi1(map.phi2(map.phi1(d))); + map.splitFace(map.phi_1(dd),map.phi1(dd)); + Dart dS = map.phi1(dd); + map.cutEdge(dS); + + attributs[map.phi1(dS)] = attBary[d]; + + //TODO : test with vertices with degree higher than 3 + for(unsigned int i=0; i < (degree/2)-2; ++i) + { + map.splitFace(map.phi2(dS),map.template phi<111>(map.phi2(dS))); + dS = map.template phi<111>(map.phi2(dS)); + } + } + + //sew all faces leading to the central vertex + for (std::map::iterator it = toSew.begin(); it != toSew.end(); ++it) + { + Dart dT = map.phi2(it->first); + if(dT==map.phi3(dT)) + { + map.sewVolumes(dT,map.phi2(it->second)); + } + } +} + +} //namespace Modelisation + +} //namespace Algo + +} //namespace CGoGN + + + diff --git a/include/Topology/generic/embeddedMap3.hpp b/include/Topology/generic/embeddedMap3.hpp index ba4fc9ac..8ff3b084 100644 --- a/include/Topology/generic/embeddedMap3.hpp +++ b/include/Topology/generic/embeddedMap3.hpp @@ -62,7 +62,10 @@ void EmbeddedMap3::sewVolumes(Dart d, Dart e) //embed the face orbit from the volume sewn if (MAP3::isOrbitEmbedded(FACE)) - MAP3::copyDartEmbedding(FACE, e, d) ; + { + unsigned int vEmb1 = MAP3::getEmbedding(FACE, d); + MAP3::embedOrbit(FACE, e, vEmb1) ; + } } template @@ -346,34 +349,61 @@ bool EmbeddedMap3::check() return false ; } - if(MAP3::phi3(d) != d && MAP3::getEmbedding(VERTEX, d) != MAP3::getEmbedding(VERTEX, MAP3::phi1(MAP3::phi3(d)))) - { - CGoGNout << "Check: different embeddings on vertex in the 2 oriented faces" << CGoGNendl ; - std::cout << "Dart #" << d << std::endl; - std::cout << "Emb(d) = " << MAP3::getEmbedding(VERTEX, d) << std::endl; - std::cout << "Emb(phi32(d)) = " << MAP3::getEmbedding(VERTEX, MAP3::phi3(MAP3::phi2(d))) << std::endl; - return false ; - } + if(MAP3::phi3(d) != d && MAP3::getEmbedding(VERTEX, d) != MAP3::getEmbedding(VERTEX, MAP3::phi1(MAP3::phi3(d)))) + { + CGoGNout << "Check: different embeddings on vertex in the 2 oriented faces" << CGoGNendl ; + CGoGNout << "Dart #" << d << CGoGNendl; + CGoGNout << "Emb(d) = " << MAP3::getEmbedding(VERTEX, d) << CGoGNendl; + CGoGNout << "Emb(phi32(d)) = " << MAP3::getEmbedding(VERTEX, MAP3::phi3(MAP3::phi2(d))) << CGoGNendl; + return false ; + } } -// if (MAP2::isOrbitEmbedded(EDGE)) -// { -// if (MAP2::getEmbedding(EDGE, d) != MAP2::getEmbedding(EDGE, MAP2::phi2(d))) -// { -// CGoGNout << "Check: different embeddings on edge" << CGoGNendl ; -// return false ; -// } -// } -// -// if (MAP2::isOrbitEmbedded(FACE)) -// { -// if (MAP2::getEmbedding(FACE, d) != MAP2::getEmbedding(FACE, MAP2::phi1(d))) -// { -// CGoGNout << "Check: different embeddings on face" << CGoGNendl ; -// return false ; -// } -// } + if (MAP3::isOrbitEmbedded(EDGE)) + { + if (MAP3::getEmbedding(EDGE, d) != MAP3::getEmbedding(EDGE, MAP3::phi2(d))) + { + CGoGNout << "Check: different embeddings on edge" << CGoGNendl ; + return false ; + } + + if (MAP3::getEmbedding(EDGE, d) != MAP3::getEmbedding(EDGE, MAP3::phi3(d))) + { + CGoGNout << "Check: different embeddings on edge" << CGoGNendl ; + return false ; + } + } + + if (MAP3::isOrbitEmbedded(FACE)) + { + if (MAP3::getEmbedding(FACE, d) != MAP3::getEmbedding(FACE, MAP3::phi1(d))) + { + CGoGNout << "Check: different embeddings on face" << CGoGNendl ; + return false ; + } + + if (MAP3::getEmbedding(FACE, d) != MAP3::getEmbedding(FACE, MAP3::phi3(d))) + { + CGoGNout << "Check: different embeddings on face" << CGoGNendl ; + return false ; + } + } + + if (MAP3::isOrbitEmbedded(VOLUME)) + { + if (MAP3::getEmbedding(VOLUME, d) != MAP3::getEmbedding(VOLUME, MAP3::phi1(d))) + { + CGoGNout << "Check: different embeddings in volume" << CGoGNendl ; + return false ; + } + + if (MAP3::getEmbedding(VOLUME, d) != MAP3::getEmbedding(VOLUME, MAP3::phi2(d))) + { + CGoGNout << "Check: different embeddings in volume" << CGoGNendl ; + return false ; + } + } } CGoGNout << "Check: embedding ok" << CGoGNendl ; return true ; diff --git a/src/Topology/map/map3.cpp b/src/Topology/map/map3.cpp index ce6813b5..3a7d71bf 100644 --- a/src/Topology/map/map3.cpp +++ b/src/Topology/map/map3.cpp @@ -635,15 +635,15 @@ unsigned int Map3::vertexDegree(Dart d) int count = 0; DartMarkerStore mv(*this); // Lock a marker - std::vector darts; //Darts that are traversed - darts.reserve(512); - darts.push_back(d); //Start with the dart d + std::list darts_list; //Darts that are traversed + darts_list.push_back(d); //Start with the dart d + std::list::iterator darts; mv.mark(d); - for(std::vector::iterator it = darts.begin(); it != darts.end() ; ++it) + for(darts = darts_list.begin(); darts != darts_list.end() ; ++darts) { - Dart dc = *it; + Dart dc = *darts; //add phi21 and phi23 successor if they are not marked yet Dart d2 = phi2(dc); @@ -652,27 +652,27 @@ unsigned int Map3::vertexDegree(Dart d) if(!mv.isMarked(d21)) { - darts.push_back(d21); + darts_list.push_back(d21); mv.mark(d21); } if((d23!=d2) && !mv.isMarked(d23)) { - darts.push_back(d23); + darts_list.push_back(d23); mv.mark(d23); } } - std::cout << "#darts = " << darts.size() << std::endl; + std::cout << "#darts = " << darts_list.size() << std::endl; DartMarkerStore me(*this); - for(std::vector::iterator it = darts.begin(); it != darts.end() ; ++it) + for(darts = darts_list.begin(); darts != darts_list.end() ; ++darts) { - if(!me.isMarked(*it)) + if(!me.isMarked(*darts)) { ++count; - me.markOrbit(EDGE, *it); + me.markOrbit(EDGE, *darts); } } -- GitLab