From dbfaf2b8e1ff6a01db137b7cc56dbaab55f15c04 Mon Sep 17 00:00:00 2001 From: untereiner Date: Thu, 10 Nov 2011 14:45:29 +0100 Subject: [PATCH] osterputz algos 3maps finished --- include/Algo/ImplicitHierarchicalMesh/ihm3.h | 3 - include/Algo/Modelisation/subdivision.h | 256 --------- include/Algo/Modelisation/subdivision.hpp | 251 --------- .../{subdivision3map.h => subdivision3.h} | 13 +- include/Algo/Modelisation/subdivision3.hpp | 501 ++++++++++++++++++ include/Algo/Modelisation/subdivision3map.hpp | 271 ---------- .../{tetrahedron.h => tetrahedralization.h} | 17 +- ...tetrahedron.hpp => tetrahedralization.hpp} | 19 +- 8 files changed, 534 insertions(+), 797 deletions(-) rename include/Algo/Modelisation/{subdivision3map.h => subdivision3.h} (91%) create mode 100644 include/Algo/Modelisation/subdivision3.hpp delete mode 100644 include/Algo/Modelisation/subdivision3map.hpp rename include/Algo/Modelisation/{tetrahedron.h => tetrahedralization.h} (91%) rename include/Algo/Modelisation/{tetrahedron.hpp => tetrahedralization.hpp} (97%) diff --git a/include/Algo/ImplicitHierarchicalMesh/ihm3.h b/include/Algo/ImplicitHierarchicalMesh/ihm3.h index 226df980..cae49af9 100644 --- a/include/Algo/ImplicitHierarchicalMesh/ihm3.h +++ b/include/Algo/ImplicitHierarchicalMesh/ihm3.h @@ -25,9 +25,6 @@ #ifndef __IMPLICIT_HIERARCHICAL_MAP3__ #define __IMPLICIT_HIERARCHICAL_MAP3__ -//#include "Topology/map/map3.h" -//#include "Topology/generic/embeddedMap3.h" -//#include "Container/attributeContainer.h" #include "Topology/map/embeddedMap3.h" namespace CGoGN diff --git a/include/Algo/Modelisation/subdivision.h b/include/Algo/Modelisation/subdivision.h index 87aed95f..95b686d9 100644 --- a/include/Algo/Modelisation/subdivision.h +++ b/include/Algo/Modelisation/subdivision.h @@ -120,262 +120,6 @@ template void Sqrt3Subdivision(typename PFP::MAP& map, typename PFP::TVEC3& position, const FunctorSelect& selected = SelectorTrue()) ; - -/* - * volume subdivision scheme - */ - -template -void hexaCutVolume(typename PFP::MAP& map, Dart d, EMBV& attributs); - - -template -void splitVolumes(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); - - -// TODO a mettre ailleurs ? -// -///** -// * create a tetra based on the two triangles that have a common dart and phi2(dart) -// * return a new dart inside the tetra -// */ -//template -//Dart extractTetra(typename PFP::MAP& the_map, Dart d) -//{ -// -// -// Dart e = the_map.phi2(d); -// -// //create the new faces -// Dart dd = the_map.newFace(3); -// Dart ee = the_map.newFace(3); -// -// //update their sew -// the_map.sewFaces(dd,ee); -// the_map.sewFaces(the_map.phi3(dd),the_map.phi3(ee)); -// -// //add the two new faces in the mesh to obtain a tetra -// Dart s2d = the_map.phi2(the_map.phi_1(d)); -// the_map.unsewFaces(the_map.phi_1(d)); -// the_map.sewFaces(the_map.phi_1(d),the_map.phi_1(dd)); -// the_map.sewFaces(s2d,the_map.phi3(the_map.phi_1(dd))); -// -// Dart s2e = the_map.phi2(the_map.phi_1(e)); -// the_map.unsewFaces(the_map.phi_1(e)); -// the_map.sewFaces(the_map.phi_1(e),the_map.phi_1(ee)); -// the_map.sewFaces(s2e,the_map.phi3(the_map.phi_1(ee))); -// -// Dart ss2d = the_map.phi2(the_map.phi1(d)); -// the_map.unsewFaces(the_map.phi1(d)); -// the_map.sewFaces(the_map.phi1(d),the_map.phi1(ee)); -// the_map.sewFaces(ss2d,the_map.phi3(the_map.phi1(ee))); -// -// Dart ss2e = the_map.phi2(the_map.phi1(e)); -// the_map.unsewFaces(the_map.phi1(e)); -// the_map.sewFaces(the_map.phi1(e),the_map.phi1(dd)); -// the_map.sewFaces(ss2e,the_map.phi3(the_map.phi1(dd))); -// -// -// -// //embed the coords -// the_map.setVertexEmb(d,the_map.getVertexEmb(d)); -// the_map.setVertexEmb(e,the_map.getVertexEmb(e)); -// the_map.setVertexEmb(the_map.phi_1(d),the_map.getVertexEmb(the_map.phi_1(d))); -// the_map.setVertexEmb(the_map.phi_1(e),the_map.getVertexEmb(the_map.phi_1(e))); -// -// return dd; -//} -// -///** -// * tetrahedrization of the volume -// * @param the map -// * @param a dart of the volume -// * @param true if the faces are in CCW order -// * @return success of the tetrahedrization -// */ -//template -//bool smartVolumeTetrahedrization(typename PFP::MAP& the_map, Dart d, bool CCW=true) -//{ -// -// typedef typename PFP::EMB EMB; -// -// bool ret=true; -// -// if (!the_map.isTetrahedron(d)) -// { -// //only works on a 3-map -// assert(Dart::nbInvolutions()>=2 || "cannot be applied on this map, nbInvolutions must be at least 2"); -// -// if (Geometry::isConvex(the_map,d,CCW)) -// { -// the_map.tetrahedrizeVolume(d); -// } -// else -// { -// -// //get all the dart of the volume -// std::vector vStore; -// FunctorStore fs(vStore); -// the_map.foreach_dart_of_volume(d,fs); -// -// if (vStore.size()==0) -// { -// if (the_map.phi1(d)==d) -// CGoGNout << "plop" << CGoGNendl; -// if (the_map.phi2(d)==d) -// CGoGNout << "plip" << CGoGNendl; -// -// CGoGNout << the_map.getVertexEmb(d)->getPosition() << CGoGNendl; -// CGoGNout << "tiens tiens, c'est etrange" << CGoGNendl; -// } -// //prepare the list of embeddings of the current volume -// std::vector lstEmb; -// -// //get a marker -// DartMarker m(the_map); -// -// //all the darts from a vertex that can generate a tetra (3 adjacent faces) -// std::vector allowTetra; -// -// //all the darts that are not in otherTetra -// std::vector otherTetra; -// -// //for each dart of the volume -// for (typename std::vector::iterator it = vStore.begin() ; it != vStore.end() ; ++it ) -// { -// Dart e = *it; -// //if the vertex is not treated -// if (!m.isMarked(e)) -// { -// //store the embedding -// lstEmb.push_back(reinterpret_cast(the_map.getVertexEmb(e))); -// Dart ee=e; -// -// //count the number of adjacent faces and mark the darts -// int nbe=0; -// do -// { -// nbe++; -// m.markOrbit(DART,e); -// ee=the_map.phi1(the_map.phi2(ee)); -// } -// while (ee!=e); -// -// //if 3 adjacents faces, we can create a tetra on this vertex -// if (nbe==3) -// allowTetra.push_back(e); -// else -// otherTetra.push_back(e); -// } -// } -// -// //we haven't created a tetra yet -// bool decoupe=false; -// -// //if we have vertex that can be base -// if (allowTetra.size()!=0) -// { -// //foreach possible vertex while we haven't done any cut -// for (typename std::vector::iterator it=allowTetra.begin();it!=allowTetra.end() && !decoupe ;++it) -// { -// //get the dart -// Dart s=*it; -// //store the emb -// std::vector lstCurEmb; -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(s))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi1(s)))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(s)))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(the_map.phi2(s))))); -// -// //store the coords of the point -// gmtl::Vec3f points[4]; -// for (int i=0;i<4;++i) -// { -// points[i] = lstCurEmb[i]->getPosition(); -// } -// -// //test if the future tetra is well oriented (concave case) -// if (Geometry::isTetrahedronWellOriented(points,CCW)) -// { -// //test if we haven't any point inside the future tetra -// bool isEmpty=true; -// for (typename std::vector::iterator iter = lstEmb.begin() ; iter != lstEmb.end() && isEmpty ; ++iter) -// { -// //we don't test the vertex that composes the new tetra -// if (std::find(lstCurEmb.begin(),lstCurEmb.end(),*iter)==lstCurEmb.end()) -// { -// isEmpty = !Geometry::isPointInTetrahedron(points, (*iter)->getPosition(), CCW); -// } -// } -// -// //if no point inside the new tetra -// if (isEmpty) -// { -// //cut the spike to make a tet -// Dart dRes = the_map.cutSpike(*it); -// decoupe=true; -// //and continue with the rest of the volume -// ret = ret && smartVolumeTetrahedrization(the_map,the_map.phi3(dRes),CCW); -// } -// } -// } -// } -// -// if (!decoupe) -// { -// //foreach other vertex while we haven't done any cut -// for (typename std::vector::iterator it=otherTetra.begin();it!=otherTetra.end() && !decoupe ;++it) -// { -// //get the dart -// Dart s=*it; -// //store the emb -// std::vector lstCurEmb; -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(s))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi1(s)))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(s)))); -// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(the_map.phi2(s))))); -// -// //store the coords of the point -// gmtl::Vec3f points[4]; -// for (int i=0;i<4;++i) -// { -// points[i] = lstCurEmb[i]->getPosition(); -// } -// -// //test if the future tetra is well oriented (concave case) -// if (Geometry::isTetrahedronWellOriented(points,CCW)) -// { -// //test if we haven't any point inside the future tetra -// bool isEmpty=true; -// for (typename std::vector::iterator iter = lstEmb.begin() ; iter != lstEmb.end() && isEmpty ; ++iter) -// { -// //we don't test the vertex that composes the new tetra -// if (std::find(lstCurEmb.begin(),lstCurEmb.end(),*iter)==lstCurEmb.end()) -// { -// isEmpty = !Geometry::isPointInTetrahedron(points, (*iter)->getPosition(), CCW); -// } -// } -// -// //if no point inside the new tetra -// if (isEmpty) -// { -// //cut the spike to make a tet -// Dart dRes = extractTetra(the_map,*it); -// decoupe=true; -// //and continue with the rest of the volume -// smartVolumeTetrahedrization(the_map,the_map.phi3(dRes),CCW); -// } -// } -// } -// } -// -// if (!decoupe) -// ret=false; -// } -// } -// return ret; -//} - } // namespace Modelisation } // namespace Algo diff --git a/include/Algo/Modelisation/subdivision.hpp b/include/Algo/Modelisation/subdivision.hpp index 63fee21f..54c8b36b 100644 --- a/include/Algo/Modelisation/subdivision.hpp +++ b/include/Algo/Modelisation/subdivision.hpp @@ -645,257 +645,6 @@ void Sqrt3Subdivision(typename PFP::MAP& map, typename PFP::TVEC3& position, con } } - -template -void hexaCutVolume(typename PFP::MAP& map, Dart d, EMBV& attributs) -{ - DartMarker mf(map) ; //mark face - DartMarker me(map) ; //mark edge - - DartMarkerStore mark(map); // Lock a marker - - // compute volume centroid - EMB volCenter = Algo::Geometry::volumeCentroidGen(map, d, attributs); - - //Store faces that are traversed and start with the face of d - std::vector visitedFaces; - visitedFaces.reserve(100); - visitedFaces.push_back(d); - std::vector::iterator face; - - //Store the edges before the cutEdge - std::vector oldEdges; - oldEdges.reserve(100); - std::vector::iterator edge; - - //Store a dart from a each face - std::vector faces; - faces.reserve(100); - - //Store the darts from quadrangulated faces - std::vector quadfaces; - quadfaces.reserve(100); - - // First pass : for every face added to the list save a dart - for (face = visitedFaces.begin(); face != visitedFaces.end(); ++face) - { - if (!mark.isMarked(*face)) // Face has not been visited yet - { - - faces.push_back(*face); - - Dart dNext = *face ; - do - { - mark.mark(dNext); // Mark - oldEdges.push_back(dNext); - Dart adj = map.phi2(dNext); // Get adjacent face - if (adj != dNext && !mark.isMarked(adj)) - visitedFaces.push_back(adj); // Add it - dNext = map.phi1(dNext); - } while(dNext != *face); - } - } - - //Second pass : cut the edges && quadrangule the faces - for (face = faces.begin(); face != faces.end(); ++face) - { - Dart dNext = *face; - - //parcours de la face pour couper les aretes - do - { - Dart d = dNext; - dNext = map.phi1(dNext); - - if(!me.isMarked(d)) - { - Dart f = map.phi1(d); - map.cutEdge(d); - Dart e = map.phi1(d); - attributs[e] = attributs[d]; - attributs[e] += attributs[f]; - attributs[e] *= 0.5; - - me.markOrbit(EDGE, d); - me.markOrbit(EDGE, e); - } - - }while (dNext != *face); - - //quadrangulation - EMB center = Algo::Geometry::faceCentroidGen(map, *face, attributs); // compute center - Dart cf = Algo::Modelisation::quadranguleFace(map, *face); // quadrangule the face - attributs[cf] = center; // affect the data to the central vertex - - Dart e = cf; - do - { - quadfaces.push_back(e); - quadfaces.push_back(map.phi2(e)); - e = map.phi2(map.phi_1(e)); - }while (e != cf); - } - - DartMarker moe(map) ; //mark edge - - //Third pass : deconnect the corners - for (edge = oldEdges.begin(); edge != oldEdges.end(); ++edge) - { - - map.unsewFaces(map.phi1(*edge)); - moe.markOrbit(DART,map.phi1(*edge)); - } - - //Thourth pass : close the hole - for (edge = oldEdges.begin(); edge != oldEdges.end(); ++edge) - { - if(moe.isMarked(map.phi1(*edge))) - { - map.closeHole(map.phi1(*edge)); - moe.unmark(map.phi1(*edge)); - moe.unmark(map.phi1(map.phi2(map.phi_1(*edge)))); - moe.unmark(map.phi1(map.phi1(map.phi2(*edge)))); - - Dart cf = Algo::Modelisation::quadranguleFace(map, map.phi1(map.phi2(map.phi1(*edge)))); // quadrangule the face - attributs[cf] = volCenter; // affect the data to the central vertex - } - } - - moe.unmarkAll(); - - //Fifth pass : traversal to phi3 sewing - std::vector::iterator nvol; - for (nvol = quadfaces.begin(); nvol != quadfaces.end(); nvol = nvol + 2) - { - map.sewVolumes(map.phi2(*nvol), map.phi2(*(nvol+1))); - } - -// // Compute edge points -// for (edge = oldEdges.begin(); edge != oldEdges.end(); ++edge) -// { -// Dart x = *edge; -// // other side of the edge -// Dart y = map.phi2(x); -// if (y != x) -// { -// Dart f1 = map.phi_1(x); -// Dart f2 = map.phi2(map.phi1(y)); -// EMB temp = AttribOps::zero(); -// temp = attributs[f1]; -// temp += attributs[f2]; // E' = (V0+V1+F1+F2)/4 -// temp *= 0.25; -// attributs[x] *= 0.5; -// attributs[x] += temp; -// } -// // else nothing to do point already in the middle of segment -// } -// -// // Compute vertex points -// for (face = faces.begin(); face != faces.end(); ++face) -// { -// //m0.unmark(*face); -// -// EMB temp = AttribOps::zero(); -// EMB temp2 = AttribOps::zero(); -// -// unsigned int n = 0; -// Dart x = *face; -// do -// { -// Dart m = map.phi1(x); -// Dart f = map.phi2(m); -// Dart v = map.template phi<11>(f); -// -// temp += attributs[f]; -// temp2 += attributs[v]; -// -// ++n; -// x = map.alpha1(x); -// } while (x != *face); -// -// EMB emcp = attributs[*face]; -// emcp *= double((n-2)*n); // V' = (n-2)/n*V + 1/n2 *(F+E) -// emcp += temp; -// emcp += temp2; -// emcp /= double(n*n); -// -// attributs[*face] = emcp ; -// } -} - - -template -void splitVolumes(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position) -{ - //Cut the edges - DartMarker me(map, EDGE); - for(Dart d = map.begin(); d != map.end(); map.next(d)) - { - if(!me.isMarked(d)) - { - // Cut the edge - Dart dd = map.phi2(d) ; - typename PFP::VEC3 p1 = position[d] ; - typename PFP::VEC3 p2 = position[map.phi1(d)] ; - map.cutEdge(d) ; - - position[map.phi1(d)] = (p1 + p2) * typename PFP::REAL(0.5) ; - - me.markOrbit(EDGE, d); - me.markOrbit(EDGE, map.phi1(d)); - } - } - - DartMarker mf(map, FACE); - for(Dart d = map.begin(); d != map.end(); map.next(d)) - { - if(!mf.isMarked(d)) - { - - - mf.markOrbit(FACE, d); - } - } - - -// //and split the faces -// -// //Insert the middleFaces -// -// // first cut the edges (if they are not already) -// Dart t = d; -// do -// { -// if(!map.edgeIsSubdivided(map.phi1(map.phi2(t)))) -// Algo::IHM::subdivideEdge(map, map.phi1(map.phi2(t)), position) ; -// t = map.phi1(t); -// } -// while(t != d); -// -// Dart neighboordVolume = map.phi1(map.phi1(map.phi2(d))); -// -// //Split the faces and open the midlle -// do -// { -// Dart t2 = map.phi2(t); -// -// Dart face2 = map.phi1(map.phi1(t2)); -// map.splitFace(map.phi_1(t2), face2); -// map.unsewFaces(map.phi1(map.phi1(t2))); -// -// t = map.phi1(t); -// } -// while(t != d); -// -// -// map.closeHole(map.phi1(map.phi1(map.phi2(d)))); -// map.closeHole(map.phi_1(neighboordVolume)); -// map.sewVolumes(map.phi2(map.phi1(map.phi1(map.phi2(d)))), map.phi2(map.phi_1(neighboordVolume))); - -} - - } // namespace Modelisation } // namespace Algo diff --git a/include/Algo/Modelisation/subdivision3map.h b/include/Algo/Modelisation/subdivision3.h similarity index 91% rename from include/Algo/Modelisation/subdivision3map.h rename to include/Algo/Modelisation/subdivision3.h index 47dc04e0..739e8d86 100644 --- a/include/Algo/Modelisation/subdivision3map.h +++ b/include/Algo/Modelisation/subdivision3.h @@ -22,8 +22,8 @@ * * *******************************************************************************/ -#ifndef __SUBDIVISION3MAP_H__ -#define __SUBDIVISION3MAP_H__ +#ifndef __SUBDIVISION3_H__ +#define __SUBDIVISION3_H__ #include #include @@ -45,12 +45,7 @@ namespace Modelisation 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 @@ -74,7 +69,7 @@ void catmullClarkVol(typename PFP::MAP& map, typename PFP::TVEC3& position, cons } // namespace CGoGN -#include "Algo/Modelisation/subdivision3map.hpp" +#include "Algo/Modelisation/subdivision3.hpp" #endif diff --git a/include/Algo/Modelisation/subdivision3.hpp b/include/Algo/Modelisation/subdivision3.hpp new file mode 100644 index 00000000..d0bc78a3 --- /dev/null +++ b/include/Algo/Modelisation/subdivision3.hpp @@ -0,0 +1,501 @@ +/******************************************************************************* +* 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 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); + } + } + + // 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)) + { + std::cout << " d " << d << std::endl; + l_vertices.push_back(d); + mv.markOrbitInParent(VERTEX,d); + } + + //cut edges + if (selected(d) && !me.isMarked(d)) + { + Dart f = map.phi1(d); + map.cutEdge(d); + Dart e = map.phi1(d) ; + + 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); + } + } + + unsigned int nb_=0; + for(unsigned int nb= attributs.begin() ; nb != attributs.end() ; attributs.next(nb)) + nb_++; + + std::cout << "first " << nb_ << 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 + } + } + + //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)); + + 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)); + } + } + + nb_=0; + for(unsigned int nb= attributs.begin() ; nb != attributs.end() ; attributs.next(nb)) + nb_++; + + std::cout << "then " << nb_ << std::endl; + + map.check(); + + //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)); + } + } +} + +// +///** +// * create a tetra based on the two triangles that have a common dart and phi2(dart) +// * return a new dart inside the tetra +// */ +//template +//Dart extractTetra(typename PFP::MAP& the_map, Dart d) +//{ +// +// +// Dart e = the_map.phi2(d); +// +// //create the new faces +// Dart dd = the_map.newFace(3); +// Dart ee = the_map.newFace(3); +// +// //update their sew +// the_map.sewFaces(dd,ee); +// the_map.sewFaces(the_map.phi3(dd),the_map.phi3(ee)); +// +// //add the two new faces in the mesh to obtain a tetra +// Dart s2d = the_map.phi2(the_map.phi_1(d)); +// the_map.unsewFaces(the_map.phi_1(d)); +// the_map.sewFaces(the_map.phi_1(d),the_map.phi_1(dd)); +// the_map.sewFaces(s2d,the_map.phi3(the_map.phi_1(dd))); +// +// Dart s2e = the_map.phi2(the_map.phi_1(e)); +// the_map.unsewFaces(the_map.phi_1(e)); +// the_map.sewFaces(the_map.phi_1(e),the_map.phi_1(ee)); +// the_map.sewFaces(s2e,the_map.phi3(the_map.phi_1(ee))); +// +// Dart ss2d = the_map.phi2(the_map.phi1(d)); +// the_map.unsewFaces(the_map.phi1(d)); +// the_map.sewFaces(the_map.phi1(d),the_map.phi1(ee)); +// the_map.sewFaces(ss2d,the_map.phi3(the_map.phi1(ee))); +// +// Dart ss2e = the_map.phi2(the_map.phi1(e)); +// the_map.unsewFaces(the_map.phi1(e)); +// the_map.sewFaces(the_map.phi1(e),the_map.phi1(dd)); +// the_map.sewFaces(ss2e,the_map.phi3(the_map.phi1(dd))); +// +// +// +// //embed the coords +// the_map.setVertexEmb(d,the_map.getVertexEmb(d)); +// the_map.setVertexEmb(e,the_map.getVertexEmb(e)); +// the_map.setVertexEmb(the_map.phi_1(d),the_map.getVertexEmb(the_map.phi_1(d))); +// the_map.setVertexEmb(the_map.phi_1(e),the_map.getVertexEmb(the_map.phi_1(e))); +// +// return dd; +//} +// +///** +// * tetrahedrization of the volume +// * @param the map +// * @param a dart of the volume +// * @param true if the faces are in CCW order +// * @return success of the tetrahedrization +// */ +//template +//bool smartVolumeTetrahedrization(typename PFP::MAP& the_map, Dart d, bool CCW=true) +//{ +// +// typedef typename PFP::EMB EMB; +// +// bool ret=true; +// +// if (!the_map.isTetrahedron(d)) +// { +// //only works on a 3-map +// assert(Dart::nbInvolutions()>=2 || "cannot be applied on this map, nbInvolutions must be at least 2"); +// +// if (Geometry::isConvex(the_map,d,CCW)) +// { +// the_map.tetrahedrizeVolume(d); +// } +// else +// { +// +// //get all the dart of the volume +// std::vector vStore; +// FunctorStore fs(vStore); +// the_map.foreach_dart_of_volume(d,fs); +// +// if (vStore.size()==0) +// { +// if (the_map.phi1(d)==d) +// CGoGNout << "plop" << CGoGNendl; +// if (the_map.phi2(d)==d) +// CGoGNout << "plip" << CGoGNendl; +// +// CGoGNout << the_map.getVertexEmb(d)->getPosition() << CGoGNendl; +// CGoGNout << "tiens tiens, c'est etrange" << CGoGNendl; +// } +// //prepare the list of embeddings of the current volume +// std::vector lstEmb; +// +// //get a marker +// DartMarker m(the_map); +// +// //all the darts from a vertex that can generate a tetra (3 adjacent faces) +// std::vector allowTetra; +// +// //all the darts that are not in otherTetra +// std::vector otherTetra; +// +// //for each dart of the volume +// for (typename std::vector::iterator it = vStore.begin() ; it != vStore.end() ; ++it ) +// { +// Dart e = *it; +// //if the vertex is not treated +// if (!m.isMarked(e)) +// { +// //store the embedding +// lstEmb.push_back(reinterpret_cast(the_map.getVertexEmb(e))); +// Dart ee=e; +// +// //count the number of adjacent faces and mark the darts +// int nbe=0; +// do +// { +// nbe++; +// m.markOrbit(DART,e); +// ee=the_map.phi1(the_map.phi2(ee)); +// } +// while (ee!=e); +// +// //if 3 adjacents faces, we can create a tetra on this vertex +// if (nbe==3) +// allowTetra.push_back(e); +// else +// otherTetra.push_back(e); +// } +// } +// +// //we haven't created a tetra yet +// bool decoupe=false; +// +// //if we have vertex that can be base +// if (allowTetra.size()!=0) +// { +// //foreach possible vertex while we haven't done any cut +// for (typename std::vector::iterator it=allowTetra.begin();it!=allowTetra.end() && !decoupe ;++it) +// { +// //get the dart +// Dart s=*it; +// //store the emb +// std::vector lstCurEmb; +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(s))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi1(s)))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(s)))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(the_map.phi2(s))))); +// +// //store the coords of the point +// gmtl::Vec3f points[4]; +// for (int i=0;i<4;++i) +// { +// points[i] = lstCurEmb[i]->getPosition(); +// } +// +// //test if the future tetra is well oriented (concave case) +// if (Geometry::isTetrahedronWellOriented(points,CCW)) +// { +// //test if we haven't any point inside the future tetra +// bool isEmpty=true; +// for (typename std::vector::iterator iter = lstEmb.begin() ; iter != lstEmb.end() && isEmpty ; ++iter) +// { +// //we don't test the vertex that composes the new tetra +// if (std::find(lstCurEmb.begin(),lstCurEmb.end(),*iter)==lstCurEmb.end()) +// { +// isEmpty = !Geometry::isPointInTetrahedron(points, (*iter)->getPosition(), CCW); +// } +// } +// +// //if no point inside the new tetra +// if (isEmpty) +// { +// //cut the spike to make a tet +// Dart dRes = the_map.cutSpike(*it); +// decoupe=true; +// //and continue with the rest of the volume +// ret = ret && smartVolumeTetrahedrization(the_map,the_map.phi3(dRes),CCW); +// } +// } +// } +// } +// +// if (!decoupe) +// { +// //foreach other vertex while we haven't done any cut +// for (typename std::vector::iterator it=otherTetra.begin();it!=otherTetra.end() && !decoupe ;++it) +// { +// //get the dart +// Dart s=*it; +// //store the emb +// std::vector lstCurEmb; +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(s))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi1(s)))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(s)))); +// lstCurEmb.push_back(reinterpret_cast(the_map.getVertexEmb(the_map.phi_1(the_map.phi2(s))))); +// +// //store the coords of the point +// gmtl::Vec3f points[4]; +// for (int i=0;i<4;++i) +// { +// points[i] = lstCurEmb[i]->getPosition(); +// } +// +// //test if the future tetra is well oriented (concave case) +// if (Geometry::isTetrahedronWellOriented(points,CCW)) +// { +// //test if we haven't any point inside the future tetra +// bool isEmpty=true; +// for (typename std::vector::iterator iter = lstEmb.begin() ; iter != lstEmb.end() && isEmpty ; ++iter) +// { +// //we don't test the vertex that composes the new tetra +// if (std::find(lstCurEmb.begin(),lstCurEmb.end(),*iter)==lstCurEmb.end()) +// { +// isEmpty = !Geometry::isPointInTetrahedron(points, (*iter)->getPosition(), CCW); +// } +// } +// +// //if no point inside the new tetra +// if (isEmpty) +// { +// //cut the spike to make a tet +// Dart dRes = extractTetra(the_map,*it); +// decoupe=true; +// //and continue with the rest of the volume +// smartVolumeTetrahedrization(the_map,the_map.phi3(dRes),CCW); +// } +// } +// } +// } +// +// if (!decoupe) +// ret=false; +// } +// } +// return ret; +//} + +} //namespace Modelisation + +} //namespace Algo + +} //namespace CGoGN + + + diff --git a/include/Algo/Modelisation/subdivision3map.hpp b/include/Algo/Modelisation/subdivision3map.hpp deleted file mode 100644 index 660c0254..00000000 --- a/include/Algo/Modelisation/subdivision3map.hpp +++ /dev/null @@ -1,271 +0,0 @@ -/******************************************************************************* -* 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); - } - } - - // 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)) - { - std::cout << " d " << d << std::endl; - l_vertices.push_back(d); - mv.markOrbitInParent(VERTEX,d); - } - - //cut edges - if (selected(d) && !me.isMarked(d)) - { - Dart f = map.phi1(d); - map.cutEdge(d); - Dart e = map.phi1(d) ; - - 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); - } - } - - unsigned int nb_=0; - for(unsigned int nb= attributs.begin() ; nb != attributs.end() ; attributs.next(nb)) - nb_++; - - std::cout << "first " << nb_ << 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 - } - } - - //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)); - - 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)); - } - } - - nb_=0; - for(unsigned int nb= attributs.begin() ; nb != attributs.end() ; attributs.next(nb)) - nb_++; - - std::cout << "then " << nb_ << std::endl; - - map.check(); - - //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/Algo/Modelisation/tetrahedron.h b/include/Algo/Modelisation/tetrahedralization.h similarity index 91% rename from include/Algo/Modelisation/tetrahedron.h rename to include/Algo/Modelisation/tetrahedralization.h index ff6e9874..10cfa6eb 100644 --- a/include/Algo/Modelisation/tetrahedron.h +++ b/include/Algo/Modelisation/tetrahedralization.h @@ -22,8 +22,8 @@ * * *******************************************************************************/ -#ifndef __TETRAHEDRON_H__ -#define __TETRAHEDRON_H__ +#ifndef __TETRAHEDRALIZATION_H__ +#define __TETRAHEDRALIZATION_H__ namespace CGoGN { @@ -34,9 +34,16 @@ namespace Algo namespace Modelisation { -namespace Tetrahedron +namespace Tetrahedralization { +/** +* subdivide a hexahedron into 5 tetrahedron +* @param d dart of the hexahedron +*/ +template +void hexahedronToTetrahedron(typename PFP::MAP& map, Dart d); + /************************************************************************************************ * Tetrahedron functions * ************************************************************************************************/ @@ -116,12 +123,12 @@ template void edgeBisection(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position); -} //end namespace Tetrahedron +} //end namespace Tetrahedralization } //end namespace Modelisation } //end namespace Algo } //end namespace CGoGN -#include "Algo/Modelisation/tetrahedron.hpp" +#include "Algo/Modelisation/tetrahedralization.hpp" #endif diff --git a/include/Algo/Modelisation/tetrahedron.hpp b/include/Algo/Modelisation/tetrahedralization.hpp similarity index 97% rename from include/Algo/Modelisation/tetrahedron.hpp rename to include/Algo/Modelisation/tetrahedralization.hpp index 1bc6553d..22dc496a 100644 --- a/include/Algo/Modelisation/tetrahedron.hpp +++ b/include/Algo/Modelisation/tetrahedralization.hpp @@ -33,8 +33,23 @@ namespace Algo namespace Modelisation { -namespace Tetrahedron +namespace Tetrahedralization { + +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); +} + /************************************************************************************************ * Tetrahedron functions * ************************************************************************************************/ @@ -633,7 +648,7 @@ void edgeBisection(typename PFP::MAP& map, Dart d, typename PFP::TVEC3& position } -}//end namespace Tetrahedron +}//end namespace Tetrahedralization }//end namespace Modelisation }//end namespace Algo }//end namespace CGoGN -- GitLab